diff options
Diffstat (limited to 'intern/cycles')
-rw-r--r-- | intern/cycles/bvh/bvh_build.cpp | 347 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh_build.h | 2 |
2 files changed, 179 insertions, 170 deletions
diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp index 4abd686cc6e..9ff68333c80 100644 --- a/intern/cycles/bvh/bvh_build.cpp +++ b/intern/cycles/bvh/bvh_build.cpp @@ -112,104 +112,214 @@ BVHBuild::~BVHBuild() /* Adding References */ -void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh, int i) +void BVHBuild::add_reference_triangles(BoundBox& root, BoundBox& center, Mesh *mesh, int i) { - if(params.primitive_mask & PRIMITIVE_ALL_TRIANGLE) { - Attribute *attr_mP = NULL; - - if(mesh->has_motion_blur()) - attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + Attribute *attr_mP = NULL; + if(mesh->has_motion_blur()) { + attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + } + const size_t num_triangles = mesh->num_triangles(); + for(uint j = 0; j < num_triangles; j++) { + Mesh::Triangle t = mesh->get_triangle(j); + const float3 *verts = &mesh->verts[0]; + if(attr_mP == NULL) { + BoundBox bounds = BoundBox::empty; + t.bounds_grow(verts, bounds); + if(bounds.valid()) { + references.push_back(BVHReference(bounds, + j, + i, + PRIMITIVE_TRIANGLE)); + root.grow(bounds); + center.grow(bounds.center2()); + } + } + else if(params.num_motion_triangle_steps == 0 || params.use_spatial_split) { + /* Motion triangles, simple case: single node for the whole + * primitive. Lowest memory footprint and faster BVH build but + * least optimal ray-tracing. + */ + /* TODO(sergey): Support motion steps for spatially split BVH. */ + const size_t num_verts = mesh->verts.size(); + const size_t num_steps = mesh->motion_steps; + const float3 *vert_steps = attr_mP->data_float3(); + BoundBox bounds = BoundBox::empty; + t.bounds_grow(verts, bounds); + for(size_t step = 0; step < num_steps - 1; step++) { + t.bounds_grow(vert_steps + step*num_verts, bounds); + } + if(bounds.valid()) { + references.push_back( + BVHReference(bounds, + j, + i, + PRIMITIVE_MOTION_TRIANGLE)); + root.grow(bounds); + center.grow(bounds.center2()); + } + } + else { + /* Motion triangles, trace optimized case: we split triangle + * primitives into separate nodes for each of the time steps. + * This way we minimize overlap of neighbor curve primitives. + */ + const int num_bvh_steps = params.num_motion_curve_steps * 2 + 1; + const float num_bvh_steps_inv_1 = 1.0f / (num_bvh_steps - 1); + const size_t num_verts = mesh->verts.size(); + const size_t num_steps = mesh->motion_steps; + const float3 *vert_steps = attr_mP->data_float3(); + /* Calculate bounding box of the previous time step. + * Will be reused later to avoid duplicated work on + * calculating BVH time step boundbox. + */ + float3 prev_verts[3]; + t.motion_verts(verts, + vert_steps, + num_verts, + num_steps, + 0.0f, + prev_verts); + BoundBox prev_bounds = BoundBox::empty; + prev_bounds.grow(prev_verts[0]); + prev_bounds.grow(prev_verts[1]); + prev_bounds.grow(prev_verts[2]); + /* Create all primitive time steps, */ + for(int bvh_step = 1; bvh_step < num_bvh_steps; ++bvh_step) { + const float curr_time = (float)(bvh_step) * num_bvh_steps_inv_1; + float3 curr_verts[3]; + t.motion_verts(verts, + vert_steps, + num_verts, + num_steps, + curr_time, + curr_verts); + BoundBox curr_bounds = BoundBox::empty; + curr_bounds.grow(curr_verts[0]); + curr_bounds.grow(curr_verts[1]); + curr_bounds.grow(curr_verts[2]); + BoundBox bounds = prev_bounds; + bounds.grow(curr_bounds); + if(bounds.valid()) { + const float prev_time = (float)(bvh_step - 1) * num_bvh_steps_inv_1; + references.push_back( + BVHReference(bounds, + j, + i, + PRIMITIVE_MOTION_TRIANGLE, + prev_time, + curr_time)); + root.grow(bounds); + center.grow(bounds.center2()); + } + /* Current time boundbox becomes previous one for the + * next time step. + */ + prev_bounds = curr_bounds; + } + } + } +} - const size_t num_triangles = mesh->num_triangles(); - for(uint j = 0; j < num_triangles; j++) { - Mesh::Triangle t = mesh->get_triangle(j); - const float3 *verts = &mesh->verts[0]; - if(attr_mP == NULL) { +void BVHBuild::add_reference_curves(BoundBox& root, BoundBox& center, Mesh *mesh, int i) +{ + Attribute *curve_attr_mP = NULL; + if(mesh->has_motion_blur()) { + curve_attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + } + size_t num_curves = mesh->num_curves(); + for(uint j = 0; j < num_curves; j++) { + const Mesh::Curve curve = mesh->get_curve(j); + const float *curve_radius = &mesh->curve_radius[0]; + for(int k = 0; k < curve.num_keys - 1; k++) { + if(curve_attr_mP == NULL) { + /* Really simple logic for static hair. */ BoundBox bounds = BoundBox::empty; - t.bounds_grow(verts, bounds); + curve.bounds_grow(k, &mesh->curve_keys[0], curve_radius, bounds); if(bounds.valid()) { - references.push_back(BVHReference(bounds, - j, - i, - PRIMITIVE_TRIANGLE)); + int packed_type = PRIMITIVE_PACK_SEGMENT(PRIMITIVE_CURVE, k); + references.push_back(BVHReference(bounds, j, i, packed_type)); root.grow(bounds); center.grow(bounds.center2()); } } - else if(params.num_motion_triangle_steps == 0 || params.use_spatial_split) { - /* Motion triangles, simple case: single node for the whole - * primitive. Lowest memory footprint and faster BVH build but - * least optimal ray-tracing. + else if(params.num_motion_curve_steps == 0 || params.use_spatial_split) { + /* Simple case of motion curves: single node for the while + * shutter time. Lowest memory usage but less optimal + * rendering. */ /* TODO(sergey): Support motion steps for spatially split BVH. */ - const size_t num_verts = mesh->verts.size(); - const size_t num_steps = mesh->motion_steps; - const float3 *vert_steps = attr_mP->data_float3(); BoundBox bounds = BoundBox::empty; - t.bounds_grow(verts, bounds); + curve.bounds_grow(k, &mesh->curve_keys[0], curve_radius, bounds); + const size_t num_keys = mesh->curve_keys.size(); + const size_t num_steps = mesh->motion_steps; + const float3 *key_steps = curve_attr_mP->data_float3(); for(size_t step = 0; step < num_steps - 1; step++) { - t.bounds_grow(vert_steps + step*num_verts, bounds); + curve.bounds_grow(k, + key_steps + step*num_keys, + curve_radius, + bounds); } if(bounds.valid()) { - references.push_back( - BVHReference(bounds, - j, - i, - PRIMITIVE_MOTION_TRIANGLE)); + int packed_type = PRIMITIVE_PACK_SEGMENT(PRIMITIVE_MOTION_CURVE, k); + references.push_back(BVHReference(bounds, + j, + i, + packed_type)); root.grow(bounds); center.grow(bounds.center2()); } } else { - /* Motion triangles, trace optimized case: we split triangle + /* Motion curves, trace optimized case: we split curve keys * primitives into separate nodes for each of the time steps. * This way we minimize overlap of neighbor curve primitives. */ const int num_bvh_steps = params.num_motion_curve_steps * 2 + 1; const float num_bvh_steps_inv_1 = 1.0f / (num_bvh_steps - 1); - const size_t num_verts = mesh->verts.size(); const size_t num_steps = mesh->motion_steps; - const float3 *vert_steps = attr_mP->data_float3(); + const float3 *curve_keys = &mesh->curve_keys[0]; + const float3 *key_steps = curve_attr_mP->data_float3(); + const size_t num_keys = mesh->curve_keys.size(); /* Calculate bounding box of the previous time step. * Will be reused later to avoid duplicated work on * calculating BVH time step boundbox. */ - float3 prev_verts[3]; - t.motion_verts(verts, - vert_steps, - num_verts, - num_steps, - 0.0f, - prev_verts); + float4 prev_keys[4]; + curve.cardinal_motion_keys(curve_keys, + curve_radius, + key_steps, + num_keys, + num_steps, + 0.0f, + k - 1, k, k + 1, k + 2, + prev_keys); BoundBox prev_bounds = BoundBox::empty; - prev_bounds.grow(prev_verts[0]); - prev_bounds.grow(prev_verts[1]); - prev_bounds.grow(prev_verts[2]); + curve.bounds_grow(prev_keys, prev_bounds); /* Create all primitive time steps, */ for(int bvh_step = 1; bvh_step < num_bvh_steps; ++bvh_step) { const float curr_time = (float)(bvh_step) * num_bvh_steps_inv_1; - float3 curr_verts[3]; - t.motion_verts(verts, - vert_steps, - num_verts, - num_steps, - curr_time, - curr_verts); + float4 curr_keys[4]; + curve.cardinal_motion_keys(curve_keys, + curve_radius, + key_steps, + num_keys, + num_steps, + curr_time, + k - 1, k, k + 1, k + 2, + curr_keys); BoundBox curr_bounds = BoundBox::empty; - curr_bounds.grow(curr_verts[0]); - curr_bounds.grow(curr_verts[1]); - curr_bounds.grow(curr_verts[2]); + curve.bounds_grow(curr_keys, curr_bounds); BoundBox bounds = prev_bounds; bounds.grow(curr_bounds); if(bounds.valid()) { const float prev_time = (float)(bvh_step - 1) * num_bvh_steps_inv_1; - references.push_back( - BVHReference(bounds, - j, - i, - PRIMITIVE_MOTION_TRIANGLE, - prev_time, - curr_time)); + int packed_type = PRIMITIVE_PACK_SEGMENT(PRIMITIVE_MOTION_CURVE, k); + references.push_back(BVHReference(bounds, + j, + i, + packed_type, + prev_time, + curr_time)); root.grow(bounds); center.grow(bounds.center2()); } @@ -221,118 +331,15 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh, } } } +} +void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh, int i) +{ + if(params.primitive_mask & PRIMITIVE_ALL_TRIANGLE) { + add_reference_triangles(root, center, mesh, i); + } if(params.primitive_mask & PRIMITIVE_ALL_CURVE) { - Attribute *curve_attr_mP = NULL; - - if(mesh->has_motion_blur()) - curve_attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); - - size_t num_curves = mesh->num_curves(); - for(uint j = 0; j < num_curves; j++) { - const Mesh::Curve curve = mesh->get_curve(j); - const float *curve_radius = &mesh->curve_radius[0]; - for(int k = 0; k < curve.num_keys - 1; k++) { - if(curve_attr_mP == NULL) { - /* Really simple logic for static hair. */ - BoundBox bounds = BoundBox::empty; - curve.bounds_grow(k, &mesh->curve_keys[0], curve_radius, bounds); - if(bounds.valid()) { - int packed_type = PRIMITIVE_PACK_SEGMENT(PRIMITIVE_CURVE, k); - references.push_back(BVHReference(bounds, j, i, packed_type)); - root.grow(bounds); - center.grow(bounds.center2()); - } - } - else if(params.num_motion_curve_steps == 0 || params.use_spatial_split) { - /* Simple case of motion curves: single node for the while - * shutter time. Lowest memory usage but less optimal - * rendering. - */ - /* TODO(sergey): Support motion steps for spatially split BVH. */ - BoundBox bounds = BoundBox::empty; - curve.bounds_grow(k, &mesh->curve_keys[0], curve_radius, bounds); - const size_t num_keys = mesh->curve_keys.size(); - const size_t num_steps = mesh->motion_steps; - const float3 *key_steps = curve_attr_mP->data_float3(); - for(size_t step = 0; step < num_steps - 1; step++) { - curve.bounds_grow(k, - key_steps + step*num_keys, - curve_radius, - bounds); - } - if(bounds.valid()) { - int packed_type = PRIMITIVE_PACK_SEGMENT(PRIMITIVE_MOTION_CURVE, k); - references.push_back(BVHReference(bounds, - j, - i, - packed_type)); - root.grow(bounds); - center.grow(bounds.center2()); - } - } - else { - /* Motion curves, trace optimized case: we split curve keys - * primitives into separate nodes for each of the time steps. - * This way we minimize overlap of neighbor curve primitives. - */ - const int num_bvh_steps = params.num_motion_curve_steps * 2 + 1; - const float num_bvh_steps_inv_1 = 1.0f / (num_bvh_steps - 1); - const size_t num_steps = mesh->motion_steps; - const float3 *curve_keys = &mesh->curve_keys[0]; - const float3 *key_steps = curve_attr_mP->data_float3(); - const size_t num_keys = mesh->curve_keys.size(); - /* Calculate bounding box of the previous time step. - * Will be reused later to avoid duplicated work on - * calculating BVH time step boundbox. - */ - float4 prev_keys[4]; - curve.cardinal_motion_keys(curve_keys, - curve_radius, - key_steps, - num_keys, - num_steps, - 0.0f, - k - 1, k, k + 1, k + 2, - prev_keys); - BoundBox prev_bounds = BoundBox::empty; - curve.bounds_grow(prev_keys, prev_bounds); - /* Create all primitive time steps, */ - for(int bvh_step = 1; bvh_step < num_bvh_steps; ++bvh_step) { - const float curr_time = (float)(bvh_step) * num_bvh_steps_inv_1; - float4 curr_keys[4]; - curve.cardinal_motion_keys(curve_keys, - curve_radius, - key_steps, - num_keys, - num_steps, - curr_time, - k - 1, k, k + 1, k + 2, - curr_keys); - BoundBox curr_bounds = BoundBox::empty; - curve.bounds_grow(curr_keys, curr_bounds); - BoundBox bounds = prev_bounds; - bounds.grow(curr_bounds); - if(bounds.valid()) { - const float prev_time = (float)(bvh_step - 1) * num_bvh_steps_inv_1; - int packed_type = PRIMITIVE_PACK_SEGMENT(PRIMITIVE_MOTION_CURVE, k); - references.push_back(BVHReference(bounds, - j, - i, - packed_type, - prev_time, - curr_time)); - root.grow(bounds); - center.grow(bounds.center2()); - } - /* Current time boundbox becomes previous one for the - * next time step. - */ - prev_bounds = curr_bounds; - } - } - } - } + add_reference_curves(root, center, mesh, i); } } diff --git a/intern/cycles/bvh/bvh_build.h b/intern/cycles/bvh/bvh_build.h index 64180349935..ee3cde66a2f 100644 --- a/intern/cycles/bvh/bvh_build.h +++ b/intern/cycles/bvh/bvh_build.h @@ -63,6 +63,8 @@ protected: friend class BVHObjectBinning; /* Adding references. */ + void add_reference_triangles(BoundBox& root, BoundBox& center, Mesh *mesh, int i); + void add_reference_curves(BoundBox& root, BoundBox& center, Mesh *mesh, int i); void add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh, int i); void add_reference_object(BoundBox& root, BoundBox& center, Object *ob, int i); void add_references(BVHRange& root); |