Cycles code refactor: changes to make adding new primitive types easier.

This commit is contained in:
Brecht Van Lommel 2014-03-29 13:03:46 +01:00
parent 24ad7e0bea
commit 0509553b5e
24 changed files with 191 additions and 189 deletions

@ -97,7 +97,7 @@ bool BVH::cache_read(CacheData& key)
value.read(pack.nodes); value.read(pack.nodes);
value.read(pack.object_node); value.read(pack.object_node);
value.read(pack.tri_woop); value.read(pack.tri_woop);
value.read(pack.prim_segment); value.read(pack.prim_type);
value.read(pack.prim_visibility); value.read(pack.prim_visibility);
value.read(pack.prim_index); value.read(pack.prim_index);
value.read(pack.prim_object); value.read(pack.prim_object);
@ -119,7 +119,7 @@ void BVH::cache_write(CacheData& key)
value.add(pack.nodes); value.add(pack.nodes);
value.add(pack.object_node); value.add(pack.object_node);
value.add(pack.tri_woop); value.add(pack.tri_woop);
value.add(pack.prim_segment); value.add(pack.prim_type);
value.add(pack.prim_visibility); value.add(pack.prim_visibility);
value.add(pack.prim_index); value.add(pack.prim_index);
value.add(pack.prim_object); value.add(pack.prim_object);
@ -165,11 +165,11 @@ void BVH::build(Progress& progress)
} }
/* build nodes */ /* build nodes */
vector<int> prim_segment; vector<int> prim_type;
vector<int> prim_index; vector<int> prim_index;
vector<int> prim_object; vector<int> prim_object;
BVHBuild bvh_build(objects, prim_segment, prim_index, prim_object, params, progress); BVHBuild bvh_build(objects, prim_type, prim_index, prim_object, params, progress);
BVHNode *root = bvh_build.run(); BVHNode *root = bvh_build.run();
if(progress.get_cancel()) { if(progress.get_cancel()) {
@ -178,7 +178,7 @@ void BVH::build(Progress& progress)
} }
/* todo: get rid of this copy */ /* todo: get rid of this copy */
pack.prim_segment = prim_segment; pack.prim_type = prim_type;
pack.prim_index = prim_index; pack.prim_index = prim_index;
pack.prim_object = prim_object; pack.prim_object = prim_object;
@ -280,7 +280,7 @@ void BVH::pack_curve_segment(int idx, float4 woop[3])
int tob = pack.prim_object[idx]; int tob = pack.prim_object[idx];
const Mesh *mesh = objects[tob]->mesh; const Mesh *mesh = objects[tob]->mesh;
int tidx = pack.prim_index[idx]; int tidx = pack.prim_index[idx];
int segment = pack.prim_segment[idx]; int segment = PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[idx]);
int k0 = mesh->curves[tidx].first_key + segment; int k0 = mesh->curves[tidx].first_key + segment;
int k1 = mesh->curves[tidx].first_key + segment + 1; int k1 = mesh->curves[tidx].first_key + segment + 1;
float3 v0 = mesh->curve_keys[k0].co; float3 v0 = mesh->curve_keys[k0].co;
@ -324,7 +324,7 @@ void BVH::pack_primitives()
if(pack.prim_index[i] != -1) { if(pack.prim_index[i] != -1) {
float4 woop[3]; float4 woop[3];
if(pack.prim_segment[i] != ~0) if(pack.prim_type[i] & PRIMITIVE_ALL_CURVE)
pack_curve_segment(i, woop); pack_curve_segment(i, woop);
else else
pack_triangle(i, woop); pack_triangle(i, woop);
@ -335,7 +335,7 @@ void BVH::pack_primitives()
Object *ob = objects[tob]; Object *ob = objects[tob];
pack.prim_visibility[i] = ob->visibility; pack.prim_visibility[i] = ob->visibility;
if(pack.prim_segment[i] != ~0) if(pack.prim_type[i] & PRIMITIVE_ALL_CURVE)
pack.prim_visibility[i] |= PATH_RAY_CURVE; pack.prim_visibility[i] |= PATH_RAY_CURVE;
} }
else { else {
@ -359,7 +359,7 @@ void BVH::pack_instances(size_t nodes_size)
* meshes with transform applied and already in the top level BVH */ * meshes with transform applied and already in the top level BVH */
for(size_t i = 0; i < pack.prim_index.size(); i++) for(size_t i = 0; i < pack.prim_index.size(); i++)
if(pack.prim_index[i] != -1) { if(pack.prim_index[i] != -1) {
if(pack.prim_segment[i] != ~0) if(pack.prim_type[i] & PRIMITIVE_ALL_CURVE)
pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->curve_offset; pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->curve_offset;
else else
pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->tri_offset; pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->tri_offset;
@ -401,7 +401,7 @@ void BVH::pack_instances(size_t nodes_size)
mesh_map.clear(); mesh_map.clear();
pack.prim_index.resize(prim_index_size); pack.prim_index.resize(prim_index_size);
pack.prim_segment.resize(prim_index_size); pack.prim_type.resize(prim_index_size);
pack.prim_object.resize(prim_index_size); pack.prim_object.resize(prim_index_size);
pack.prim_visibility.resize(prim_index_size); pack.prim_visibility.resize(prim_index_size);
pack.tri_woop.resize(tri_woop_size); pack.tri_woop.resize(tri_woop_size);
@ -409,7 +409,7 @@ void BVH::pack_instances(size_t nodes_size)
pack.object_node.resize(objects.size()); pack.object_node.resize(objects.size());
int *pack_prim_index = (pack.prim_index.size())? &pack.prim_index[0]: NULL; int *pack_prim_index = (pack.prim_index.size())? &pack.prim_index[0]: NULL;
int *pack_prim_segment = (pack.prim_segment.size())? &pack.prim_segment[0]: NULL; int *pack_prim_type = (pack.prim_type.size())? &pack.prim_type[0]: NULL;
int *pack_prim_object = (pack.prim_object.size())? &pack.prim_object[0]: NULL; 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; 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; float4 *pack_tri_woop = (pack.tri_woop.size())? &pack.tri_woop[0]: NULL;
@ -454,16 +454,16 @@ void BVH::pack_instances(size_t nodes_size)
if(bvh->pack.prim_index.size()) { if(bvh->pack.prim_index.size()) {
size_t bvh_prim_index_size = 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_index = &bvh->pack.prim_index[0];
int *bvh_prim_segment = &bvh->pack.prim_segment[0]; int *bvh_prim_type = &bvh->pack.prim_type[0];
uint *bvh_prim_visibility = &bvh->pack.prim_visibility[0]; uint *bvh_prim_visibility = &bvh->pack.prim_visibility[0];
for(size_t i = 0; i < bvh_prim_index_size; i++) { for(size_t i = 0; i < bvh_prim_index_size; i++) {
if(bvh->pack.prim_segment[i] != ~0) if(bvh->pack.prim_type[i] & PRIMITIVE_ALL_CURVE)
pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_curve_offset; pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_curve_offset;
else else
pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_tri_offset; pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_tri_offset;
pack_prim_segment[pack_prim_index_offset] = bvh_prim_segment[i]; pack_prim_type[pack_prim_index_offset] = bvh_prim_type[i];
pack_prim_visibility[pack_prim_index_offset] = bvh_prim_visibility[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_object[pack_prim_index_offset] = 0; // unused for instances
pack_prim_index_offset++; pack_prim_index_offset++;
@ -629,10 +629,10 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility
/* primitives */ /* primitives */
const Mesh *mesh = ob->mesh; const Mesh *mesh = ob->mesh;
if(pack.prim_segment[prim] != ~0) { if(pack.prim_type[prim] & PRIMITIVE_ALL_CURVE) {
/* curves */ /* curves */
int str_offset = (params.top_level)? mesh->curve_offset: 0; 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 k0 = mesh->curves[pidx - str_offset].first_key + PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[prim]);
int k1 = k0 + 1; int k1 = k0 + 1;
float3 p[4]; float3 p[4];

@ -52,8 +52,8 @@ struct PackedBVH {
array<int> object_node; array<int> object_node;
/* precomputed triangle intersection data, one triangle is 4x float4 */ /* precomputed triangle intersection data, one triangle is 4x float4 */
array<float4> tri_woop; array<float4> tri_woop;
/* primitive type - triangle or strand (should be moved to flag?) */ /* primitive type - triangle or strand */
array<int> prim_segment; array<int> prim_type;
/* visibility visibilitys for primitives */ /* visibility visibilitys for primitives */
array<uint> prim_visibility; array<uint> prim_visibility;
/* mapping from BVH primitive index to true primitive index, as primitives /* mapping from BVH primitive index to true primitive index, as primitives

@ -49,10 +49,10 @@ public:
/* Constructor / Destructor */ /* Constructor / Destructor */
BVHBuild::BVHBuild(const vector<Object*>& objects_, BVHBuild::BVHBuild(const vector<Object*>& objects_,
vector<int>& prim_segment_, vector<int>& prim_index_, vector<int>& prim_object_, vector<int>& prim_type_, vector<int>& prim_index_, vector<int>& prim_object_,
const BVHParams& params_, Progress& progress_) const BVHParams& params_, Progress& progress_)
: objects(objects_), : objects(objects_),
prim_segment(prim_segment_), prim_type(prim_type_),
prim_index(prim_index_), prim_index(prim_index_),
prim_object(prim_object_), prim_object(prim_object_),
params(params_), params(params_),
@ -73,6 +73,7 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh,
for(uint j = 0; j < mesh->triangles.size(); j++) { for(uint j = 0; j < mesh->triangles.size(); j++) {
Mesh::Triangle t = mesh->triangles[j]; Mesh::Triangle t = mesh->triangles[j];
BoundBox bounds = BoundBox::empty; BoundBox bounds = BoundBox::empty;
PrimitiveType type = PRIMITIVE_TRIANGLE;
for(int k = 0; k < 3; k++) { for(int k = 0; k < 3; k++) {
float3 co = mesh->verts[t.v[k]]; float3 co = mesh->verts[t.v[k]];
@ -80,7 +81,7 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh,
} }
if(bounds.valid()) { if(bounds.valid()) {
references.push_back(BVHReference(bounds, j, i, ~0)); references.push_back(BVHReference(bounds, j, i, type));
root.grow(bounds); root.grow(bounds);
center.grow(bounds.center2()); center.grow(bounds.center2());
} }
@ -88,6 +89,7 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh,
for(uint j = 0; j < mesh->curves.size(); j++) { for(uint j = 0; j < mesh->curves.size(); j++) {
Mesh::Curve curve = mesh->curves[j]; Mesh::Curve curve = mesh->curves[j];
PrimitiveType type = PRIMITIVE_CURVE;
for(int k = 0; k < curve.num_keys - 1; k++) { for(int k = 0; k < curve.num_keys - 1; k++) {
BoundBox bounds = BoundBox::empty; BoundBox bounds = BoundBox::empty;
@ -108,7 +110,9 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh,
bounds.grow(upper, mr); bounds.grow(upper, mr);
if(bounds.valid()) { if(bounds.valid()) {
references.push_back(BVHReference(bounds, j, i, k)); int packed_type = PRIMITIVE_PACK_SEGMENT(type, k);
references.push_back(BVHReference(bounds, j, i, packed_type));
root.grow(bounds); root.grow(bounds);
center.grow(bounds.center2()); center.grow(bounds.center2());
} }
@ -118,7 +122,7 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh,
void BVHBuild::add_reference_object(BoundBox& root, BoundBox& center, Object *ob, int i) void BVHBuild::add_reference_object(BoundBox& root, BoundBox& center, Object *ob, int i)
{ {
references.push_back(BVHReference(ob->bounds, -1, i, false)); references.push_back(BVHReference(ob->bounds, -1, i, 0));
root.grow(ob->bounds); root.grow(ob->bounds);
center.grow(ob->bounds.center2()); center.grow(ob->bounds.center2());
} }
@ -207,7 +211,7 @@ BVHNode* BVHBuild::run()
progress_total = references.size(); progress_total = references.size();
progress_original_total = progress_total; progress_original_total = progress_total;
prim_segment.resize(references.size()); prim_type.resize(references.size());
prim_index.resize(references.size()); prim_index.resize(references.size());
prim_object.resize(references.size()); prim_object.resize(references.size());
@ -373,12 +377,12 @@ BVHNode *BVHBuild::create_object_leaf_nodes(const BVHReference *ref, int start,
if(start == prim_index.size()) { if(start == prim_index.size()) {
assert(params.use_spatial_split); assert(params.use_spatial_split);
prim_segment.push_back(ref->prim_segment()); prim_type.push_back(ref->prim_type());
prim_index.push_back(ref->prim_index()); prim_index.push_back(ref->prim_index());
prim_object.push_back(ref->prim_object()); prim_object.push_back(ref->prim_object());
} }
else { else {
prim_segment[start] = ref->prim_segment(); prim_type[start] = ref->prim_type();
prim_index[start] = ref->prim_index(); prim_index[start] = ref->prim_index();
prim_object[start] = ref->prim_object(); prim_object[start] = ref->prim_object();
} }
@ -401,7 +405,7 @@ BVHNode *BVHBuild::create_object_leaf_nodes(const BVHReference *ref, int start,
BVHNode* BVHBuild::create_leaf_node(const BVHRange& range) BVHNode* BVHBuild::create_leaf_node(const BVHRange& range)
{ {
vector<int>& p_segment = prim_segment; vector<int>& p_type = prim_type;
vector<int>& p_index = prim_index; vector<int>& p_index = prim_index;
vector<int>& p_object = prim_object; vector<int>& p_object = prim_object;
BoundBox bounds = BoundBox::empty; BoundBox bounds = BoundBox::empty;
@ -415,12 +419,12 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range)
if(range.start() + num == prim_index.size()) { if(range.start() + num == prim_index.size()) {
assert(params.use_spatial_split); assert(params.use_spatial_split);
p_segment.push_back(ref.prim_segment()); p_type.push_back(ref.prim_type());
p_index.push_back(ref.prim_index()); p_index.push_back(ref.prim_index());
p_object.push_back(ref.prim_object()); p_object.push_back(ref.prim_object());
} }
else { else {
p_segment[range.start() + num] = ref.prim_segment(); p_type[range.start() + num] = ref.prim_type();
p_index[range.start() + num] = ref.prim_index(); p_index[range.start() + num] = ref.prim_index();
p_object[range.start() + num] = ref.prim_object(); p_object[range.start() + num] = ref.prim_object();
} }

@ -44,7 +44,7 @@ public:
/* Constructor/Destructor */ /* Constructor/Destructor */
BVHBuild( BVHBuild(
const vector<Object*>& objects, const vector<Object*>& objects,
vector<int>& prim_segment, vector<int>& prim_type,
vector<int>& prim_index, vector<int>& prim_index,
vector<int>& prim_object, vector<int>& prim_object,
const BVHParams& params, const BVHParams& params,
@ -88,7 +88,7 @@ protected:
int num_original_references; int num_original_references;
/* output primitive indexes and objects */ /* output primitive indexes and objects */
vector<int>& prim_segment; vector<int>& prim_type;
vector<int>& prim_index; vector<int>& prim_index;
vector<int>& prim_object; vector<int>& prim_object;

@ -98,22 +98,22 @@ class BVHReference
public: public:
__forceinline BVHReference() {} __forceinline BVHReference() {}
__forceinline BVHReference(const BoundBox& bounds_, int prim_index_, int prim_object_, int prim_segment) __forceinline BVHReference(const BoundBox& bounds_, int prim_index_, int prim_object_, int prim_type)
: rbounds(bounds_) : rbounds(bounds_)
{ {
rbounds.min.w = __int_as_float(prim_index_); rbounds.min.w = __int_as_float(prim_index_);
rbounds.max.w = __int_as_float(prim_object_); rbounds.max.w = __int_as_float(prim_object_);
segment = prim_segment; type = prim_type;
} }
__forceinline const BoundBox& bounds() const { return rbounds; } __forceinline const BoundBox& bounds() const { return rbounds; }
__forceinline int prim_index() const { return __float_as_int(rbounds.min.w); } __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_object() const { return __float_as_int(rbounds.max.w); }
__forceinline int prim_segment() const { return segment; } __forceinline int prim_type() const { return type; }
protected: protected:
BoundBox rbounds; BoundBox rbounds;
uint segment; uint type;
}; };
/* BVH Range /* BVH Range

@ -52,8 +52,8 @@ public:
else if(ra.prim_object() > rb.prim_object()) return false; 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 true;
else if(ra.prim_index() > rb.prim_index()) return false; else if(ra.prim_index() > rb.prim_index()) return false;
else if(ra.prim_segment() < rb.prim_segment()) return true; else if(ra.prim_type() < rb.prim_type()) return true;
else if(ra.prim_segment() > rb.prim_segment()) return false; else if(ra.prim_type() > rb.prim_type()) return false;
return false; return false;
} }

@ -253,7 +253,7 @@ void BVHSpatialSplit::split_reference(BVHBuild *builder, BVHReference& left, BVH
Object *ob = builder->objects[ref.prim_object()]; Object *ob = builder->objects[ref.prim_object()];
const Mesh *mesh = ob->mesh; const Mesh *mesh = ob->mesh;
if (ref.prim_segment() == ~0) { if (ref.prim_type() & PRIMITIVE_ALL_TRIANGLE) {
const int *inds = mesh->triangles[ref.prim_index()].v; const int *inds = mesh->triangles[ref.prim_index()].v;
const float3 *verts = &mesh->verts[0]; const float3 *verts = &mesh->verts[0];
const float3* v1 = &verts[inds[2]]; const float3* v1 = &verts[inds[2]];
@ -282,7 +282,7 @@ void BVHSpatialSplit::split_reference(BVHBuild *builder, BVHReference& left, BVH
} }
else { else {
/* curve split: NOTE - Currently ignores curve width and needs to be fixed.*/ /* 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 k0 = mesh->curves[ref.prim_index()].first_key + PRIMITIVE_UNPACK_SEGMENT(ref.prim_type());
const int k1 = k0 + 1; const int k1 = k0 + 1;
const float3* v0 = &mesh->curve_keys[k0].co; const float3* v0 = &mesh->curve_keys[k0].co;
const float3* v1 = &mesh->curve_keys[k1].co; const float3* v1 = &mesh->curve_keys[k1].co;
@ -318,8 +318,8 @@ void BVHSpatialSplit::split_reference(BVHBuild *builder, BVHReference& left, BVH
right_bounds.intersect(ref.bounds()); right_bounds.intersect(ref.bounds());
/* set references */ /* set references */
left = BVHReference(left_bounds, ref.prim_index(), ref.prim_object(), ref.prim_segment()); 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_segment()); right = BVHReference(right_bounds, ref.prim_index(), ref.prim_object(), ref.prim_type());
} }
CCL_NAMESPACE_END CCL_NAMESPACE_END

@ -204,19 +204,23 @@ ccl_device uint BVH_FUNCTION_NAME(KernelGlobals *kg, const Ray *ray, Intersectio
/* primitive intersection */ /* primitive intersection */
for(; primAddr < primAddr2; primAddr++) { for(; primAddr < primAddr2; primAddr++) {
#if FEATURE(BVH_HAIR)
uint segment = kernel_tex_fetch(__prim_segment, primAddr);
if(segment != ~0)
continue;
#endif
/* only primitives from the same object */ /* only primitives from the same object */
uint tri_object = (object == ~0)? kernel_tex_fetch(__prim_object, primAddr): object; uint tri_object = (object == ~0)? kernel_tex_fetch(__prim_object, primAddr): object;
if(tri_object == subsurface_object) { if(tri_object != subsurface_object)
continue;
/* intersect ray against primitive */ /* intersect ray against primitive */
triangle_intersect_subsurface(kg, isect_array, P, idir, object, primAddr, isect_t, &num_hits, lcg_state, max_hits); uint type = kernel_tex_fetch(__prim_type, primAddr);
switch(type & PRIMITIVE_ALL) {
case PRIMITIVE_TRIANGLE: {
triangle_intersect_subsurface(kg, isect_array, P, idir, object, primAddr, isect_t, &num_hits, lcg_state, max_hits);
break;
}
default: {
break;
}
} }
} }
} }

@ -249,26 +249,35 @@ ccl_device bool BVH_FUNCTION_NAME
/* primitive intersection */ /* primitive intersection */
while(primAddr < primAddr2) { while(primAddr < primAddr2) {
bool hit; bool hit;
uint type = kernel_tex_fetch(__prim_type, primAddr);
/* intersect ray against primitive */ switch(type & PRIMITIVE_ALL) {
case PRIMITIVE_TRIANGLE: {
hit = triangle_intersect(kg, isect, P, idir, visibility, object, primAddr);
break;
}
#if FEATURE(BVH_HAIR) #if FEATURE(BVH_HAIR)
uint segment = kernel_tex_fetch(__prim_segment, primAddr); case PRIMITIVE_CURVE: {
if(segment != ~0) {
if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
#if FEATURE(BVH_HAIR_MINIMUM_WIDTH) #if FEATURE(BVH_HAIR_MINIMUM_WIDTH)
hit = bvh_cardinal_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, ray->time, segment, lcg_state, difl, extmax); if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
else hit = bvh_cardinal_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax);
hit = bvh_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, ray->time, segment, lcg_state, difl, extmax); else
hit = bvh_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax);
#else #else
hit = bvh_cardinal_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, ray->time, segment); if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
else hit = bvh_cardinal_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, ray->time, type);
hit = bvh_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, ray->time, segment); else
hit = bvh_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, ray->time, type);
#endif #endif
break;
}
#endif
default: {
hit = false;
break;
}
} }
else
#endif
hit = triangle_intersect(kg, isect, P, idir, visibility, object, primAddr);
/* shadow ray early termination */ /* shadow ray early termination */
#if defined(__KERNEL_SSE2__) #if defined(__KERNEL_SSE2__)

@ -30,7 +30,7 @@ ccl_device float curve_attribute_float(KernelGlobals *kg, const ShaderData *sd,
} }
else if(elem == ATTR_ELEMENT_CURVE_KEY || elem == ATTR_ELEMENT_CURVE_KEY_MOTION) { else if(elem == ATTR_ELEMENT_CURVE_KEY || elem == ATTR_ELEMENT_CURVE_KEY_MOTION) {
float4 curvedata = kernel_tex_fetch(__curves, sd->prim); float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
int k0 = __float_as_int(curvedata.x) + sd->segment; int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
int k1 = k0 + 1; int k1 = k0 + 1;
float f0 = kernel_tex_fetch(__attributes_float, offset + k0); float f0 = kernel_tex_fetch(__attributes_float, offset + k0);
@ -69,7 +69,7 @@ ccl_device float3 curve_attribute_float3(KernelGlobals *kg, const ShaderData *sd
} }
else if(elem == ATTR_ELEMENT_CURVE_KEY || elem == ATTR_ELEMENT_CURVE_KEY_MOTION) { else if(elem == ATTR_ELEMENT_CURVE_KEY || elem == ATTR_ELEMENT_CURVE_KEY_MOTION) {
float4 curvedata = kernel_tex_fetch(__curves, sd->prim); float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
int k0 = __float_as_int(curvedata.x) + sd->segment; int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
int k1 = k0 + 1; int k1 = k0 + 1;
float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + k0)); float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + k0));
@ -98,9 +98,9 @@ ccl_device float curve_thickness(KernelGlobals *kg, ShaderData *sd)
{ {
float r = 0.0f; float r = 0.0f;
if(sd->segment != ~0) { if(sd->type & PRIMITIVE_ALL_CURVE) {
float4 curvedata = kernel_tex_fetch(__curves, sd->prim); float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
int k0 = __float_as_int(curvedata.x) + sd->segment; int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
int k1 = k0 + 1; int k1 = k0 + 1;
float4 P1 = kernel_tex_fetch(__curve_keys, k0); float4 P1 = kernel_tex_fetch(__curve_keys, k0);
@ -115,7 +115,7 @@ ccl_device float3 curve_tangent_normal(KernelGlobals *kg, ShaderData *sd)
{ {
float3 tgN = make_float3(0.0f,0.0f,0.0f); float3 tgN = make_float3(0.0f,0.0f,0.0f);
if(sd->segment != ~0) { if(sd->type & PRIMITIVE_ALL_CURVE) {
tgN = -(-sd->I - sd->dPdu * (dot(sd->dPdu,-sd->I) / len_squared(sd->dPdu))); tgN = -(-sd->I - sd->dPdu * (dot(sd->dPdu,-sd->I) / len_squared(sd->dPdu)));
tgN = normalize(tgN); tgN = normalize(tgN);
@ -192,12 +192,13 @@ ccl_device_inline __m128 transform_point_T3(const __m128 t[3], const __m128 &a)
#ifdef __KERNEL_SSE2__ #ifdef __KERNEL_SSE2__
/* Pass P and idir by reference to aligned vector */ /* Pass P and idir by reference to aligned vector */
ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersection *isect, ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersection *isect,
const float3 &P, const float3 &idir, uint visibility, int object, int curveAddr, float time, int segment, uint *lcg_state, float difl, float extmax) const float3 &P, const float3 &idir, uint visibility, int object, int curveAddr, float time, int type, uint *lcg_state, float difl, float extmax)
#else #else
ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersection *isect, ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersection *isect,
float3 P, float3 idir, uint visibility, int object, int curveAddr, float time, int segment, uint *lcg_state, float difl, float extmax) float3 P, float3 idir, uint visibility, int object, int curveAddr, float time,int type, uint *lcg_state, float difl, float extmax)
#endif #endif
{ {
int segment = PRIMITIVE_UNPACK_SEGMENT(type);
float epsilon = 0.0f; float epsilon = 0.0f;
float r_st, r_en; float r_st, r_en;
@ -548,7 +549,7 @@ ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersect
/* record intersection */ /* record intersection */
isect->prim = curveAddr; isect->prim = curveAddr;
isect->object = object; isect->object = object;
isect->segment = segment; isect->type = type;
isect->u = u; isect->u = u;
isect->v = 0.0f; isect->v = 0.0f;
/*isect->v = 1.0f - coverage; */ /*isect->v = 1.0f - coverage; */
@ -569,7 +570,7 @@ ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersect
} }
ccl_device_inline bool bvh_curve_intersect(KernelGlobals *kg, Intersection *isect, ccl_device_inline bool bvh_curve_intersect(KernelGlobals *kg, Intersection *isect,
float3 P, float3 idir, uint visibility, int object, int curveAddr, float time, int segment, uint *lcg_state, float difl, float extmax) float3 P, float3 idir, uint visibility, int object, int curveAddr, float time, int type, uint *lcg_state, float difl, float extmax)
{ {
/* define few macros to minimize code duplication for SSE */ /* define few macros to minimize code duplication for SSE */
#ifndef __KERNEL_SSE2__ #ifndef __KERNEL_SSE2__
@ -578,6 +579,7 @@ ccl_device_inline bool bvh_curve_intersect(KernelGlobals *kg, Intersection *isec
#define dot3(x, y) dot(x, y) #define dot3(x, y) dot(x, y)
#endif #endif
int segment = PRIMITIVE_UNPACK_SEGMENT(type);
/* curve Intersection check */ /* curve Intersection check */
int flags = kernel_data.curve.curveflags; int flags = kernel_data.curve.curveflags;
@ -768,7 +770,7 @@ ccl_device_inline bool bvh_curve_intersect(KernelGlobals *kg, Intersection *isec
/* record intersection */ /* record intersection */
isect->prim = curveAddr; isect->prim = curveAddr;
isect->object = object; isect->object = object;
isect->segment = segment; isect->type = type;
isect->u = z*invl; isect->u = z*invl;
isect->v = td/(4*a*a); isect->v = td/(4*a*a);
/*isect->v = 1.0f - adjradius;*/ /*isect->v = 1.0f - adjradius;*/
@ -841,7 +843,7 @@ ccl_device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, con
int prim = kernel_tex_fetch(__prim_index, isect->prim); int prim = kernel_tex_fetch(__prim_index, isect->prim);
float4 v00 = kernel_tex_fetch(__curves, prim); float4 v00 = kernel_tex_fetch(__curves, prim);
int k0 = __float_as_int(v00.x) + sd->segment; int k0 = __float_as_int(v00.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
int k1 = k0 + 1; int k1 = k0 + 1;
float3 tg; float3 tg;

@ -290,6 +290,7 @@ ccl_device_inline bool triangle_intersect(KernelGlobals *kg, Intersection *isect
/* record intersection */ /* record intersection */
isect->prim = triAddr; isect->prim = triAddr;
isect->object = object; isect->object = object;
isect->type = PRIMITIVE_TRIANGLE;
isect->u = u; isect->u = u;
isect->v = v; isect->v = v;
isect->t = t; isect->t = t;
@ -353,6 +354,7 @@ ccl_device_inline void triangle_intersect_subsurface(KernelGlobals *kg, Intersec
Intersection *isect = &isect_array[hit]; Intersection *isect = &isect_array[hit];
isect->prim = triAddr; isect->prim = triAddr;
isect->object = object; isect->object = object;
isect->type = PRIMITIVE_TRIANGLE;
isect->u = u; isect->u = u;
isect->v = v; isect->v = v;
isect->t = t; isect->t = t;

@ -43,12 +43,7 @@ ccl_device_noinline float3 direct_emissive_eval(KernelGlobals *kg, float rando,
else else
#endif #endif
{ {
#ifdef __HAIR__ shader_setup_from_sample(kg, &sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, ls->u, ls->v, t, time, bounce+1);
if(ls->type == LIGHT_STRAND)
shader_setup_from_sample(kg, &sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, ls->u, ls->v, t, time, bounce+1, ls->prim);
else
#endif
shader_setup_from_sample(kg, &sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, ls->u, ls->v, t, time, bounce+1, ~0);
ls->Ng = sd.Ng; ls->Ng = sd.Ng;
@ -171,7 +166,7 @@ ccl_device_noinline float3 indirect_primitive_emission(KernelGlobals *kg, Shader
float3 L = shader_emissive_eval(kg, sd); float3 L = shader_emissive_eval(kg, sd);
#ifdef __HAIR__ #ifdef __HAIR__
if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_USE_MIS) && (sd->segment == ~0)) { if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_USE_MIS) && (sd->type & PRIMITIVE_ALL_TRIANGLE)) {
#else #else
if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_USE_MIS)) { if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_USE_MIS)) {
#endif #endif

@ -36,7 +36,7 @@ ccl_device_inline int find_attribute(KernelGlobals *kg, ShaderData *sd, uint id,
/* for SVM, find attribute by unique id */ /* for SVM, find attribute by unique id */
uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride; uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
#ifdef __HAIR__ #ifdef __HAIR__
attr_offset = (sd->segment == ~0)? attr_offset: attr_offset + ATTR_PRIM_CURVE; attr_offset = (sd->type & PRIMITIVE_ALL_CURVE)? attr_offset + ATTR_PRIM_CURVE: attr_offset;
#endif #endif
uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset); uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
@ -58,7 +58,7 @@ ccl_device_inline int find_attribute(KernelGlobals *kg, ShaderData *sd, uint id,
ccl_device float primitive_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy) ccl_device float primitive_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy)
{ {
#ifdef __HAIR__ #ifdef __HAIR__
if(sd->segment == ~0) if(sd->type & PRIMITIVE_ALL_TRIANGLE)
#endif #endif
return triangle_attribute_float(kg, sd, elem, offset, dx, dy); return triangle_attribute_float(kg, sd, elem, offset, dx, dy);
#ifdef __HAIR__ #ifdef __HAIR__
@ -70,7 +70,7 @@ ccl_device float primitive_attribute_float(KernelGlobals *kg, const ShaderData *
ccl_device float3 primitive_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy) ccl_device float3 primitive_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy)
{ {
#ifdef __HAIR__ #ifdef __HAIR__
if(sd->segment == ~0) if(sd->type & PRIMITIVE_ALL_TRIANGLE)
#endif #endif
return triangle_attribute_float3(kg, sd, elem, offset, dx, dy); return triangle_attribute_float3(kg, sd, elem, offset, dx, dy);
#ifdef __HAIR__ #ifdef __HAIR__
@ -126,7 +126,7 @@ ccl_device bool primitive_ptex(KernelGlobals *kg, ShaderData *sd, float2 *uv, in
ccl_device float3 primitive_tangent(KernelGlobals *kg, ShaderData *sd) ccl_device float3 primitive_tangent(KernelGlobals *kg, ShaderData *sd)
{ {
#ifdef __HAIR__ #ifdef __HAIR__
if(sd->segment != ~0) if(sd->type & PRIMITIVE_ALL_CURVE)
#ifdef __DPDU__ #ifdef __DPDU__
return normalize(sd->dPdu); return normalize(sd->dPdu);
#else #else

@ -55,6 +55,7 @@ ccl_device void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
sd->object = (isect->object == ~0)? kernel_tex_fetch(__prim_object, isect->prim): isect->object; sd->object = (isect->object == ~0)? kernel_tex_fetch(__prim_object, isect->prim): isect->object;
#endif #endif
sd->type = isect->type;
sd->flag = kernel_tex_fetch(__object_flag, sd->object); sd->flag = kernel_tex_fetch(__object_flag, sd->object);
/* matrices and time */ /* matrices and time */
@ -67,34 +68,27 @@ ccl_device void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
sd->ray_length = isect->t; sd->ray_length = isect->t;
sd->ray_depth = bounce; sd->ray_depth = bounce;
#ifdef __UV__
sd->u = isect->u;
sd->v = isect->v;
#endif
#ifdef __HAIR__ #ifdef __HAIR__
if(kernel_tex_fetch(__prim_segment, isect->prim) != ~0) { if(sd->type & PRIMITIVE_ALL_CURVE) {
/* Strand Shader setting*/ /* curve */
float4 curvedata = kernel_tex_fetch(__curves, sd->prim); float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
sd->shader = __float_as_int(curvedata.z); sd->shader = __float_as_int(curvedata.z);
sd->segment = isect->segment;
sd->P = bvh_curve_refine(kg, sd, isect, ray); sd->P = bvh_curve_refine(kg, sd, isect, ray);
} }
else { else
#endif #endif
{
/* fetch triangle data */ /* fetch triangle data */
float4 Ns = kernel_tex_fetch(__tri_normal, sd->prim); float4 Ns = kernel_tex_fetch(__tri_normal, sd->prim);
float3 Ng = make_float3(Ns.x, Ns.y, Ns.z); float3 Ng = make_float3(Ns.x, Ns.y, Ns.z);
sd->shader = __float_as_int(Ns.w); sd->shader = __float_as_int(Ns.w);
#ifdef __HAIR__
sd->segment = ~0;
/*elements for minimum hair width using transparency bsdf*/
/*sd->curve_transparency = 0.0f;*/
/*sd->curve_radius = 0.0f;*/
#endif
#ifdef __UV__
sd->u = isect->u;
sd->v = isect->v;
#endif
/* vectors */ /* vectors */
sd->P = triangle_refine(kg, sd, isect, ray); sd->P = triangle_refine(kg, sd, isect, ray);
sd->Ng = Ng; sd->Ng = Ng;
@ -108,10 +102,7 @@ ccl_device void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
/* dPdu/dPdv */ /* dPdu/dPdv */
triangle_dPdudv(kg, sd->prim, &sd->dPdu, &sd->dPdv); triangle_dPdudv(kg, sd->prim, &sd->dPdu, &sd->dPdv);
#endif #endif
#ifdef __HAIR__
} }
#endif
sd->I = -ray->D; sd->I = -ray->D;
@ -161,34 +152,32 @@ ccl_device_inline void shader_setup_from_subsurface(KernelGlobals *kg, ShaderDat
/* object, matrices, time, ray_length stay the same */ /* object, matrices, time, ray_length stay the same */
sd->flag = kernel_tex_fetch(__object_flag, sd->object); sd->flag = kernel_tex_fetch(__object_flag, sd->object);
sd->prim = kernel_tex_fetch(__prim_index, isect->prim); sd->prim = kernel_tex_fetch(__prim_index, isect->prim);
sd->type = isect->type;
/* fetch triangle data */
float4 Ns = kernel_tex_fetch(__tri_normal, sd->prim);
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__ #ifdef __UV__
sd->u = isect->u; sd->u = isect->u;
sd->v = isect->v; sd->v = isect->v;
#endif #endif
/* vectors */ /* fetch triangle data */
sd->P = triangle_refine_subsurface(kg, sd, isect, ray); {
sd->Ng = Ng; float4 Ns = kernel_tex_fetch(__tri_normal, sd->prim);
sd->N = Ng; float3 Ng = make_float3(Ns.x, Ns.y, Ns.z);
sd->shader = __float_as_int(Ns.w);
/* smooth normal */
if(sd->shader & SHADER_SMOOTH_NORMAL) /* static triangle */
sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v); sd->P = triangle_refine_subsurface(kg, sd, isect, ray);
sd->Ng = Ng;
sd->N = Ng;
if(sd->shader & SHADER_SMOOTH_NORMAL)
sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
#ifdef __DPDU__ #ifdef __DPDU__
/* dPdu/dPdv */ /* dPdu/dPdv */
triangle_dPdudv(kg, sd->prim, &sd->dPdu, &sd->dPdv); triangle_dPdudv(kg, sd->prim, &sd->dPdu, &sd->dPdv);
#endif #endif
}
sd->flag |= kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2); sd->flag |= kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2);
@ -231,7 +220,7 @@ ccl_device_inline void shader_setup_from_subsurface(KernelGlobals *kg, ShaderDat
ccl_device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd, ccl_device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
const float3 P, const float3 Ng, const float3 I, const float3 P, const float3 Ng, const float3 I,
int shader, int object, int prim, float u, float v, float t, float time, int bounce, int segment) int shader, int object, int prim, float u, float v, float t, float time, int bounce)
{ {
/* vectors */ /* vectors */
sd->P = P; sd->P = P;
@ -239,9 +228,7 @@ ccl_device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
sd->Ng = Ng; sd->Ng = Ng;
sd->I = I; sd->I = I;
sd->shader = shader; sd->shader = shader;
#ifdef __HAIR__ sd->type = (prim == ~0)? PRIMITIVE_NONE: PRIMITIVE_TRIANGLE;
sd->segment = segment;
#endif
/* primitive */ /* primitive */
#ifdef __INSTANCING__ #ifdef __INSTANCING__
@ -283,35 +270,19 @@ ccl_device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
} }
#endif #endif
/* smooth normal */ if(sd->type & PRIMITIVE_TRIANGLE) {
#ifdef __HAIR__ /* smooth normal */
if(sd->shader & SHADER_SMOOTH_NORMAL && sd->segment == ~0) { if(sd->shader & SHADER_SMOOTH_NORMAL) {
sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v); sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
#else
if(sd->shader & SHADER_SMOOTH_NORMAL) {
sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
#endif
#ifdef __INSTANCING__ #ifdef __INSTANCING__
if(instanced) if(instanced)
object_normal_transform(kg, sd, &sd->N); object_normal_transform(kg, sd, &sd->N);
#endif #endif
} }
/* dPdu/dPdv */
#ifdef __DPDU__ #ifdef __DPDU__
/* dPdu/dPdv */
#ifdef __HAIR__
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);
}
#else
if(sd->prim == ~0) {
sd->dPdu = make_float3(0.0f, 0.0f, 0.0f);
sd->dPdv = make_float3(0.0f, 0.0f, 0.0f);
}
#endif
else {
triangle_dPdudv(kg, sd->prim, &sd->dPdu, &sd->dPdv); triangle_dPdudv(kg, sd->prim, &sd->dPdu, &sd->dPdv);
#ifdef __INSTANCING__ #ifdef __INSTANCING__
@ -320,8 +291,14 @@ ccl_device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
object_dir_transform(kg, sd, &sd->dPdv); object_dir_transform(kg, sd, &sd->dPdv);
} }
#endif #endif
}
#endif #endif
}
else {
#ifdef __DPDU__
sd->dPdu = make_float3(0.0f, 0.0f, 0.0f);
sd->dPdv = make_float3(0.0f, 0.0f, 0.0f);
#endif
}
/* backfacing test */ /* backfacing test */
if(sd->prim != ~0) { if(sd->prim != ~0) {
@ -362,7 +339,7 @@ ccl_device void shader_setup_from_displace(KernelGlobals *kg, ShaderData *sd,
/* watch out: no instance transform currently */ /* watch out: no instance transform currently */
shader_setup_from_sample(kg, sd, P, Ng, I, shader, object, prim, u, v, 0.0f, TIME_INVALID, 0, ~0); shader_setup_from_sample(kg, sd, P, Ng, I, shader, object, prim, u, v, 0.0f, TIME_INVALID, 0);
} }
/* ShaderData setup from ray into background */ /* ShaderData setup from ray into background */
@ -429,9 +406,7 @@ ccl_device_inline void shader_setup_from_volume(KernelGlobals *kg, ShaderData *s
sd->object = ~0; /* todo: fill this for texture coordinates */ sd->object = ~0; /* todo: fill this for texture coordinates */
#endif #endif
sd->prim = ~0; sd->prim = ~0;
#ifdef __HAIR__ sd->type = PRIMITIVE_NONE;
sd->segment = ~0;
#endif
#ifdef __UV__ #ifdef __UV__
sd->u = 0.0f; sd->u = 0.0f;
@ -1146,7 +1121,7 @@ ccl_device bool shader_transparent_shadow(KernelGlobals *kg, Intersection *isect
int shader = 0; int shader = 0;
#ifdef __HAIR__ #ifdef __HAIR__
if(kernel_tex_fetch(__prim_segment, isect->prim) == ~0) { if(kernel_tex_fetch(__prim_type, isect->prim) & PRIMITIVE_ALL_TRIANGLE) {
#endif #endif
float4 Ns = kernel_tex_fetch(__tri_normal, prim); float4 Ns = kernel_tex_fetch(__tri_normal, prim);
shader = __float_as_int(Ns.w); shader = __float_as_int(Ns.w);

@ -25,7 +25,7 @@
/* bvh */ /* bvh */
KERNEL_TEX(float4, texture_float4, __bvh_nodes) KERNEL_TEX(float4, texture_float4, __bvh_nodes)
KERNEL_TEX(float4, texture_float4, __tri_woop) KERNEL_TEX(float4, texture_float4, __tri_woop)
KERNEL_TEX(uint, texture_uint, __prim_segment) KERNEL_TEX(uint, texture_uint, __prim_type)
KERNEL_TEX(uint, texture_uint, __prim_visibility) KERNEL_TEX(uint, texture_uint, __prim_visibility)
KERNEL_TEX(uint, texture_uint, __prim_index) KERNEL_TEX(uint, texture_uint, __prim_index)
KERNEL_TEX(uint, texture_uint, __prim_object) KERNEL_TEX(uint, texture_uint, __prim_object)

@ -420,9 +420,27 @@ typedef struct Intersection {
float t, u, v; float t, u, v;
int prim; int prim;
int object; int object;
int segment; int type;
} Intersection; } Intersection;
/* Primitives */
typedef enum PrimitiveType {
PRIMITIVE_NONE = 0,
PRIMITIVE_TRIANGLE = 1,
PRIMITIVE_MOTION_TRIANGLE = 2,
PRIMITIVE_CURVE = 4,
PRIMITIVE_MOTION_CURVE = 8,
PRIMITIVE_ALL_TRIANGLE = (PRIMITIVE_TRIANGLE|PRIMITIVE_MOTION_TRIANGLE),
PRIMITIVE_ALL_CURVE = (PRIMITIVE_CURVE|PRIMITIVE_MOTION_CURVE),
PRIMITIVE_ALL_MOTION = (PRIMITIVE_MOTION_TRIANGLE|PRIMITIVE_MOTION_CURVE),
PRIMITIVE_ALL = (PRIMITIVE_ALL_TRIANGLE|PRIMITIVE_ALL_CURVE)
} PrimitiveType;
#define PRIMITIVE_PACK_SEGMENT(type, segment) ((segment << 16) | type)
#define PRIMITIVE_UNPACK_SEGMENT(type) (type >> 16)
/* Attributes */ /* Attributes */
#define ATTR_PRIM_TYPES 2 #define ATTR_PRIM_TYPES 2
@ -565,13 +583,9 @@ typedef struct ShaderData {
/* primitive id if there is one, ~0 otherwise */ /* primitive id if there is one, ~0 otherwise */
int prim; int prim;
#ifdef __HAIR__ /* combined type and curve segment for hair */
/* for curves, segment number in curve, ~0 for triangles */ int type;
int segment;
/* variables for minimum hair width using transparency bsdf */
/*float curve_transparency; */
/*float curve_radius; */
#endif
/* parametric coordinates /* parametric coordinates
* - barycentric weights for triangles */ * - barycentric weights for triangles */
float u, v; float u, v;

@ -643,7 +643,7 @@ bool OSLRenderServices::get_object_standard_attribute(KernelGlobals *kg, ShaderD
} }
else if ((name == u_geom_trianglevertices || name == u_geom_polyvertices) else if ((name == u_geom_trianglevertices || name == u_geom_polyvertices)
#ifdef __HAIR__ #ifdef __HAIR__
&& sd->segment == ~0) { && sd->type & PRIMITIVE_ALL_TRIANGLE) {
#else #else
) { ) {
#endif #endif
@ -669,7 +669,7 @@ bool OSLRenderServices::get_object_standard_attribute(KernelGlobals *kg, ShaderD
#ifdef __HAIR__ #ifdef __HAIR__
/* Hair Attributes */ /* Hair Attributes */
else if (name == u_is_curve) { else if (name == u_is_curve) {
float f = (sd->segment != ~0); float f = (sd->type & PRIMITIVE_ALL_CURVE) != 0;
return set_attribute_float(f, type, derivatives, val); return set_attribute_float(f, type, derivatives, val);
} }
else if (name == u_curve_thickness) { else if (name == u_curve_thickness) {
@ -732,7 +732,8 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri
{ {
ShaderData *sd = (ShaderData *)renderstate; ShaderData *sd = (ShaderData *)renderstate;
KernelGlobals *kg = sd->osl_globals; KernelGlobals *kg = sd->osl_globals;
int object, prim, segment; bool is_curve;
int object, prim;
/* lookup of attribute on another object */ /* lookup of attribute on another object */
if (object_name != u_empty) { if (object_name != u_empty) {
@ -743,23 +744,19 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri
object = it->second; object = it->second;
prim = ~0; prim = ~0;
segment = ~0; is_curve = false;
} }
else { else {
object = sd->object; object = sd->object;
prim = sd->prim; prim = sd->prim;
#ifdef __HAIR__ is_curve = (sd->type & PRIMITIVE_ALL_CURVE) != 0;
segment = sd->segment;
#else
segment = ~0;
#endif
if (object == ~0) if (object == ~0)
return get_background_attribute(kg, sd, name, type, derivatives, val); return get_background_attribute(kg, sd, name, type, derivatives, val);
} }
/* find attribute on object */ /* find attribute on object */
object = object*ATTR_PRIM_TYPES + (segment != ~0); object = object*ATTR_PRIM_TYPES + (is_curve == true);
OSLGlobals::AttributeMap& attribute_map = kg->osl->attribute_map[object]; OSLGlobals::AttributeMap& attribute_map = kg->osl->attribute_map[object];
OSLGlobals::AttributeMap::iterator it = attribute_map.find(name); OSLGlobals::AttributeMap::iterator it = attribute_map.find(name);

@ -536,7 +536,7 @@ int OSLShader::find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id,
/* for OSL, a hash map is used to lookup the attribute by name. */ /* for OSL, a hash map is used to lookup the attribute by name. */
int object = sd->object*ATTR_PRIM_TYPES; int object = sd->object*ATTR_PRIM_TYPES;
#ifdef __HAIR__ #ifdef __HAIR__
if(sd->segment != ~0) object += ATTR_PRIM_CURVE; if(sd->type & PRIMITIVE_ALL_CURVE) object += ATTR_PRIM_CURVE;
#endif #endif
OSLGlobals::AttributeMap &attr_map = kg->osl->attribute_map[object]; OSLGlobals::AttributeMap &attr_map = kg->osl->attribute_map[object];

@ -27,7 +27,7 @@ ccl_device void svm_node_attr_init(KernelGlobals *kg, ShaderData *sd,
uint id = node.y; uint id = node.y;
uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride; uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
#ifdef __HAIR__ #ifdef __HAIR__
attr_offset = (sd->segment == ~0)? attr_offset: attr_offset + ATTR_PRIM_CURVE; attr_offset = (sd->type & PRIMITIVE_ALL_TRIANGLE)? attr_offset: attr_offset + ATTR_PRIM_CURVE;
#endif #endif
uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset); uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);

@ -364,7 +364,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
case CLOSURE_BSDF_HAIR_REFLECTION_ID: case CLOSURE_BSDF_HAIR_REFLECTION_ID:
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID: { case CLOSURE_BSDF_HAIR_TRANSMISSION_ID: {
if(sd->flag & SD_BACKFACING && sd->segment != ~0) { if(sd->flag & SD_BACKFACING && sd->type & PRIMITIVE_ALL_CURVE) {
ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight); ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
if(sc) { if(sc) {
sc->weight = make_float3(1.0f,1.0f,1.0f); sc->weight = make_float3(1.0f,1.0f,1.0f);
@ -381,7 +381,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
sc->data0 = param1; sc->data0 = param1;
sc->data1 = param2; sc->data1 = param2;
sc->offset = -stack_load_float(stack, data_node.z); sc->offset = -stack_load_float(stack, data_node.z);
if(sd->segment == ~0) { if(sd->type & PRIMITIVE_ALL_CURVE) {
sc->T = normalize(sd->dPdv); sc->T = normalize(sd->dPdv);
sc->offset = 0.0f; sc->offset = 0.0f;
} }

@ -153,7 +153,7 @@ ccl_device void svm_node_hair_info(KernelGlobals *kg, ShaderData *sd, float *sta
switch(type) { switch(type) {
case NODE_INFO_CURVE_IS_STRAND: { case NODE_INFO_CURVE_IS_STRAND: {
data = (sd->segment != ~0); data = (sd->type & PRIMITIVE_ALL_CURVE) != 0;
stack_store_float(stack, out_offset, data); stack_store_float(stack, out_offset, data);
break; break;
} }

@ -45,7 +45,7 @@ ccl_device void svm_node_wireframe(KernelGlobals *kg, ShaderData *sd, float *sta
/* Calculate wireframe */ /* Calculate wireframe */
#ifdef __HAIR__ #ifdef __HAIR__
if (sd->prim != ~0 && sd->segment == ~0) { if (sd->prim != ~0 && sd->type & PRIMITIVE_ALL_TRIANGLE) {
#else #else
if (sd->prim != ~0) { if (sd->prim != ~0) {
#endif #endif

@ -873,9 +873,9 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *
dscene->tri_woop.reference(&pack.tri_woop[0], pack.tri_woop.size()); dscene->tri_woop.reference(&pack.tri_woop[0], pack.tri_woop.size());
device->tex_alloc("__tri_woop", dscene->tri_woop); device->tex_alloc("__tri_woop", dscene->tri_woop);
} }
if(pack.prim_segment.size()) { if(pack.prim_type.size()) {
dscene->prim_segment.reference((uint*)&pack.prim_segment[0], pack.prim_segment.size()); dscene->prim_type.reference((uint*)&pack.prim_type[0], pack.prim_type.size());
device->tex_alloc("__prim_segment", dscene->prim_segment); device->tex_alloc("__prim_type", dscene->prim_type);
} }
if(pack.prim_visibility.size()) { if(pack.prim_visibility.size()) {
dscene->prim_visibility.reference((uint*)&pack.prim_visibility[0], pack.prim_visibility.size()); dscene->prim_visibility.reference((uint*)&pack.prim_visibility[0], pack.prim_visibility.size());
@ -986,7 +986,7 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene)
device->tex_free(dscene->bvh_nodes); device->tex_free(dscene->bvh_nodes);
device->tex_free(dscene->object_node); device->tex_free(dscene->object_node);
device->tex_free(dscene->tri_woop); device->tex_free(dscene->tri_woop);
device->tex_free(dscene->prim_segment); device->tex_free(dscene->prim_type);
device->tex_free(dscene->prim_visibility); device->tex_free(dscene->prim_visibility);
device->tex_free(dscene->prim_index); device->tex_free(dscene->prim_index);
device->tex_free(dscene->prim_object); device->tex_free(dscene->prim_object);
@ -1003,7 +1003,7 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene)
dscene->bvh_nodes.clear(); dscene->bvh_nodes.clear();
dscene->object_node.clear(); dscene->object_node.clear();
dscene->tri_woop.clear(); dscene->tri_woop.clear();
dscene->prim_segment.clear(); dscene->prim_type.clear();
dscene->prim_visibility.clear(); dscene->prim_visibility.clear();
dscene->prim_index.clear(); dscene->prim_index.clear();
dscene->prim_object.clear(); dscene->prim_object.clear();

@ -60,7 +60,7 @@ public:
device_vector<float4> bvh_nodes; device_vector<float4> bvh_nodes;
device_vector<uint> object_node; device_vector<uint> object_node;
device_vector<float4> tri_woop; device_vector<float4> tri_woop;
device_vector<uint> prim_segment; device_vector<uint> prim_type;
device_vector<uint> prim_visibility; device_vector<uint> prim_visibility;
device_vector<uint> prim_index; device_vector<uint> prim_index;
device_vector<uint> prim_object; device_vector<uint> prim_object;