diff options
26 files changed, 331 insertions, 290 deletions
diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp index 61628aae535..2e9a32f15f2 100644 --- a/intern/cycles/blender/blender_curves.cpp +++ b/intern/cycles/blender/blender_curves.cpp @@ -652,11 +652,10 @@ void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int inter void ExportCurveSegments(Mesh *mesh, ParticleCurveData *CData, int interpolation, int segments) { - int cks = 0; - int curs = 0; - int segs = 0; + int num_keys = 0; + int num_curves = 0; - if(!(mesh->curve_segments.empty() && mesh->curve_keys.empty())) + if(!(mesh->curves.empty() && mesh->curve_keys.empty())) return; Attribute *attr_uv = mesh->curve_attributes.add(ATTR_STD_UV); @@ -672,6 +671,8 @@ void ExportCurveSegments(Mesh *mesh, ParticleCurveData *CData, int interpolation if(CData->curve_keynum[curve] <= 1) continue; + size_t num_curve_keys = 0; + for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) { int subv = 1; @@ -696,26 +697,23 @@ void ExportCurveSegments(Mesh *mesh, ParticleCurveData *CData, int interpolation mesh->add_curve_key(ickey_loc, radius); attr_intercept->add(time); - if(subv != 0) { - attr_uv->add(CData->curve_uv[curve]); - mesh->add_curve_segment(cks - 1, cks, CData->psys_shader[sys], curs); - segs++; - } - - cks++; + num_curve_keys++; } } - curs++; + mesh->add_curve(num_keys, num_curve_keys, CData->psys_shader[sys]); + attr_uv->add(CData->curve_uv[curve]); + num_keys += num_curve_keys; + num_curves++; } } /* check allocation*/ - if((mesh->curve_keys.size() != cks) || (mesh->curve_segments.size() != segs)) { + if((mesh->curve_keys.size() != num_keys) || (mesh->curves.size() != num_curves)) { /* allocation failed -> clear data */ mesh->curve_keys.clear(); - mesh->curve_segments.clear(); + mesh->curves.clear(); mesh->curve_attributes.clear(); } } @@ -824,7 +822,7 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool { /* Clear stored curve data */ mesh->curve_keys.clear(); - mesh->curve_segments.clear(); + mesh->curves.clear(); mesh->curve_attributes.clear(); /* obtain general settings */ diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp index 0b43704b7b8..412b44031e6 100644 --- a/intern/cycles/bvh/bvh.cpp +++ b/intern/cycles/bvh/bvh.cpp @@ -76,7 +76,7 @@ bool BVH::cache_read(CacheData& key) key.add(ob->mesh->verts); key.add(ob->mesh->triangles); key.add(ob->mesh->curve_keys); - key.add(ob->mesh->curve_segments); + key.add(ob->mesh->curves); key.add(&ob->bounds, sizeof(ob->bounds)); key.add(&ob->visibility, sizeof(ob->visibility)); key.add(&ob->mesh->transform_applied, sizeof(bool)); @@ -93,7 +93,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_segment); value.read(pack.prim_visibility); value.read(pack.prim_index); value.read(pack.prim_object); @@ -115,7 +115,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_segment); value.add(pack.prim_visibility); value.add(pack.prim_index); value.add(pack.prim_object); @@ -161,11 +161,11 @@ void BVH::build(Progress& progress) } /* build nodes */ - vector<int> prim_type; + vector<int> prim_segment; vector<int> prim_index; vector<int> prim_object; - BVHBuild bvh_build(objects, prim_type, prim_index, prim_object, params, progress); + BVHBuild bvh_build(objects, prim_segment, prim_index, prim_object, params, progress); BVHNode *root = bvh_build.run(); if(progress.get_cancel()) { @@ -174,7 +174,7 @@ void BVH::build(Progress& progress) } /* todo: get rid of this copy */ - pack.prim_type = prim_type; + pack.prim_segment = prim_segment; pack.prim_index = prim_index; pack.prim_object = prim_object; @@ -271,13 +271,16 @@ void BVH::pack_triangle(int idx, float4 woop[3]) /* Curves*/ -void BVH::pack_curve_seg(int idx, float4 woop[3]) +void BVH::pack_curve_segment(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_segments[tidx].v[0]].co; - float3 v1 = mesh->curve_keys[mesh->curve_segments[tidx].v[1]].co; + int segment = pack.prim_segment[idx]; + int k0 = mesh->curves[tidx].first_key + segment; + int k1 = mesh->curves[tidx].first_key + segment + 1; + float3 v0 = mesh->curve_keys[k0].co; + float3 v1 = mesh->curve_keys[k1].co; float3 d0 = v1 - v0; float l = len(d0); @@ -289,19 +292,19 @@ void BVH::pack_curve_seg(int idx, float4 woop[3]) * nextkey, flags/tip?, 0, 0); */ Attribute *attr_tangent = mesh->curve_attributes.find(ATTR_STD_CURVE_TANGENT); + float3 tg0 = make_float3(1.0f, 0.0f, 0.0f); float3 tg1 = make_float3(1.0f, 0.0f, 0.0f); - float3 tg2 = make_float3(1.0f, 0.0f, 0.0f); if(attr_tangent) { const float3 *data_tangent = attr_tangent->data_float3(); - tg1 = data_tangent[mesh->curve_segments[tidx].v[0]]; - tg2 = data_tangent[mesh->curve_segments[tidx].v[1]]; + tg0 = data_tangent[k0]; + tg1 = data_tangent[k1]; } Transform tfm = make_transform( - tg1.x, tg1.y, tg1.z, l, - tg2.x, tg2.y, tg2.z, 0, + tg0.x, tg0.y, tg0.z, l, + tg1.x, tg1.y, tg1.z, 0, 0, 0, 0, 0, 0, 0, 0, 1); @@ -325,8 +328,8 @@ void BVH::pack_primitives() if(pack.prim_index[i] != -1) { float4 woop[3]; - if(pack.prim_type[i]) - pack_curve_seg(i, woop); + if(pack.prim_segment[i] != ~0) + pack_curve_segment(i, woop); else pack_triangle(i, woop); @@ -353,8 +356,8 @@ void BVH::pack_instances(size_t nodes_size) * 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) { - if(pack.prim_type[i]) - pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->curveseg_offset; + if(pack.prim_segment[i] != ~0) + pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->curve_offset; else pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->tri_offset; } @@ -395,7 +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_segment.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); @@ -403,7 +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_segment = (pack.prim_segment.size())? &pack.prim_segment[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; @@ -434,7 +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; + int mesh_curve_offset = mesh->curve_offset; /* fill in node indexes for instances */ if((bvh->pack.is_leaf.size() != 0) && bvh->pack.is_leaf[0]) @@ -448,16 +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]; + int *bvh_prim_segment = &bvh->pack.prim_segment[0]; uint *bvh_prim_visibility = &bvh->pack.prim_visibility[0]; for(size_t i = 0; i < bvh_prim_index_size; i++) { - if(bvh->pack.prim_type[i]) + if(bvh->pack.prim_segment[i] != ~0) 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_segment[pack_prim_index_offset] = bvh_prim_segment[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++; @@ -622,13 +625,14 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility /* primitives */ const Mesh *mesh = ob->mesh; - if(pack.prim_type[prim]) { - /* strands */ - int str_offset = (params.top_level)? mesh->curveseg_offset: 0; - const int *hidx = mesh->curve_segments[pidx - str_offset].v; + if(pack.prim_segment[prim] != ~0) { + /* curves */ + int str_offset = (params.top_level)? mesh->curve_offset: 0; + int k0 = mesh->curves[pidx - str_offset].first_key + pack.prim_segment[prim]; // XXX! + int k1 = k0 + 1; - bbox.grow(mesh->curve_keys[hidx[0]].co, mesh->curve_keys[hidx[0]].radius); - bbox.grow(mesh->curve_keys[hidx[1]].co, mesh->curve_keys[hidx[1]].radius); + bbox.grow(mesh->curve_keys[k0].co, mesh->curve_keys[k0].radius); + bbox.grow(mesh->curve_keys[k1].co, mesh->curve_keys[k1].radius); } else { /* triangles */ diff --git a/intern/cycles/bvh/bvh.h b/intern/cycles/bvh/bvh.h index d81bb312148..00c146143b8 100644 --- a/intern/cycles/bvh/bvh.h +++ b/intern/cycles/bvh/bvh.h @@ -53,7 +53,7 @@ struct PackedBVH { /* precomputed triangle intersection data, one triangle is 4x float4 */ array<float4> tri_woop; /* primitive type - triangle or strand (should be moved to flag?) */ - array<int> prim_type; + array<int> prim_segment; /* visibility visibilitys for primitives */ array<uint> prim_visibility; /* mapping from BVH primitive index to true primitive index, as primitives @@ -106,7 +106,7 @@ protected: /* triangles and strands*/ void pack_primitives(); void pack_triangle(int idx, float4 woop[3]); - void pack_curve_seg(int idx, float4 woop[3]); + void pack_curve_segment(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 665c783b2d8..38fb1a15a13 100644 --- a/intern/cycles/bvh/bvh_build.cpp +++ b/intern/cycles/bvh/bvh_build.cpp @@ -48,10 +48,10 @@ public: /* Constructor / Destructor */ BVHBuild::BVHBuild(const vector<Object*>& objects_, - vector<int>& prim_type_, vector<int>& prim_index_, vector<int>& prim_object_, + vector<int>& prim_segment_, vector<int>& prim_index_, vector<int>& prim_object_, const BVHParams& params_, Progress& progress_) : objects(objects_), - prim_type(prim_type_), + prim_segment(prim_segment_), prim_index(prim_index_), prim_object(prim_object_), params(params_), @@ -74,30 +74,34 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh, BoundBox bounds = BoundBox::empty; for(int k = 0; k < 3; k++) { - float3 pt = mesh->verts[t.v[k]]; - bounds.grow(pt); + float3 co = mesh->verts[t.v[k]]; + bounds.grow(co); } if(bounds.valid()) { - references.push_back(BVHReference(bounds, j, i, false)); + references.push_back(BVHReference(bounds, j, i, ~0)); root.grow(bounds); center.grow(bounds.center2()); } } - for(uint j = 0; j < mesh->curve_segments.size(); j++) { - Mesh::CurveSegment s = mesh->curve_segments[j]; - BoundBox bounds = BoundBox::empty; + for(uint j = 0; j < mesh->curves.size(); j++) { + Mesh::Curve curve = mesh->curves[j]; - for(int k = 0; k < 2; k++) { - float3 pt = mesh->curve_keys[s.v[k]].co; - bounds.grow(pt, mesh->curve_keys[s.v[k]].radius); - } + for(int k = 0; k < curve.num_keys - 1; k++) { + BoundBox bounds = BoundBox::empty; - if(bounds.valid()) { - references.push_back(BVHReference(bounds, j, i, true)); - root.grow(bounds); - center.grow(bounds.center2()); + float3 co0 = mesh->curve_keys[curve.first_key + k].co; + float3 co1 = mesh->curve_keys[curve.first_key + k + 1].co; + + bounds.grow(co0, mesh->curve_keys[curve.first_key + k].radius); + bounds.grow(co1, mesh->curve_keys[curve.first_key + k + 1].radius); + + if(bounds.valid()) { + references.push_back(BVHReference(bounds, j, i, k)); + root.grow(bounds); + center.grow(bounds.center2()); + } } } } @@ -109,6 +113,16 @@ void BVHBuild::add_reference_object(BoundBox& root, BoundBox& center, Object *ob center.grow(ob->bounds.center2()); } +static size_t count_curve_segments(Mesh *mesh) +{ + size_t num = 0, num_curves = mesh->curves.size(); + + for(size_t i = 0; i < num_curves; i++) + num += mesh->curves[i].num_keys - 1; + + return num; +} + void BVHBuild::add_references(BVHRange& root) { /* reserve space for references */ @@ -118,14 +132,14 @@ void BVHBuild::add_references(BVHRange& root) if(params.top_level) { if(ob->mesh->transform_applied) { num_alloc_references += ob->mesh->triangles.size(); - num_alloc_references += ob->mesh->curve_segments.size(); + num_alloc_references += count_curve_segments(ob->mesh); } else num_alloc_references++; } else { num_alloc_references += ob->mesh->triangles.size(); - num_alloc_references += ob->mesh->curve_segments.size(); + num_alloc_references += count_curve_segments(ob->mesh); } } @@ -183,7 +197,7 @@ BVHNode* BVHBuild::run() progress_total = references.size(); progress_original_total = progress_total; - prim_type.resize(references.size()); + prim_segment.resize(references.size()); prim_index.resize(references.size()); prim_object.resize(references.size()); @@ -341,12 +355,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_segment.push_back(ref->prim_segment()); prim_index.push_back(ref->prim_index()); prim_object.push_back(ref->prim_object()); } else { - prim_type[start] = ref->prim_type(); + prim_segment[start] = ref->prim_segment(); prim_index[start] = ref->prim_index(); prim_object[start] = ref->prim_object(); } @@ -369,7 +383,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_segment = prim_segment; vector<int>& p_index = prim_index; vector<int>& p_object = prim_object; BoundBox bounds = BoundBox::empty; @@ -383,12 +397,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_segment.push_back(ref.prim_segment()); p_index.push_back(ref.prim_index()); p_object.push_back(ref.prim_object()); } else { - p_type[range.start() + num] = ref.prim_type(); + p_segment[range.start() + num] = ref.prim_segment(); 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 ba10eb49412..3df4da1739a 100644 --- a/intern/cycles/bvh/bvh_build.h +++ b/intern/cycles/bvh/bvh_build.h @@ -44,7 +44,7 @@ public: /* Constructor/Destructor */ BVHBuild( const vector<Object*>& objects, - vector<int>& prim_type, + vector<int>& prim_segment, vector<int>& prim_index, vector<int>& prim_object, const BVHParams& params, @@ -88,7 +88,7 @@ protected: int num_original_references; /* output primitive indexes and objects */ - vector<int>& prim_type; + vector<int>& prim_segment; 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 7a1555ae548..f7bc79f71e6 100644 --- a/intern/cycles/bvh/bvh_params.h +++ b/intern/cycles/bvh/bvh_params.h @@ -98,22 +98,22 @@ class BVHReference public: __forceinline BVHReference() {} - __forceinline BVHReference(const BoundBox& bounds_, int prim_index_, int prim_object_, int prim_type) + __forceinline BVHReference(const BoundBox& bounds_, int prim_index_, int prim_object_, int prim_segment) : rbounds(bounds_) { rbounds.min.w = __int_as_float(prim_index_); rbounds.max.w = __int_as_float(prim_object_); - type = prim_type; + segment = prim_segment; } __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; } + __forceinline int prim_segment() const { return segment; } protected: BoundBox rbounds; - uint type; + uint segment; }; /* BVH Range diff --git a/intern/cycles/bvh/bvh_sort.cpp b/intern/cycles/bvh/bvh_sort.cpp index 9a8961c8b15..91994be5b96 100644 --- a/intern/cycles/bvh/bvh_sort.cpp +++ b/intern/cycles/bvh/bvh_sort.cpp @@ -43,8 +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; + else if(ra.prim_segment() < rb.prim_segment()) return true; + else if(ra.prim_segment() > rb.prim_segment()) return false; return false; } diff --git a/intern/cycles/bvh/bvh_split.cpp b/intern/cycles/bvh/bvh_split.cpp index 67fdfd77657..03ff69d7b6d 100644 --- a/intern/cycles/bvh/bvh_split.cpp +++ b/intern/cycles/bvh/bvh_split.cpp @@ -253,7 +253,7 @@ void BVHSpatialSplit::split_reference(BVHBuild *builder, BVHReference& left, BVH Object *ob = builder->objects[ref.prim_object()]; const Mesh *mesh = ob->mesh; - if (!ref.prim_type()) { + if (ref.prim_segment() == ~0) { const int *inds = mesh->triangles[ref.prim_index()].v; const float3 *verts = &mesh->verts[0]; const float3* v1 = &verts[inds[2]]; @@ -281,11 +281,11 @@ void BVHSpatialSplit::split_reference(BVHBuild *builder, BVHReference& left, BVH } } else { - /* Strand split: NOTE - Currently ignores strand width and needs to be fixed.*/ - - const int *inds = mesh->curve_segments[ref.prim_index()].v; - const float3* v0 = &mesh->curve_keys[inds[0]].co; - const float3* v1 = &mesh->curve_keys[inds[1]].co; + /* curve split: NOTE - Currently ignores curve width and needs to be fixed.*/ + const int k0 = mesh->curves[ref.prim_index()].first_key + ref.prim_segment(); + const int k1 = k0 + 1; + const float3* v0 = &mesh->curve_keys[k0].co; + const float3* v1 = &mesh->curve_keys[k1].co; float v0p = (*v0)[dim]; float v1p = (*v1)[dim]; @@ -318,8 +318,8 @@ void BVHSpatialSplit::split_reference(BVHBuild *builder, BVHReference& left, BVH right_bounds.intersect(ref.bounds()); /* 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()); + left = BVHReference(left_bounds, ref.prim_index(), ref.prim_object(), ref.prim_segment()); + right = BVHReference(right_bounds, ref.prim_index(), ref.prim_object(), ref.prim_segment()); } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/kernel_bvh.h b/intern/cycles/kernel/kernel_bvh.h index d32287f91e8..c811d83ad78 100644 --- a/intern/cycles/kernel/kernel_bvh.h +++ b/intern/cycles/kernel/kernel_bvh.h @@ -207,22 +207,22 @@ __device_inline void bvh_triangle_intersect(KernelGlobals *kg, Intersection *ise #ifdef __HAIR__ __device_inline void bvh_curve_intersect(KernelGlobals *kg, Intersection *isect, - float3 P, float3 idir, uint visibility, int object, int triAddr) + float3 P, float3 idir, uint visibility, int object, int curveAddr, int segment) { /* curve Intersection check */ int flags = kernel_data.curve_kernel_data.curveflags; - int prim = kernel_tex_fetch(__prim_index, triAddr); - float4 v00 = kernel_tex_fetch(__curve_segments, prim); + int prim = kernel_tex_fetch(__prim_index, curveAddr); + float4 v00 = kernel_tex_fetch(__curves, prim); - int v1 = __float_as_int(v00.x); - int v2 = __float_as_int(v00.y); + int k0 = __float_as_int(v00.x) + segment; + int k1 = k0 + 1; - float4 P1 = kernel_tex_fetch(__curve_keys, v1); - float4 P2 = kernel_tex_fetch(__curve_keys, v2); + float4 P1 = kernel_tex_fetch(__curve_keys, k0); + float4 P2 = kernel_tex_fetch(__curve_keys, k1); - float l = v00.w; + float l = len(P2 - P1); // XXX slower float r1 = P1.w; float r2 = P2.w; float mr = max(r1,r2); @@ -329,14 +329,15 @@ __device_inline void bvh_curve_intersect(KernelGlobals *kg, Intersection *isect, return; }*/ - #ifdef __VISIBILITY_FLAG__ +#ifdef __VISIBILITY_FLAG__ /* visibility flag test. we do it here under the assumption * that most triangles are culled by node flags */ - if(kernel_tex_fetch(__prim_visibility, triAddr) & visibility) - #endif + if(kernel_tex_fetch(__prim_visibility, curveAddr) & visibility) +#endif { /* record intersection */ - isect->prim = triAddr; + isect->prim = curveAddr; + isect->segment = segment; isect->object = object; isect->u = z/l; isect->v = td/(4*a*a); @@ -430,8 +431,9 @@ __device_inline bool bvh_intersect(KernelGlobals *kg, const Ray *ray, const uint while(primAddr < primAddr2) { /* intersect ray against primitive */ #ifdef __HAIR__ - if(kernel_tex_fetch(__prim_type, primAddr)) - bvh_curve_intersect(kg, isect, P, idir, visibility, object, primAddr); + uint segment = kernel_tex_fetch(__prim_segment, primAddr); + if(segment != ~0) + bvh_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, segment); else #endif bvh_triangle_intersect(kg, isect, P, idir, visibility, object, primAddr); @@ -555,8 +557,9 @@ __device_inline bool bvh_intersect_motion(KernelGlobals *kg, const Ray *ray, con while(primAddr < primAddr2) { /* intersect ray against primitive */ #ifdef __HAIR__ - if(kernel_tex_fetch(__prim_type, primAddr)) - bvh_curve_intersect(kg, isect, P, idir, visibility, object, primAddr); + uint segment = kernel_tex_fetch(__prim_segment, primAddr); + if(segment != ~0) + bvh_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, segment); else #endif bvh_triangle_intersect(kg, isect, P, idir, visibility, object, primAddr); @@ -720,14 +723,14 @@ __device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, const } int prim = kernel_tex_fetch(__prim_index, isect->prim); - float4 v00 = kernel_tex_fetch(__curve_segments, prim); + float4 v00 = kernel_tex_fetch(__curves, prim); - int v1 = __float_as_int(v00.x); - int v2 = __float_as_int(v00.y); + int k0 = __float_as_int(v00.x) + isect->segment; + int k1 = k0 + 1; - float4 P1 = kernel_tex_fetch(__curve_keys, v1); - float4 P2 = kernel_tex_fetch(__curve_keys, v2); - float l = v00.w; + float4 P1 = kernel_tex_fetch(__curve_keys, k0); + float4 P2 = kernel_tex_fetch(__curve_keys, k1); + float l = len(P2 - P1); // XXX slower float r1 = P1.w; float r2 = P2.w; float3 tg = float4_to_float3(P2 - P1) / l; diff --git a/intern/cycles/kernel/kernel_curve.h b/intern/cycles/kernel/kernel_curve.h index fef1a48644d..e065717888c 100644 --- a/intern/cycles/kernel/kernel_curve.h +++ b/intern/cycles/kernel/kernel_curve.h @@ -24,19 +24,21 @@ CCL_NAMESPACE_BEGIN __device float curve_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy) { - if(elem == ATTR_ELEMENT_CURVE_SEGMENT) { + if(elem == ATTR_ELEMENT_CURVE) { #ifdef __RAY_DIFFERENTIALS__ if(dx) *dx = 0.0f; if(dy) *dy = 0.0f; #endif - return kernel_tex_fetch(__attributes_float, offset + sd->curve_seg); + return kernel_tex_fetch(__attributes_float, offset + sd->prim); } else if(elem == ATTR_ELEMENT_CURVE_KEY) { - float4 segment = kernel_tex_fetch(__curve_segments, sd->curve_seg); + float4 curvedata = kernel_tex_fetch(__curves, sd->prim); + int k0 = __float_as_int(curvedata.x) + sd->segment; + int k1 = k0 + 1; - float f0 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(segment.x)); - float f1 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(segment.y)); + float f0 = kernel_tex_fetch(__attributes_float, offset + k0); + float f1 = kernel_tex_fetch(__attributes_float, offset + k1); #ifdef __RAY_DIFFERENTIALS__ if(dx) *dx = sd->du.dx*(f1 - f0); @@ -57,7 +59,7 @@ __device float curve_attribute_float(KernelGlobals *kg, const ShaderData *sd, At __device float3 curve_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy) { - if(elem == ATTR_ELEMENT_CURVE_SEGMENT) { + if(elem == ATTR_ELEMENT_CURVE) { /* idea: we can't derive any useful differentials here, but for tiled * mipmap image caching it would be useful to avoid reading the highest * detail level always. maybe a derivative based on the hair density @@ -67,13 +69,15 @@ __device float3 curve_attribute_float3(KernelGlobals *kg, const ShaderData *sd, if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f); #endif - return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + sd->curve_seg)); + return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + sd->prim)); } else if(elem == ATTR_ELEMENT_CURVE_KEY) { - float4 segment = kernel_tex_fetch(__curve_segments, sd->curve_seg); + float4 curvedata = kernel_tex_fetch(__curves, sd->prim); + int k0 = __float_as_int(curvedata.x) + sd->segment; + int k1 = k0 + 1; - float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(segment.x))); - float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(segment.y))); + float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + k0)); + float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + k1)); #ifdef __RAY_DIFFERENTIALS__ if(dx) *dx = sd->du.dx*(f1 - f0); @@ -96,19 +100,16 @@ __device float3 curve_attribute_float3(KernelGlobals *kg, const ShaderData *sd, __device float curve_thickness(KernelGlobals *kg, ShaderData *sd) { - int prim = sd->curve_seg; - float u = sd->u; float r = 0.0f; - if(prim != -1) { - float4 v00 = kernel_tex_fetch(__curve_segments, prim); + if(sd->segment != ~0) { + float4 curvedata = kernel_tex_fetch(__curves, sd->prim); + int k0 = __float_as_int(curvedata.x) + sd->segment; + int k1 = k0 + 1; - int v1 = __float_as_int(v00.x); - int v2 = __float_as_int(v00.y); - - float4 P1 = kernel_tex_fetch(__curve_keys, v1); - float4 P2 = kernel_tex_fetch(__curve_keys, v2); - r = (P2.w - P1.w) * u + P1.w; + float4 P1 = kernel_tex_fetch(__curve_keys, k0); + float4 P2 = kernel_tex_fetch(__curve_keys, k1); + r = (P2.w - P1.w) * sd->u + P1.w; } return r*2.0f; @@ -118,7 +119,7 @@ __device float3 curve_tangent_normal(KernelGlobals *kg, ShaderData *sd) { float3 tgN = make_float3(0.0f,0.0f,0.0f); - if(sd->curve_seg != ~0) { + if(sd->segment != ~0) { float normalmix = kernel_data.curve_kernel_data.normalmix; tgN = -(-sd->I - sd->dPdu * (dot(sd->dPdu,-sd->I) * normalmix / len_squared(sd->dPdu))); diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h index adf7e8eca82..d5506ad1dd0 100644 --- a/intern/cycles/kernel/kernel_emission.h +++ b/intern/cycles/kernel/kernel_emission.h @@ -157,7 +157,7 @@ __device float3 indirect_emission(KernelGlobals *kg, ShaderData *sd, float t, in float3 L = shader_emissive_eval(kg, sd); #ifdef __HAIR__ - if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_SAMPLE_AS_LIGHT) && (sd->curve_seg == ~0)) { + if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_SAMPLE_AS_LIGHT) && (sd->segment == ~0)) { #else if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_SAMPLE_AS_LIGHT)) { #endif diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index 09ee1f68e12..1561ddc9ddd 100644 --- a/intern/cycles/kernel/kernel_light.h +++ b/intern/cycles/kernel/kernel_light.h @@ -329,18 +329,20 @@ __device float triangle_light_pdf(KernelGlobals *kg, #ifdef __HAIR__ /* Strand Light */ -__device void curve_seg_light_sample(KernelGlobals *kg, int prim, int object, - float randu, float randv, float time, LightSample *ls) +__device void curve_segment_light_sample(KernelGlobals *kg, int prim, int object, + int segment, float randu, float randv, float time, LightSample *ls) { /* this strand code needs completion */ - float4 v00 = kernel_tex_fetch(__curve_segments, prim); + float4 v00 = kernel_tex_fetch(__curves, prim); + + int k0 = __float_as_int(v00.x) + segment; + int k1 = k0 + 1; - int v1 = __float_as_int(v00.x); - int v2 = __float_as_int(v00.y); - float l = v00.w; + float4 P1 = kernel_tex_fetch(__curve_keys, k0); + float4 P2 = kernel_tex_fetch(__curve_keys, k1); + + float l = len(P2 - P1); // XXX slower - float4 P1 = kernel_tex_fetch(__curve_keys, v1); - float4 P2 = kernel_tex_fetch(__curve_keys, v2); float r1 = P1.w; float r2 = P2.w; float3 tg = float4_to_float3(P2 - P1) / l; @@ -419,15 +421,15 @@ __device void light_sample(KernelGlobals *kg, float randt, float randu, float ra float4 l = kernel_tex_fetch(__light_distribution, index); int prim = __float_as_int(l.y); #ifdef __HAIR__ -/* currently use l.z to indicate is strand sample which isn't ideal */ - bool is_curve = __float_as_int(l.z) == 0.0f; + int segment = __float_as_int(l.z); #endif if(prim >= 0) { int object = __float_as_int(l.w); + #ifdef __HAIR__ - if (is_curve) - curve_seg_light_sample(kg, prim, object, randu, randv, time, ls); + if (segment != ~0) + curve_segment_light_sample(kg, prim, object, segment, randu, randv, time, ls); else #endif triangle_light_sample(kg, prim, object, randu, randv, time, ls); diff --git a/intern/cycles/kernel/kernel_primitive.h b/intern/cycles/kernel/kernel_primitive.h index 2296017c686..7538b7107d0 100644 --- a/intern/cycles/kernel/kernel_primitive.h +++ b/intern/cycles/kernel/kernel_primitive.h @@ -37,7 +37,7 @@ __device_inline int find_attribute(KernelGlobals *kg, ShaderData *sd, uint id, A { /* for SVM, find attribute by unique id */ uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride; - attr_offset = (sd->curve_seg == ~0)? attr_offset: attr_offset + ATTR_PRIM_CURVE; + attr_offset = (sd->segment == ~0)? attr_offset: attr_offset + ATTR_PRIM_CURVE; uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset); while(attr_map.x != id) { @@ -55,7 +55,7 @@ __device_inline int find_attribute(KernelGlobals *kg, ShaderData *sd, uint id, A __device float primitive_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy) { #ifdef __HAIR__ - if(sd->curve_seg == ~0) + if(sd->segment == ~0) #endif return triangle_attribute_float(kg, sd, elem, offset, dx, dy); #ifdef __HAIR__ @@ -67,7 +67,7 @@ __device float primitive_attribute_float(KernelGlobals *kg, const ShaderData *sd __device float3 primitive_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy) { #ifdef __HAIR__ - if(sd->curve_seg == ~0) + if(sd->segment == ~0) #endif return triangle_attribute_float3(kg, sd, elem, offset, dx, dy); #ifdef __HAIR__ @@ -92,7 +92,7 @@ __device float3 primitive_uv(KernelGlobals *kg, ShaderData *sd) __device float3 primitive_tangent(KernelGlobals *kg, ShaderData *sd) { #ifdef __HAIR__ - if(sd->curve_seg != ~0) + if(sd->segment != ~0) return normalize(sd->dPdu); #endif diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index 49bbc5a74ab..0a5a2ab54b0 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -69,25 +69,22 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd, #endif sd->prim = kernel_tex_fetch(__prim_index, isect->prim); -#ifdef __HAIR__ - sd->curve_seg = ~0; -#endif sd->ray_length = isect->t; #ifdef __HAIR__ - if(kernel_tex_fetch(__prim_type, isect->prim)) { + if(kernel_tex_fetch(__prim_segment, isect->prim) != ~0) { /* Strand Shader setting*/ - float4 CurSeg = kernel_tex_fetch(__curve_segments, sd->prim); - sd->shader = __float_as_int(CurSeg.z); + float4 curvedata = kernel_tex_fetch(__curves, sd->prim); - sd->curve_seg = sd->prim; - sd->prim = isect->prim; + sd->shader = __float_as_int(curvedata.z); + sd->segment = isect->segment; float tcorr = isect->t; if(kernel_data.curve_kernel_data.curveflags & CURVE_KN_POSTINTERSECTCORRECTION) { tcorr = (isect->u < 0)? tcorr + sqrtf(isect->v) : tcorr - sqrtf(isect->v); sd->ray_length = tcorr; } + sd->P = bvh_curve_refine(kg, sd, isect, ray, tcorr); } else { @@ -97,6 +94,10 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd, float3 Ng = make_float3(Ns.x, Ns.y, Ns.z); sd->shader = __float_as_int(Ns.w); +#ifdef __HAIR__ + sd->segment = ~0; +#endif + #ifdef __UV__ sd->u = isect->u; sd->v = isect->v; @@ -107,7 +108,6 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd, sd->Ng = Ng; sd->N = Ng; - /* smooth normal */ if(sd->shader & SHADER_SMOOTH_NORMAL) sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v); @@ -162,7 +162,7 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd, __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd, const float3 P, const float3 Ng, const float3 I, - int shader, int object, int prim, float u, float v, float t, float time, int curve = ~0) + int shader, int object, int prim, float u, float v, float t, float time, int segment = ~0) { /* vectors */ sd->P = P; @@ -171,7 +171,7 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd, sd->I = I; sd->shader = shader; #ifdef __HAIR__ - sd->curve_seg = curve; + sd->segment = segment; #endif /* primitive */ @@ -215,7 +215,7 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd, /* smooth normal */ #ifdef __HAIR__ - if(sd->shader & SHADER_SMOOTH_NORMAL && sd->curve_seg == ~0) { + if(sd->shader & SHADER_SMOOTH_NORMAL && sd->segment == ~0) { sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v); #else if(sd->shader & SHADER_SMOOTH_NORMAL) { @@ -231,7 +231,7 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd, #ifdef __DPDU__ /* dPdu/dPdv */ #ifdef __HAIR__ - if(sd->prim == ~0 || sd->curve_seg != ~0) { + if(sd->prim == ~0 || sd->segment != ~0) { sd->dPdu = make_float3(0.0f, 0.0f, 0.0f); sd->dPdv = make_float3(0.0f, 0.0f, 0.0f); } @@ -323,7 +323,7 @@ __device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData #endif sd->prim = ~0; #ifdef __HAIR__ - sd->curve_seg = ~0; + sd->segment = ~0; #endif #ifdef __UV__ sd->u = 0.0f; @@ -781,14 +781,14 @@ __device bool shader_transparent_shadow(KernelGlobals *kg, Intersection *isect) int shader = 0; #ifdef __HAIR__ - if(!kernel_tex_fetch(__prim_type, isect->prim)) { + if(kernel_tex_fetch(__prim_segment, isect->prim) == ~0) { #endif float4 Ns = kernel_tex_fetch(__tri_normal, prim); shader = __float_as_int(Ns.w); #ifdef __HAIR__ } else { - float4 str = kernel_tex_fetch(__curve_segments, prim); + float4 str = kernel_tex_fetch(__curves, prim); shader = __float_as_int(str.z); } #endif diff --git a/intern/cycles/kernel/kernel_textures.h b/intern/cycles/kernel/kernel_textures.h index 072df21a188..e27de95e7ab 100644 --- a/intern/cycles/kernel/kernel_textures.h +++ b/intern/cycles/kernel/kernel_textures.h @@ -27,7 +27,7 @@ /* bvh */ KERNEL_TEX(float4, texture_float4, __bvh_nodes) KERNEL_TEX(float4, texture_float4, __tri_woop) -KERNEL_TEX(uint, texture_uint, __prim_type) +KERNEL_TEX(uint, texture_uint, __prim_segment) KERNEL_TEX(uint, texture_uint, __prim_visibility) KERNEL_TEX(uint, texture_uint, __prim_index) KERNEL_TEX(uint, texture_uint, __prim_object) @@ -44,7 +44,7 @@ KERNEL_TEX(float4, texture_float4, __tri_vindex) KERNEL_TEX(float4, texture_float4, __tri_verts) /* curves */ -KERNEL_TEX(float4, texture_float4, __curve_segments) +KERNEL_TEX(float4, texture_float4, __curves) KERNEL_TEX(float4, texture_float4, __curve_keys) /* attributes */ diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index e80772bd4e2..2bd6b5859f3 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -344,6 +344,7 @@ typedef struct Intersection { float t, u, v; int prim; int object; + int segment; } Intersection; /* Attributes */ @@ -357,7 +358,7 @@ typedef enum AttributeElement { ATTR_ELEMENT_FACE, ATTR_ELEMENT_VERTEX, ATTR_ELEMENT_CORNER, - ATTR_ELEMENT_CURVE_SEGMENT, + ATTR_ELEMENT_CURVE, ATTR_ELEMENT_CURVE_KEY } AttributeElement; @@ -464,8 +465,8 @@ typedef struct ShaderData { int prim; #ifdef __HAIR__ - /* strand id if there is one, -1 otherwise */ - int curve_seg; + /* for curves, segment number in curve, ~0 for triangles */ + int segment; #endif /* parametric coordinates * - barycentric weights for triangles */ diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index afa5211216b..28742d56e3b 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -605,7 +605,7 @@ bool OSLRenderServices::get_object_standard_attribute(KernelGlobals *kg, ShaderD return set_attribute_int(3, type, derivatives, val); } else if ((name == u_geom_trianglevertices || name == u_geom_polyvertices) - && sd->curve_seg == ~0) { + && sd->segment == ~0) { float3 P[3]; triangle_vertices(kg, sd->prim, P); @@ -625,7 +625,7 @@ bool OSLRenderServices::get_object_standard_attribute(KernelGlobals *kg, ShaderD #ifdef __HAIR__ /* Hair Attributes */ else if (name == u_is_curve) { - float f = !(sd->curve_seg == ~0); + float f = (sd->segment != ~0); return set_attribute_float(f, type, derivatives, val); } else if (name == u_curve_thickness) { @@ -659,7 +659,7 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri { KernelGlobals *kg = kernel_globals; ShaderData *sd = (ShaderData *)renderstate; - int object, prim, curve_seg; + int object, prim, segment; /* lookup of attribute on another object */ if (object_name != u_empty || sd == NULL) { @@ -670,19 +670,19 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri object = it->second; prim = ~0; - curve_seg = ~0; + segment = ~0; } else { object = sd->object; prim = sd->prim; - curve_seg = sd->curve_seg; + segment = sd->segment; if (object == ~0) return get_background_attribute(kg, sd, name, type, derivatives, val); } /* find attribute on object */ - object = object*ATTR_PRIM_TYPES + (curve_seg != ~0); + object = object*ATTR_PRIM_TYPES + (segment != ~0); OSLGlobals::AttributeMap& attribute_map = kg->osl->attribute_map[object]; OSLGlobals::AttributeMap::iterator it = attribute_map.find(name); diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp index 18486eba114..59e307bb408 100644 --- a/intern/cycles/kernel/osl/osl_shader.cpp +++ b/intern/cycles/kernel/osl/osl_shader.cpp @@ -457,7 +457,7 @@ float3 OSLShader::volume_eval_phase(const ShaderClosure *sc, const float3 omega_ int OSLShader::find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeElement *elem) { /* for OSL, a hash map is used to lookup the attribute by name. */ - int object = sd->object*ATTR_PRIM_TYPES + (sd->curve_seg != ~0); + int object = sd->object*ATTR_PRIM_TYPES + (sd->segment != ~0); OSLGlobals::AttributeMap &attr_map = kg->osl->attribute_map[object]; ustring stdname(std::string("geom:") + std::string(Attribute::standard_name((AttributeStandard)id))); OSLGlobals::AttributeMap::const_iterator it = attr_map.find(stdname); diff --git a/intern/cycles/kernel/svm/svm_attribute.h b/intern/cycles/kernel/svm/svm_attribute.h index f11b69138d1..ea0a31610f1 100644 --- a/intern/cycles/kernel/svm/svm_attribute.h +++ b/intern/cycles/kernel/svm/svm_attribute.h @@ -28,7 +28,7 @@ __device void svm_node_attr_init(KernelGlobals *kg, ShaderData *sd, /* find attribute by unique id */ uint id = node.y; uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride; - attr_offset = (sd->curve_seg == ~0)? attr_offset: attr_offset + ATTR_PRIM_CURVE; + attr_offset = (sd->segment == ~0)? attr_offset: attr_offset + ATTR_PRIM_CURVE; uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset); while(attr_map.x != id) { diff --git a/intern/cycles/kernel/svm/svm_geometry.h b/intern/cycles/kernel/svm/svm_geometry.h index db8bbabe0ec..a04f4ea0fa7 100644 --- a/intern/cycles/kernel/svm/svm_geometry.h +++ b/intern/cycles/kernel/svm/svm_geometry.h @@ -155,7 +155,7 @@ __device void svm_node_hair_info(KernelGlobals *kg, ShaderData *sd, float *stack switch(type) { case NODE_INFO_CURVE_IS_STRAND: { - data = !(sd->curve_seg == ~0); + data = (sd->segment != ~0); stack_store_float(stack, out_offset, data); break; } diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp index 758e4e5e820..b6f6ba47fe8 100644 --- a/intern/cycles/render/attribute.cpp +++ b/intern/cycles/render/attribute.cpp @@ -80,7 +80,7 @@ size_t Attribute::element_size(int numverts, int numtris, int numcurves, int num return numtris; else if(element == ATTR_ELEMENT_CORNER) return numtris*3; - else if(element == ATTR_ELEMENT_CURVE_SEGMENT) + else if(element == ATTR_ELEMENT_CURVE) return numcurves; else if(element == ATTR_ELEMENT_CURVE_KEY) return numkeys; @@ -176,7 +176,7 @@ Attribute *AttributeSet::add(ustring name, TypeDesc type, AttributeElement eleme if(triangle_mesh) attr->reserve(triangle_mesh->verts.size(), triangle_mesh->triangles.size(), 0, 0); if(curve_mesh) - attr->reserve(0, 0, curve_mesh->curve_segments.size(), curve_mesh->curve_keys.size()); + attr->reserve(0, 0, curve_mesh->curves.size(), curve_mesh->curve_keys.size()); return attr; } @@ -239,9 +239,9 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name) } else if(curve_mesh) { if(std == ATTR_STD_UV) - attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_SEGMENT); + attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE); else if(std == ATTR_STD_GENERATED) - attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_SEGMENT); + attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE); else if(std == ATTR_STD_MOTION_PRE) attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_KEY); else if(std == ATTR_STD_MOTION_POST) @@ -298,7 +298,7 @@ void AttributeSet::reserve() if(triangle_mesh) attr.reserve(triangle_mesh->verts.size(), triangle_mesh->triangles.size(), 0, 0); if(curve_mesh) - attr.reserve(0, 0, curve_mesh->curve_segments.size(), curve_mesh->curve_keys.size()); + attr.reserve(0, 0, curve_mesh->curves.size(), curve_mesh->curve_keys.size()); } } diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index cab6008dd7c..c8e3e94ec98 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -171,13 +171,14 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen num_triangles++; } - /* disabled for strands*/ - /*for(size_t i = 0; i < mesh->curve_segments.size(); i++) { - * Shader *shader = scene->shaders[mesh->curve_segments[i].shader]; - * - * if(shader->sample_as_light && shader->has_surface_emission) - * num_curve_segments++; - }*/ + /* disabled for curves */ +#if 0 + foreach(Mesh::Curve& curve, mesh->curves) { + Shader *shader = scene->shaders[curve.shader]; + + if(shader->sample_as_light && shader->has_surface_emission) + num_curve_segments += curve.num_segments(); +#endif } } @@ -225,7 +226,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen if(shader->sample_as_light && shader->has_surface_emission) { distribution[offset].x = totarea; distribution[offset].y = __int_as_float(i + mesh->tri_offset); - distribution[offset].z = 1.0f; + distribution[offset].z = __int_as_float(~0); distribution[offset].w = __int_as_float(object_id); offset++; @@ -245,30 +246,38 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen } /*sample as light disabled for strands*/ - /*for(size_t i = 0; i < mesh->curve_segments.size(); i++) { - * Shader *shader = scene->shaders[mesh->curve_segments[i].shader]; - * - * if(shader->sample_as_light && shader->has_surface_emission) { - * distribution[offset].x = totarea; - * distribution[offset].y = __int_as_float(i + mesh->curveseg_offset); - * distribution[offset].z = 0.0f; - * distribution[offset].w = __int_as_float(object_id); - * offset++; - * - * Mesh::CurveSeg s = mesh->curve_segments[i]; - * float3 p1 = mesh->curve_keys[s.v[0]].loc; - * float r1 = mesh->curve_keys[s.v[0]].radius; - * float3 p2 = mesh->curve_keys[s.v[1]].loc; - * float r2 = mesh->curve_keys[s.v[1]].radius; - * - * if(!transform_applied) { - * p1 = transform_point(&tfm, p1); - * p2 = transform_point(&tfm, p2); - * } - * - * totarea += M_PI_F * (r1 + r2) * len(p1 - p2); - * } - }*/ +#if 0 + size_t i = 0; + + foreach(Mesh::Curve& curve, mesh->curves) { + Shader *shader = scene->shaders[curve.shader]; + int first_key = curve.first_key; + + if(shader->sample_as_light && shader->has_surface_emission) { + for(int j = 0; j < curve.num_segments(); j++) { + distribution[offset].x = totarea; + distribution[offset].y = __int_as_float(i + mesh->curve_offset); // XXX fix kernel code + distribution[offset].z = __int_as_float(j); + distribution[offset].w = __int_as_float(object_id); + offset++; + + float3 p1 = mesh->curve_keys[first_key + j].loc; + float r1 = mesh->curve_keys[first_key + j].radius; + float3 p2 = mesh->curve_keys[first_key + j + 1].loc; + float r2 = mesh->curve_keys[first_key + j + 1].radius; + + if(!transform_applied) { + p1 = transform_point(&tfm, p1); + p2 = transform_point(&tfm, p2); + } + + totarea += M_PI_F * (r1 + r2) * len(p1 - p2); + } + } + + i++; + } +#endif } if(progress.get_cancel()) return; diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index 53cae53ef69..d4619dcff55 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -51,7 +51,7 @@ Mesh::Mesh() tri_offset = 0; vert_offset = 0; - curveseg_offset = 0; + curve_offset = 0; curvekey_offset = 0; attributes.triangle_mesh = this; @@ -71,7 +71,7 @@ void Mesh::reserve(int numverts, int numtris, int numcurves, int numcurvekeys) shader.resize(numtris); smooth.resize(numtris); curve_keys.resize(numcurvekeys); - curve_segments.resize(numcurves); + curves.resize(numcurves); attributes.reserve(); curve_attributes.reserve(); @@ -86,7 +86,7 @@ void Mesh::clear() smooth.clear(); curve_keys.clear(); - curve_segments.clear(); + curves.clear(); attributes.clear(); curve_attributes.clear(); @@ -98,34 +98,33 @@ void Mesh::clear() void Mesh::add_triangle(int v0, int v1, int v2, int shader_, bool smooth_) { - Triangle t; - t.v[0] = v0; - t.v[1] = v1; - t.v[2] = v2; + Triangle tri; + tri.v[0] = v0; + tri.v[1] = v1; + tri.v[2] = v2; - triangles.push_back(t); + triangles.push_back(tri); shader.push_back(shader_); smooth.push_back(smooth_); } void Mesh::add_curve_key(float3 co, float radius) { - CurveKey ck; - ck.co = co; - ck.radius = radius; + CurveKey key; + key.co = co; + key.radius = radius; - curve_keys.push_back(ck); + curve_keys.push_back(key); } -void Mesh::add_curve_segment(int v0, int v1, int shader, int curveid) +void Mesh::add_curve(int first_key, int num_keys, int shader) { - CurveSegment s; - s.v[0] = v0; - s.v[1] = v1; - s.shader = shader; - s.curve = curveid; + Curve curve; + curve.first_key = first_key; + curve.num_keys = num_keys; + curve.shader = shader; - curve_segments.push_back(s); + curves.push_back(curve); } void Mesh::compute_bounds() @@ -284,7 +283,7 @@ void Mesh::pack_verts(float4 *tri_verts, float4 *tri_vindex, size_t vert_offset) } } -void Mesh::pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_seg_keys, size_t curvekey_offset) +void Mesh::pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_data, size_t curvekey_offset) { size_t curve_keys_size = curve_keys.size(); CurveKey *keys_ptr = NULL; @@ -302,25 +301,21 @@ void Mesh::pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_seg_key } /* pack curve segments */ - size_t curve_seg_num = curve_segments.size(); + size_t curve_num = curves.size(); - if(curve_seg_num) { - CurveSegment *curve_ptr = &curve_segments[0]; + if(curve_num) { + Curve *curve_ptr = &curves[0]; int shader_id = 0; - for(size_t i = 0; i < curve_seg_num; i++) { - CurveSegment s = curve_ptr[i]; - shader_id = scene->shader_manager->get_shader_id(s.shader, this, false); + for(size_t i = 0; i < curve_num; i++) { + Curve curve = curve_ptr[i]; + shader_id = scene->shader_manager->get_shader_id(curve.shader, this, false); - float3 p1 = keys_ptr[s.v[0]].co; - float3 p2 = keys_ptr[s.v[1]].co; - float length = len(p2 - p1); - - curve_seg_keys[i] = make_float4( - __int_as_float(s.v[0] + curvekey_offset), - __int_as_float(s.v[1] + curvekey_offset), + curve_data[i] = make_float4( + __int_as_float(curve.first_key + curvekey_offset), + __int_as_float(curve.num_keys), __int_as_float(shader_id), - length); + 0.0f); } } } @@ -541,7 +536,7 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce index++; - if(mesh->curve_segments.size()) { + if(mesh->curves.size()) { attr_map[index].x = id; attr_map[index].y = req.curve_element; attr_map[index].z = as_uint(req.curve_offset); @@ -588,7 +583,7 @@ static void update_attribute_element_offset(Mesh *mesh, vector<float>& attr_floa size_t size = mattr->element_size( mesh->verts.size(), mesh->triangles.size(), - mesh->curve_segments.size(), + mesh->curves.size(), mesh->curve_keys.size()); if(mattr->type == TypeDesc::TypeFloat) { @@ -618,8 +613,8 @@ static void update_attribute_element_offset(Mesh *mesh, vector<float>& attr_floa offset -= mesh->tri_offset; else if(element == ATTR_ELEMENT_CORNER) offset -= 3*mesh->tri_offset; - else if(element == ATTR_ELEMENT_CURVE_SEGMENT) - offset -= mesh->curveseg_offset; + else if(element == ATTR_ELEMENT_CURVE) + offset -= mesh->curve_offset; else if(element == ATTR_ELEMENT_CURVE_KEY) offset -= mesh->curvekey_offset; } @@ -713,20 +708,20 @@ void MeshManager::device_update_mesh(Device *device, DeviceScene *dscene, Scene size_t tri_size = 0; size_t curve_key_size = 0; - size_t curve_seg_keys = 0; + size_t curve_size = 0; foreach(Mesh *mesh, scene->meshes) { mesh->vert_offset = vert_size; mesh->tri_offset = tri_size; mesh->curvekey_offset = curve_key_size; - mesh->curveseg_offset = curve_seg_keys; + mesh->curve_offset = curve_size; vert_size += mesh->verts.size(); tri_size += mesh->triangles.size(); curve_key_size += mesh->curve_keys.size(); - curve_seg_keys += mesh->curve_segments.size(); + curve_size += mesh->curves.size(); } if(tri_size != 0) { @@ -754,19 +749,19 @@ void MeshManager::device_update_mesh(Device *device, DeviceScene *dscene, Scene device->tex_alloc("__tri_vindex", dscene->tri_vindex); } - if(curve_seg_keys != 0) { + if(curve_size != 0) { progress.set_status("Updating Mesh", "Copying Strands to device"); float4 *curve_keys = dscene->curve_keys.resize(curve_key_size); - float4 *curve_segments = dscene->curve_segments.resize(curve_seg_keys); + float4 *curves = dscene->curves.resize(curve_size); foreach(Mesh *mesh, scene->meshes) { - mesh->pack_curves(scene, &curve_keys[mesh->curvekey_offset], &curve_segments[mesh->curveseg_offset], mesh->curvekey_offset); + mesh->pack_curves(scene, &curve_keys[mesh->curvekey_offset], &curves[mesh->curve_offset], mesh->curvekey_offset); if(progress.get_cancel()) return; } device->tex_alloc("__curve_keys", dscene->curve_keys); - device->tex_alloc("__curve_segments", dscene->curve_segments); + device->tex_alloc("__curves", dscene->curves); } } @@ -804,9 +799,9 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene * dscene->tri_woop.reference(&pack.tri_woop[0], pack.tri_woop.size()); device->tex_alloc("__tri_woop", dscene->tri_woop); } - if(pack.prim_type.size()) { - dscene->prim_type.reference((uint*)&pack.prim_type[0], pack.prim_type.size()); - device->tex_alloc("__prim_type", dscene->prim_type); + if(pack.prim_segment.size()) { + dscene->prim_segment.reference((uint*)&pack.prim_segment[0], pack.prim_segment.size()); + device->tex_alloc("__prim_segment", dscene->prim_segment); } if(pack.prim_visibility.size()) { dscene->prim_visibility.reference((uint*)&pack.prim_visibility[0], pack.prim_visibility.size()); @@ -917,7 +912,7 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene) device->tex_free(dscene->bvh_nodes); device->tex_free(dscene->object_node); device->tex_free(dscene->tri_woop); - device->tex_free(dscene->prim_type); + device->tex_free(dscene->prim_segment); device->tex_free(dscene->prim_visibility); device->tex_free(dscene->prim_index); device->tex_free(dscene->prim_object); @@ -925,7 +920,7 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene) device->tex_free(dscene->tri_vnormal); device->tex_free(dscene->tri_vindex); device->tex_free(dscene->tri_verts); - device->tex_free(dscene->curve_segments); + device->tex_free(dscene->curves); device->tex_free(dscene->curve_keys); device->tex_free(dscene->attributes_map); device->tex_free(dscene->attributes_float); @@ -934,7 +929,7 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene) dscene->bvh_nodes.clear(); dscene->object_node.clear(); dscene->tri_woop.clear(); - dscene->prim_type.clear(); + dscene->prim_segment.clear(); dscene->prim_visibility.clear(); dscene->prim_index.clear(); dscene->prim_object.clear(); @@ -942,7 +937,7 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene) dscene->tri_vnormal.clear(); dscene->tri_vindex.clear(); dscene->tri_verts.clear(); - dscene->curve_segments.clear(); + dscene->curves.clear(); dscene->curve_keys.clear(); dscene->attributes_map.clear(); dscene->attributes_float.clear(); diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h index ca8c755671f..b83752ad8df 100644 --- a/intern/cycles/render/mesh.h +++ b/intern/cycles/render/mesh.h @@ -51,10 +51,13 @@ public: }; /* Mesh Curve */ - struct CurveSegment { - int v[2]; + struct Curve { + int first_key; + int num_keys; uint shader; - int curve; + uint pad; + + int num_segments() { return num_keys - 1; } }; struct CurveKey { @@ -78,7 +81,7 @@ public: vector<bool> smooth; vector<CurveKey> curve_keys; - vector<CurveSegment> curve_segments; + vector<Curve> curves; vector<uint> used_shaders; AttributeSet attributes; @@ -98,7 +101,7 @@ public: size_t tri_offset; size_t vert_offset; - size_t curveseg_offset; + size_t curve_offset; size_t curvekey_offset; /* Functions */ @@ -109,7 +112,7 @@ public: void clear(); void add_triangle(int v0, int v1, int v2, int shader, bool smooth); void add_curve_key(float3 loc, float radius); - void add_curve_segment(int v0, int v1, int shader, int curveid); + void add_curve(int first_key, int num_keys, int shader); void compute_bounds(); void add_face_normals(); @@ -117,7 +120,7 @@ public: void pack_normals(Scene *scene, float4 *normal, float4 *vnormal); void pack_verts(float4 *tri_verts, float4 *tri_vindex, size_t vert_offset); - void pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_seg_keys, size_t curvekey_offset); + void pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_data, size_t curvekey_offset); void compute_bvh(SceneParams *params, Progress *progress, int n, int total); bool need_attribute(Scene *scene, AttributeStandard std); diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 4862b47c342..a89f8afd251 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -203,14 +203,18 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene surface_area += triangle_area(p1, p2, p3); } - foreach(Mesh::CurveSegment& t, mesh->curve_segments) { - float3 p1 = mesh->curve_keys[t.v[0]].co; - float r1 = mesh->curve_keys[t.v[0]].radius; - float3 p2 = mesh->curve_keys[t.v[1]].co; - float r2 = mesh->curve_keys[t.v[1]].radius; - - /* currently ignores segment overlaps*/ - surface_area += M_PI_F *(r1 + r2) * len(p1 - p2); + foreach(Mesh::Curve& curve, mesh->curves) { + int first_key = curve.first_key; + + for(int i = 0; i < curve.num_segments(); i++) { + float3 p1 = mesh->curve_keys[first_key + i].co; + float r1 = mesh->curve_keys[first_key + i].radius; + float3 p2 = mesh->curve_keys[first_key + i + 1].co; + float r2 = mesh->curve_keys[first_key + i + 1].radius; + + /* currently ignores segment overlaps*/ + surface_area += M_PI_F *(r1 + r2) * len(p1 - p2); + } } surface_area_map[mesh] = surface_area; @@ -229,14 +233,21 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene surface_area += triangle_area(p1, p2, p3); } - foreach(Mesh::CurveSegment& t, mesh->curve_segments) { - float3 p1 = mesh->curve_keys[t.v[0]].co; - float r1 = mesh->curve_keys[t.v[0]].radius; - float3 p2 = mesh->curve_keys[t.v[1]].co; - float r2 = mesh->curve_keys[t.v[1]].radius; + foreach(Mesh::Curve& curve, mesh->curves) { + int first_key = curve.first_key; + + for(int i = 0; i < curve.num_segments(); i++) { + float3 p1 = mesh->curve_keys[first_key + i].co; + float r1 = mesh->curve_keys[first_key + i].radius; + float3 p2 = mesh->curve_keys[first_key + i + 1].co; + float r2 = mesh->curve_keys[first_key + i + 1].radius; - /* currently ignores segment overlaps*/ - surface_area += M_PI_F *(r1 + r2) * len(p1 - p2); + p1 = transform_point(&tfm, p1); + p2 = transform_point(&tfm, p2); + + /* currently ignores segment overlaps*/ + surface_area += M_PI_F *(r1 + r2) * len(p1 - p2); + } } } diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index 9490fd96be0..f6e1daea80d 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -62,7 +62,7 @@ public: device_vector<float4> bvh_nodes; device_vector<uint> object_node; device_vector<float4> tri_woop; - device_vector<uint> prim_type; + device_vector<uint> prim_segment; device_vector<uint> prim_visibility; device_vector<uint> prim_index; device_vector<uint> prim_object; @@ -73,7 +73,7 @@ public: device_vector<float4> tri_vindex; device_vector<float4> tri_verts; - device_vector<float4> curve_segments; + device_vector<float4> curves; device_vector<float4> curve_keys; /* objects */ |