Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/bvh/build.cpp')
-rw-r--r--intern/cycles/bvh/build.cpp130
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 &center, Hair *hair
}
}
+void BVHBuild::add_reference_points(BoundBox &root,
+ BoundBox &center,
+ 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 &center,
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 &center, 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 */