diff options
author | Stuart Broadfoot <gbroadfoot@hotmail.com> | 2012-12-28 18:21:30 +0400 |
---|---|---|
committer | Stuart Broadfoot <gbroadfoot@hotmail.com> | 2012-12-28 18:21:30 +0400 |
commit | e9ba345c46c93a193193f01d4bfac714a666d384 (patch) | |
tree | 49df9d78dc9327de642779e300e1592e5d7b3a42 /intern/cycles/bvh | |
parent | 857df8065face58eff5556953cdf2dd72e09f2b6 (diff) |
New feature
Patch [#33445] - Experimental Cycles Hair Rendering (CPU only)
This patch allows hair data to be exported to cycles and introduces a new line segment primitive to render with.
The UI appears under the particle tab and there is a new hair info node available.
It is only available under the experimental feature set and for cpu rendering.
Diffstat (limited to 'intern/cycles/bvh')
-rw-r--r-- | intern/cycles/bvh/bvh.cpp | 132 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh.h | 9 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh_build.cpp | 37 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh_build.h | 2 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh_params.h | 5 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh_sort.cpp | 2 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh_split.cpp | 55 |
7 files changed, 196 insertions, 46 deletions
diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp index b58a34f9942..102414e4a3d 100644 --- a/intern/cycles/bvh/bvh.cpp +++ b/intern/cycles/bvh/bvh.cpp @@ -75,6 +75,10 @@ bool BVH::cache_read(CacheData& key) foreach(Object *ob, objects) { key.add(ob->mesh->verts); key.add(ob->mesh->triangles); + key.add(ob->mesh->curve_keys); + key.add(ob->mesh->curve_keysCD); + key.add(ob->mesh->curve_segs); + key.add(ob->mesh->curve_attrib); key.add(&ob->bounds, sizeof(ob->bounds)); key.add(&ob->visibility, sizeof(ob->visibility)); key.add(&ob->mesh->transform_applied, sizeof(bool)); @@ -91,6 +95,7 @@ bool BVH::cache_read(CacheData& key) value.read(pack.nodes); value.read(pack.object_node); value.read(pack.tri_woop); + value.read(pack.prim_type); value.read(pack.prim_visibility); value.read(pack.prim_index); value.read(pack.prim_object); @@ -112,6 +117,7 @@ void BVH::cache_write(CacheData& key) value.add(pack.nodes); value.add(pack.object_node); value.add(pack.tri_woop); + value.add(pack.prim_type); value.add(pack.prim_visibility); value.add(pack.prim_index); value.add(pack.prim_object); @@ -157,10 +163,11 @@ void BVH::build(Progress& progress) } /* build nodes */ + vector<int> prim_type; vector<int> prim_index; vector<int> prim_object; - BVHBuild bvh_build(objects, prim_index, prim_object, params, progress); + BVHBuild bvh_build(objects, prim_type, prim_index, prim_object, params, progress); BVHNode *root = bvh_build.run(); if(progress.get_cancel()) { @@ -169,6 +176,7 @@ void BVH::build(Progress& progress) } /* todo: get rid of this copy */ + pack.prim_type = prim_type; pack.prim_index = prim_index; pack.prim_object = prim_object; @@ -182,8 +190,8 @@ void BVH::build(Progress& progress) } /* pack triangles */ - progress.set_substatus("Packing BVH triangles"); - pack_triangles(); + progress.set_substatus("Packing BVH triangles and strands"); + pack_primitives(); if(progress.get_cancel()) { root->deleteSubtree(); @@ -215,8 +223,8 @@ void BVH::build(Progress& progress) void BVH::refit(Progress& progress) { - progress.set_substatus("Packing BVH triangles"); - pack_triangles(); + progress.set_substatus("Packing BVH primitives"); + pack_primitives(); if(progress.get_cancel()) return; @@ -263,7 +271,50 @@ void BVH::pack_triangle(int idx, float4 woop[3]) } } -void BVH::pack_triangles() +/* Curves*/ + +void BVH::pack_curve_seg(int idx, float4 woop[3]) +{ + int tob = pack.prim_object[idx]; + const Mesh *mesh = objects[tob]->mesh; + int tidx = pack.prim_index[idx]; + float3 v0 = mesh->curve_keys[mesh->curve_segs[tidx].v[0]].loc; + float3 v1 = mesh->curve_keys[mesh->curve_segs[tidx].v[1]].loc; + float t0 = mesh->curve_keys[mesh->curve_segs[tidx].v[0]].time; + float t1 = mesh->curve_keys[mesh->curve_segs[tidx].v[1]].time; + + float3 d0 = v1 - v0; + float l = len(d0); + + float u = mesh->curve_attrib[mesh->curve_segs[tidx].curve].uv[0]; + float v = mesh->curve_attrib[mesh->curve_segs[tidx].curve].uv[1]; + + /*Plan + *Transform tfm = make_transform( + * location <3> , l, + * extra curve data <3> , StrID, + * nextkey, flags/tip?, r, t); + */ + float3 tg1 = make_float3(1.0f,0.0f,0.0f); + float3 tg2 = make_float3(1.0f,0.0f,0.0f); + if(mesh->curve_keysCD.size()) { + tg1 = mesh->curve_keysCD[mesh->curve_segs[tidx].v[0]].tg; + tg2 = mesh->curve_keysCD[mesh->curve_segs[tidx].v[1]].tg; + } + + Transform tfm = make_transform( + tg1.x, tg1.y, tg1.z, l, + tg2.x, tg2.y, tg2.z, 0, + t0, t1, u, v, + 0, 0, 0, 1); + + woop[0] = tfm.x; + woop[1] = tfm.y; + woop[2] = tfm.z; + +} + +void BVH::pack_primitives() { int nsize = TRI_NODE_SIZE; size_t tidx_size = pack.prim_index.size(); @@ -277,7 +328,11 @@ void BVH::pack_triangles() if(pack.prim_index[i] != -1) { float4 woop[3]; - pack_triangle(i, woop); + if(pack.prim_type[i]) + pack_curve_seg(i, woop); + else + pack_triangle(i, woop); + memcpy(&pack.tri_woop[i * nsize], woop, sizeof(float4)*3); int tob = pack.prim_object[i]; @@ -300,11 +355,15 @@ void BVH::pack_instances(size_t nodes_size) /* adjust primitive index to point to the triangle in the global array, for * meshes with transform applied and already in the top level BVH */ for(size_t i = 0; i < pack.prim_index.size(); i++) - if(pack.prim_index[i] != -1) - pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->tri_offset; + if(pack.prim_index[i] != -1) { + if(pack.prim_type[i]) + pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->curveseg_offset; + else + pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->tri_offset; + } /* track offsets of instanced BVH data in global array */ - size_t tri_offset = pack.prim_index.size(); + size_t prim_offset = pack.prim_index.size(); size_t nodes_offset = nodes_size; /* clear array that gives the node indexes for instanced objects */ @@ -339,6 +398,7 @@ void BVH::pack_instances(size_t nodes_size) mesh_map.clear(); pack.prim_index.resize(prim_index_size); + pack.prim_type.resize(prim_index_size); pack.prim_object.resize(prim_index_size); pack.prim_visibility.resize(prim_index_size); pack.tri_woop.resize(tri_woop_size); @@ -346,6 +406,7 @@ void BVH::pack_instances(size_t nodes_size) pack.object_node.resize(objects.size()); int *pack_prim_index = (pack.prim_index.size())? &pack.prim_index[0]: NULL; + int *pack_prim_type = (pack.prim_type.size())? &pack.prim_type[0]: NULL; int *pack_prim_object = (pack.prim_object.size())? &pack.prim_object[0]: NULL; uint *pack_prim_visibility = (pack.prim_visibility.size())? &pack.prim_visibility[0]: NULL; float4 *pack_tri_woop = (pack.tri_woop.size())? &pack.tri_woop[0]: NULL; @@ -376,6 +437,7 @@ void BVH::pack_instances(size_t nodes_size) int noffset = nodes_offset/nsize; int mesh_tri_offset = mesh->tri_offset; + int mesh_curve_offset = mesh->curveseg_offset; /* fill in node indexes for instances */ if((bvh->pack.is_leaf.size() != 0) && bvh->pack.is_leaf[0]) @@ -389,10 +451,16 @@ void BVH::pack_instances(size_t nodes_size) if(bvh->pack.prim_index.size()) { size_t bvh_prim_index_size = bvh->pack.prim_index.size(); int *bvh_prim_index = &bvh->pack.prim_index[0]; + int *bvh_prim_type = &bvh->pack.prim_type[0]; uint *bvh_prim_visibility = &bvh->pack.prim_visibility[0]; for(size_t i = 0; i < bvh_prim_index_size; i++) { - pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_tri_offset; + if(bvh->pack.prim_type[i]) + pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_curve_offset; + else + pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_tri_offset; + + pack_prim_type[pack_prim_index_offset] = bvh_prim_type[i]; pack_prim_visibility[pack_prim_index_offset] = bvh_prim_visibility[i]; pack_prim_object[pack_prim_index_offset] = 0; // unused for instances pack_prim_index_offset++; @@ -401,7 +469,7 @@ void BVH::pack_instances(size_t nodes_size) /* merge triangle intersection data */ if(bvh->pack.tri_woop.size()) { - memcpy(pack_tri_woop+pack_tri_woop_offset, &bvh->pack.tri_woop[0], + memcpy(pack_tri_woop + pack_tri_woop_offset, &bvh->pack.tri_woop[0], bvh->pack.tri_woop.size()*sizeof(float4)); pack_tri_woop_offset += bvh->pack.tri_woop.size(); } @@ -420,8 +488,8 @@ void BVH::pack_instances(size_t nodes_size) int4 data = bvh_nodes[i + nsize_bbox]; if(bvh_is_leaf && bvh_is_leaf[j]) { - data.x += tri_offset; - data.y += tri_offset; + data.x += prim_offset; + data.y += prim_offset; } else { data.x += (data.x < 0)? -noffset: noffset; @@ -443,7 +511,7 @@ void BVH::pack_instances(size_t nodes_size) } nodes_offset += bvh->pack.nodes.size(); - tri_offset += bvh->pack.prim_index.size(); + prim_offset += bvh->pack.prim_index.size(); } } @@ -544,25 +612,37 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility if(leaf) { /* refit leaf node */ - for(int tri = c0; tri < c1; tri++) { - int tidx = pack.prim_index[tri]; - int tob = pack.prim_object[tri]; + for(int prim = c0; prim < c1; prim++) { + int pidx = pack.prim_index[prim]; + int tob = pack.prim_object[prim]; Object *ob = objects[tob]; - if(tidx == -1) { + if(pidx == -1) { /* object instance */ bbox.grow(ob->bounds); } else { - /* triangles */ + /* primitives */ const Mesh *mesh = ob->mesh; - int tri_offset = (params.top_level)? mesh->tri_offset: 0; - const int *vidx = mesh->triangles[tidx - tri_offset].v; - const float3 *vpos = &mesh->verts[0]; - bbox.grow(vpos[vidx[0]]); - bbox.grow(vpos[vidx[1]]); - bbox.grow(vpos[vidx[2]]); + if(pack.prim_type[prim]) { + /* strands */ + int str_offset = (params.top_level)? mesh->curveseg_offset: 0; + const int *hidx = mesh->curve_segs[pidx - str_offset].v; + + bbox.grow(mesh->curve_keys[hidx[0]].loc, mesh->curve_keys[hidx[0]].radius); + bbox.grow(mesh->curve_keys[hidx[1]].loc, mesh->curve_keys[hidx[1]].radius); + } + else { + /* triangles */ + int tri_offset = (params.top_level)? mesh->tri_offset: 0; + const int *vidx = mesh->triangles[pidx - tri_offset].v; + const float3 *vpos = &mesh->verts[0]; + + bbox.grow(vpos[vidx[0]]); + bbox.grow(vpos[vidx[1]]); + bbox.grow(vpos[vidx[2]]); + } } visibility |= ob->visibility; diff --git a/intern/cycles/bvh/bvh.h b/intern/cycles/bvh/bvh.h index 549f1e3ac1d..d81bb312148 100644 --- a/intern/cycles/bvh/bvh.h +++ b/intern/cycles/bvh/bvh.h @@ -51,7 +51,9 @@ struct PackedBVH { /* object index to BVH node index mapping for instances */ array<int> object_node; /* precomputed triangle intersection data, one triangle is 4x float4 */ - array<float4> tri_woop; + array<float4> tri_woop; + /* primitive type - triangle or strand (should be moved to flag?) */ + array<int> prim_type; /* visibility visibilitys for primitives */ array<uint> prim_visibility; /* mapping from BVH primitive index to true primitive index, as primitives @@ -101,9 +103,10 @@ protected: bool cache_read(CacheData& key); void cache_write(CacheData& key); - /* triangles */ - void pack_triangles(); + /* triangles and strands*/ + void pack_primitives(); void pack_triangle(int idx, float4 woop[3]); + void pack_curve_seg(int idx, float4 woop[3]); /* merge instance BVH's */ void pack_instances(size_t nodes_size); diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp index 705b805a3a9..cdd94324f53 100644 --- a/intern/cycles/bvh/bvh_build.cpp +++ b/intern/cycles/bvh/bvh_build.cpp @@ -48,9 +48,10 @@ public: /* Constructor / Destructor */ BVHBuild::BVHBuild(const vector<Object*>& objects_, - vector<int>& prim_index_, vector<int>& prim_object_, + vector<int>& prim_type_, vector<int>& prim_index_, vector<int>& prim_object_, const BVHParams& params_, Progress& progress_) : objects(objects_), + prim_type(prim_type_), prim_index(prim_index_), prim_object(prim_object_), params(params_), @@ -78,7 +79,23 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh, } if(bounds.valid()) { - references.push_back(BVHReference(bounds, j, i)); + references.push_back(BVHReference(bounds, j, i, false)); + root.grow(bounds); + center.grow(bounds.center2()); + } + } + + for(uint j = 0; j < mesh->curve_segs.size(); j++) { + Mesh::CurveSeg s = mesh->curve_segs[j]; + BoundBox bounds = BoundBox::empty; + + for(int k = 0; k < 2; k++) { + float3 pt = mesh->curve_keys[s.v[k]].loc; + bounds.grow(pt, mesh->curve_keys[s.v[k]].radius); + } + + if(bounds.valid()) { + references.push_back(BVHReference(bounds, j, i, true)); root.grow(bounds); center.grow(bounds.center2()); } @@ -87,7 +104,7 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh, void BVHBuild::add_reference_object(BoundBox& root, BoundBox& center, Object *ob, int i) { - references.push_back(BVHReference(ob->bounds, -1, i)); + references.push_back(BVHReference(ob->bounds, -1, i, false)); root.grow(ob->bounds); center.grow(ob->bounds.center2()); } @@ -99,13 +116,17 @@ void BVHBuild::add_references(BVHRange& root) foreach(Object *ob, objects) { if(params.top_level) { - if(ob->mesh->transform_applied) + if(ob->mesh->transform_applied) { num_alloc_references += ob->mesh->triangles.size(); + num_alloc_references += ob->mesh->curve_segs.size(); + } else num_alloc_references++; } - else + else { num_alloc_references += ob->mesh->triangles.size(); + num_alloc_references += ob->mesh->curve_segs.size(); + } } references.reserve(num_alloc_references); @@ -162,6 +183,7 @@ BVHNode* BVHBuild::run() progress_total = references.size(); progress_original_total = progress_total; + prim_type.resize(references.size()); prim_index.resize(references.size()); prim_object.resize(references.size()); @@ -319,10 +341,12 @@ BVHNode *BVHBuild::create_object_leaf_nodes(const BVHReference *ref, int start, if(start == prim_index.size()) { assert(params.use_spatial_split); + prim_type.push_back(ref->prim_type()); prim_index.push_back(ref->prim_index()); prim_object.push_back(ref->prim_object()); } else { + prim_type[start] = ref->prim_type(); prim_index[start] = ref->prim_index(); prim_object[start] = ref->prim_object(); } @@ -345,6 +369,7 @@ BVHNode *BVHBuild::create_object_leaf_nodes(const BVHReference *ref, int start, BVHNode* BVHBuild::create_leaf_node(const BVHRange& range) { + vector<int>& p_type = prim_type; vector<int>& p_index = prim_index; vector<int>& p_object = prim_object; BoundBox bounds = BoundBox::empty; @@ -358,10 +383,12 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range) if(range.start() + num == prim_index.size()) { assert(params.use_spatial_split); + p_type.push_back(ref.prim_type()); p_index.push_back(ref.prim_index()); p_object.push_back(ref.prim_object()); } else { + p_type[range.start() + num] = ref.prim_type(); p_index[range.start() + num] = ref.prim_index(); p_object[range.start() + num] = ref.prim_object(); } diff --git a/intern/cycles/bvh/bvh_build.h b/intern/cycles/bvh/bvh_build.h index 44ef918b326..ba10eb49412 100644 --- a/intern/cycles/bvh/bvh_build.h +++ b/intern/cycles/bvh/bvh_build.h @@ -44,6 +44,7 @@ public: /* Constructor/Destructor */ BVHBuild( const vector<Object*>& objects, + vector<int>& prim_type, vector<int>& prim_index, vector<int>& prim_object, const BVHParams& params, @@ -87,6 +88,7 @@ protected: int num_original_references; /* output primitive indexes and objects */ + vector<int>& prim_type; vector<int>& prim_index; vector<int>& prim_object; diff --git a/intern/cycles/bvh/bvh_params.h b/intern/cycles/bvh/bvh_params.h index a78496d841d..7a1555ae548 100644 --- a/intern/cycles/bvh/bvh_params.h +++ b/intern/cycles/bvh/bvh_params.h @@ -98,19 +98,22 @@ class BVHReference public: __forceinline BVHReference() {} - __forceinline BVHReference(const BoundBox& bounds_, int prim_index_, int prim_object_) + __forceinline BVHReference(const BoundBox& bounds_, int prim_index_, int prim_object_, int prim_type) : rbounds(bounds_) { rbounds.min.w = __int_as_float(prim_index_); rbounds.max.w = __int_as_float(prim_object_); + type = prim_type; } __forceinline const BoundBox& bounds() const { return rbounds; } __forceinline int prim_index() const { return __float_as_int(rbounds.min.w); } __forceinline int prim_object() const { return __float_as_int(rbounds.max.w); } + __forceinline int prim_type() const { return type; } protected: BoundBox rbounds; + uint type; }; /* BVH Range diff --git a/intern/cycles/bvh/bvh_sort.cpp b/intern/cycles/bvh/bvh_sort.cpp index bef384be592..9a8961c8b15 100644 --- a/intern/cycles/bvh/bvh_sort.cpp +++ b/intern/cycles/bvh/bvh_sort.cpp @@ -43,6 +43,8 @@ public: else if(ra.prim_object() > rb.prim_object()) return false; else if(ra.prim_index() < rb.prim_index()) return true; else if(ra.prim_index() > rb.prim_index()) return false; + else if(ra.prim_type() < rb.prim_type()) return true; + else if(ra.prim_type() > rb.prim_type()) return false; return false; } diff --git a/intern/cycles/bvh/bvh_split.cpp b/intern/cycles/bvh/bvh_split.cpp index 263c5834428..860e2c8d7df 100644 --- a/intern/cycles/bvh/bvh_split.cpp +++ b/intern/cycles/bvh/bvh_split.cpp @@ -252,14 +252,41 @@ void BVHSpatialSplit::split_reference(BVHBuild *builder, BVHReference& left, BVH /* loop over vertices/edges. */ Object *ob = builder->objects[ref.prim_object()]; const Mesh *mesh = ob->mesh; - const int *inds = mesh->triangles[ref.prim_index()].v; - const float3 *verts = &mesh->verts[0]; - const float3* v1 = &verts[inds[2]]; - - for(int i = 0; i < 3; i++) { - const float3* v0 = v1; - int vindex = inds[i]; - v1 = &verts[vindex]; + + if (!ref.prim_type()) { + const int *inds = mesh->triangles[ref.prim_index()].v; + const float3 *verts = &mesh->verts[0]; + const float3* v1 = &verts[inds[2]]; + + for(int i = 0; i < 3; i++) { + const float3* v0 = v1; + int vindex = inds[i]; + v1 = &verts[vindex]; + float v0p = (*v0)[dim]; + float v1p = (*v1)[dim]; + + /* insert vertex to the boxes it belongs to. */ + if(v0p <= pos) + left_bounds.grow(*v0); + + if(v0p >= pos) + right_bounds.grow(*v0); + + /* edge intersects the plane => insert intersection to both boxes. */ + if((v0p < pos && v1p > pos) || (v0p > pos && v1p < pos)) { + float3 t = lerp(*v0, *v1, clamp((pos - v0p) / (v1p - v0p), 0.0f, 1.0f)); + left_bounds.grow(t); + right_bounds.grow(t); + } + } + } + else { + /* Strand split: NOTE - Currently ignores strand width and needs to be fixed.*/ + + const int *inds = mesh->curve_segs[ref.prim_index()].v; + const float3* v0 = &mesh->curve_keys[inds[0]].loc; + const float3* v1 = &mesh->curve_keys[inds[1]].loc; + float v0p = (*v0)[dim]; float v1p = (*v1)[dim]; @@ -270,6 +297,12 @@ void BVHSpatialSplit::split_reference(BVHBuild *builder, BVHReference& left, BVH if(v0p >= pos) right_bounds.grow(*v0); + if(v1p <= pos) + left_bounds.grow(*v1); + + if(v1p >= pos) + right_bounds.grow(*v1); + /* edge intersects the plane => insert intersection to both boxes. */ if((v0p < pos && v1p > pos) || (v0p > pos && v1p < pos)) { float3 t = lerp(*v0, *v1, clamp((pos - v0p) / (v1p - v0p), 0.0f, 1.0f)); @@ -284,9 +317,9 @@ void BVHSpatialSplit::split_reference(BVHBuild *builder, BVHReference& left, BVH left_bounds.intersect(ref.bounds()); right_bounds.intersect(ref.bounds()); - /* set referecnes */ - left = BVHReference(left_bounds, ref.prim_index(), ref.prim_object()); - right = BVHReference(right_bounds, ref.prim_index(), ref.prim_object()); + /* set references */ + left = BVHReference(left_bounds, ref.prim_index(), ref.prim_object(), ref.prim_type()); + right = BVHReference(right_bounds, ref.prim_index(), ref.prim_object(), ref.prim_type()); } CCL_NAMESPACE_END |