From bf25f1ea96d01b513907cf3067e8e2dd3c7e41b4 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 3 Jan 2013 12:09:09 +0000 Subject: Cycles Hair: refactoring to store curves with the index of the first key and the number of keys in the curve, rather than curve segments with the indices of two keys. ShaderData.segment now stores the segment number in the curve. --- intern/cycles/blender/blender_curves.cpp | 28 ++++----- intern/cycles/bvh/bvh.cpp | 64 ++++++++++---------- intern/cycles/bvh/bvh.h | 4 +- intern/cycles/bvh/bvh_build.cpp | 62 +++++++++++-------- intern/cycles/bvh/bvh_build.h | 4 +- intern/cycles/bvh/bvh_params.h | 8 +-- intern/cycles/bvh/bvh_sort.cpp | 4 +- intern/cycles/bvh/bvh_split.cpp | 16 ++--- intern/cycles/kernel/kernel_bvh.h | 47 ++++++++------- intern/cycles/kernel/kernel_curve.h | 43 +++++++------- intern/cycles/kernel/kernel_emission.h | 2 +- intern/cycles/kernel/kernel_light.h | 26 ++++---- intern/cycles/kernel/kernel_primitive.h | 8 +-- intern/cycles/kernel/kernel_shader.h | 32 +++++----- intern/cycles/kernel/kernel_textures.h | 4 +- intern/cycles/kernel/kernel_types.h | 7 ++- intern/cycles/kernel/osl/osl_services.cpp | 12 ++-- intern/cycles/kernel/osl/osl_shader.cpp | 2 +- intern/cycles/kernel/svm/svm_attribute.h | 2 +- intern/cycles/kernel/svm/svm_geometry.h | 2 +- intern/cycles/render/attribute.cpp | 10 ++-- intern/cycles/render/light.cpp | 73 +++++++++++++---------- intern/cycles/render/mesh.cpp | 99 +++++++++++++++---------------- intern/cycles/render/mesh.h | 17 +++--- intern/cycles/render/object.cpp | 41 ++++++++----- intern/cycles/render/scene.h | 4 +- 26 files changed, 331 insertions(+), 290 deletions(-) (limited to 'intern') 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 prim_type; + vector prim_segment; vector prim_index; vector 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 tri_woop; /* primitive type - triangle or strand (should be moved to flag?) */ - array prim_type; + array prim_segment; /* visibility visibilitys for primitives */ array 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& objects_, - vector& prim_type_, vector& prim_index_, vector& prim_object_, + vector& prim_segment_, vector& prim_index_, vector& 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& p_type = prim_type; + vector& p_segment = prim_segment; vector& p_index = prim_index; vector& 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& objects, - vector& prim_type, + vector& prim_segment, vector& prim_index, vector& prim_object, const BVHParams& params, @@ -88,7 +88,7 @@ protected: int num_original_references; /* output primitive indexes and objects */ - vector& prim_type; + vector& prim_segment; vector& prim_index; vector& 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& 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& 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 smooth; vector curve_keys; - vector curve_segments; + vector curves; vector 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 bvh_nodes; device_vector object_node; device_vector tri_woop; - device_vector prim_type; + device_vector prim_segment; device_vector prim_visibility; device_vector prim_index; device_vector prim_object; @@ -73,7 +73,7 @@ public: device_vector tri_vindex; device_vector tri_verts; - device_vector curve_segments; + device_vector curves; device_vector curve_keys; /* objects */ -- cgit v1.2.3