diff options
Diffstat (limited to 'intern/cycles/bvh/build.cpp')
-rw-r--r-- | intern/cycles/bvh/build.cpp | 130 |
1 files changed, 124 insertions, 6 deletions
diff --git a/intern/cycles/bvh/build.cpp b/intern/cycles/bvh/build.cpp index 3ce268dfb25..91198e4e2a2 100644 --- a/intern/cycles/bvh/build.cpp +++ b/intern/cycles/bvh/build.cpp @@ -26,6 +26,7 @@ #include "scene/hair.h" #include "scene/mesh.h" #include "scene/object.h" +#include "scene/pointcloud.h" #include "scene/scene.h" #include "util/algorithm.h" @@ -113,9 +114,9 @@ void BVHBuild::add_reference_triangles(BoundBox &root, 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. + * This way we minimize overlap of neighbor triangle primitives. */ - const int num_bvh_steps = params.num_motion_curve_steps * 2 + 1; + const int num_bvh_steps = params.num_motion_triangle_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; @@ -269,6 +270,101 @@ void BVHBuild::add_reference_curves(BoundBox &root, BoundBox ¢er, Hair *hair } } +void BVHBuild::add_reference_points(BoundBox &root, + BoundBox ¢er, + PointCloud *pointcloud, + int i) +{ + const Attribute *point_attr_mP = NULL; + if (pointcloud->has_motion_blur()) { + point_attr_mP = pointcloud->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + } + + const float3 *points_data = &pointcloud->points[0]; + const float *radius_data = &pointcloud->radius[0]; + const size_t num_points = pointcloud->num_points(); + const float3 *motion_data = (point_attr_mP) ? point_attr_mP->data_float3() : NULL; + const size_t num_steps = pointcloud->get_motion_steps(); + + if (point_attr_mP == NULL) { + /* Really simple logic for static points. */ + for (uint j = 0; j < num_points; j++) { + const PointCloud::Point point = pointcloud->get_point(j); + BoundBox bounds = BoundBox::empty; + point.bounds_grow(points_data, radius_data, bounds); + if (bounds.valid()) { + references.push_back(BVHReference(bounds, j, i, PRIMITIVE_POINT)); + root.grow(bounds); + center.grow(bounds.center2()); + } + } + } + else if (params.num_motion_point_steps == 0 || params.use_spatial_split) { + /* Simple case of motion points: single node for the whole + * shutter time. Lowest memory usage but less optimal + * rendering. + */ + /* TODO(sergey): Support motion steps for spatially split BVH. */ + for (uint j = 0; j < num_points; j++) { + const PointCloud::Point point = pointcloud->get_point(j); + BoundBox bounds = BoundBox::empty; + point.bounds_grow(points_data, radius_data, bounds); + for (size_t step = 0; step < num_steps - 1; step++) { + point.bounds_grow(motion_data + step * num_points, radius_data, bounds); + } + if (bounds.valid()) { + references.push_back(BVHReference(bounds, j, i, PRIMITIVE_MOTION_POINT)); + root.grow(bounds); + center.grow(bounds.center2()); + } + } + } + else { + /* Motion points, trace optimized case: we split point + * primitives into separate nodes for each of the time steps. + * This way we minimize overlap of neighbor point primitives. + */ + const int num_bvh_steps = params.num_motion_point_steps * 2 + 1; + const float num_bvh_steps_inv_1 = 1.0f / (num_bvh_steps - 1); + + for (uint j = 0; j < num_points; j++) { + const PointCloud::Point point = pointcloud->get_point(j); + const size_t num_steps = pointcloud->get_motion_steps(); + const float3 *point_steps = point_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. + */ + float4 prev_key = point.motion_key( + points_data, radius_data, point_steps, num_points, num_steps, 0.0f, j); + BoundBox prev_bounds = BoundBox::empty; + point.bounds_grow(prev_key, 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_key = point.motion_key( + points_data, radius_data, point_steps, num_points, num_steps, curr_time, j); + BoundBox curr_bounds = BoundBox::empty; + point.bounds_grow(curr_key, 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_POINT, 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; + } + } + } +} + void BVHBuild::add_reference_geometry(BoundBox &root, BoundBox ¢er, Geometry *geom, @@ -282,6 +378,10 @@ void BVHBuild::add_reference_geometry(BoundBox &root, Hair *hair = static_cast<Hair *>(geom); add_reference_curves(root, center, hair, object_index); } + else if (geom->geometry_type == Geometry::POINTCLOUD) { + PointCloud *pointcloud = static_cast<PointCloud *>(geom); + add_reference_points(root, center, pointcloud, object_index); + } } void BVHBuild::add_reference_object(BoundBox &root, BoundBox ¢er, Object *ob, int i) @@ -311,6 +411,10 @@ static size_t count_primitives(Geometry *geom) Hair *hair = static_cast<Hair *>(geom); return count_curve_segments(hair); } + else if (geom->geometry_type == Geometry::POINTCLOUD) { + PointCloud *pointcloud = static_cast<PointCloud *>(geom); + return pointcloud->num_points(); + } return 0; } @@ -328,8 +432,9 @@ void BVHBuild::add_references(BVHRange &root) if (!ob->get_geometry()->is_instanced()) { num_alloc_references += count_primitives(ob->get_geometry()); } - else + else { num_alloc_references++; + } } else { num_alloc_references += count_primitives(ob->get_geometry()); @@ -394,7 +499,7 @@ BVHNode *BVHBuild::run() spatial_min_overlap = root.bounds().safe_area() * params.spatial_split_alpha; spatial_free_index = 0; - need_prim_time = params.num_motion_curve_steps > 0 || params.num_motion_triangle_steps > 0; + need_prim_time = params.use_motion_steps(); /* init progress updates */ double build_start_time; @@ -535,7 +640,8 @@ bool BVHBuild::range_within_max_leaf_size(const BVHRange &range, const vector<BVHReference> &references) const { size_t size = range.size(); - size_t max_leaf_size = max(params.max_triangle_leaf_size, params.max_curve_leaf_size); + size_t max_leaf_size = max(max(params.max_triangle_leaf_size, params.max_curve_leaf_size), + params.max_point_leaf_size); if (size > max_leaf_size) return false; @@ -544,6 +650,8 @@ bool BVHBuild::range_within_max_leaf_size(const BVHRange &range, size_t num_motion_triangles = 0; size_t num_curves = 0; size_t num_motion_curves = 0; + size_t num_points = 0; + size_t num_motion_points = 0; for (int i = 0; i < size; i++) { const BVHReference &ref = references[range.start() + i]; @@ -564,12 +672,22 @@ bool BVHBuild::range_within_max_leaf_size(const BVHRange &range, num_triangles++; } } + else if (ref.prim_type() & PRIMITIVE_ALL_POINT) { + if (ref.prim_type() & PRIMITIVE_ALL_MOTION) { + num_motion_points++; + } + else { + num_points++; + } + } } return (num_triangles <= params.max_triangle_leaf_size) && (num_motion_triangles <= params.max_motion_triangle_leaf_size) && (num_curves <= params.max_curve_leaf_size) && - (num_motion_curves <= params.max_motion_curve_leaf_size); + (num_motion_curves <= params.max_motion_curve_leaf_size) && + (num_points <= params.max_point_leaf_size) && + (num_motion_points <= params.max_motion_point_leaf_size); } /* multithreaded binning builder */ |