[Bf-blender-cvs] [91fe6bdcb6] blender-v2.78b-release: Cycles: Add option to split triangle motion primitives by time steps

Sergey Sharybin noreply at git.blender.org
Thu Jan 26 13:46:53 CET 2017


Commit: 91fe6bdcb69af4f04b083b85a46807e5f7061dde
Author: Sergey Sharybin
Date:   Tue Jan 17 15:13:01 2017 +0100
Branches: blender-v2.78b-release
https://developer.blender.org/rB91fe6bdcb69af4f04b083b85a46807e5f7061dde

Cycles: Add option to split triangle motion primitives by time steps

Similar to the previous commit, the statistics goes as:

BVH Steps     Render time (sec)       Memory usage (MB)
    0                46                    260
    1                27                    373
    2                18                    598
    3                15                    826

Scene used for the tests is the agent's body from one of the barber
shop scenes (no textures or anything, just a diffuse material).

Once again this is limited to regular (non-spatial split) BVH,
Support of spatial split to this feature will come later.

===================================================================

M	intern/cycles/blender/blender_sync.cpp
M	intern/cycles/bvh/bvh_build.cpp
M	intern/cycles/bvh/bvh_params.h
M	intern/cycles/render/mesh.cpp
M	intern/cycles/render/scene.h

===================================================================

diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index a9b7d7d358..f8f2303ec7 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -498,7 +498,7 @@ SceneParams BlenderSync::get_scene_params(BL::Scene& b_scene,
 
 	params.use_bvh_spatial_split = RNA_boolean_get(&cscene, "debug_use_spatial_splits");
 	params.use_bvh_unaligned_nodes = RNA_boolean_get(&cscene, "debug_use_hair_bvh");
-	params.num_bvh_motion_curve_steps = RNA_int_get(&cscene, "debug_bvh_time_steps");
+	params.num_bvh_time_steps = RNA_int_get(&cscene, "debug_bvh_time_steps");
 
 	if(background && params.shadingsystem != SHADINGSYSTEM_OSL)
 		params.persistent_data = r.use_persistent_data();
diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp
index 4d684e51c1..21b8b98040 100644
--- a/intern/cycles/bvh/bvh_build.cpp
+++ b/intern/cycles/bvh/bvh_build.cpp
@@ -120,31 +120,101 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh,
 		if(mesh->has_motion_blur())
 			attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
 
-		size_t num_triangles = mesh->num_triangles();
+		const size_t num_triangles = mesh->num_triangles();
 		for(uint j = 0; j < num_triangles; j++) {
 			Mesh::Triangle t = mesh->get_triangle(j);
-			BoundBox bounds = BoundBox::empty;
-			PrimitiveType type = PRIMITIVE_TRIANGLE;
-
-			t.bounds_grow(&mesh->verts[0], bounds);
-
-			/* motion triangles */
-			if(attr_mP) {
+			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 - 1;
+				const size_t num_steps = mesh->motion_steps;
 				const float3 *vert_steps = attr_mP->data_float3();
-
-				for(size_t step = 0; step < num_steps; step++) {
+				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);
 				}
-
-				type = PRIMITIVE_MOTION_TRIANGLE;
+				if(bounds.valid()) {
+					references.push_back(
+					        BVHReference(bounds,
+					                     j,
+					                     i,
+					                     PRIMITIVE_MOTION_TRIANGLE));
+					root.grow(bounds);
+					center.grow(bounds.center2());
+				}
 			}
-
-			if(bounds.valid()) {
-				references.push_back(BVHReference(bounds, j, i, type));
-				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()) {
+						references.push_back(
+						        BVHReference(bounds,
+						                     j,
+						                     i,
+						                     PRIMITIVE_MOTION_TRIANGLE));
+						root.grow(bounds);
+						center.grow(bounds.center2());
+					}
+					/* Current time boundbox becomes previous one for the
+					 * next time step.
+					 */
+					prev_bounds = curr_bounds;
+				}
 			}
 		}
 	}
@@ -224,6 +294,7 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh,
 					                           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];
diff --git a/intern/cycles/bvh/bvh_params.h b/intern/cycles/bvh/bvh_params.h
index 1521fe9b5e..233c7adacb 100644
--- a/intern/cycles/bvh/bvh_params.h
+++ b/intern/cycles/bvh/bvh_params.h
@@ -69,6 +69,9 @@ public:
 	 */
 	int num_motion_curve_steps;
 
+	/* Same as above, but for triangle primitives. */
+	int num_motion_triangle_steps;
+
 	/* fixed parameters */
 	enum {
 		MAX_DEPTH = 64,
diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index 1522a2dc18..c42b32919d 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -1053,7 +1053,8 @@ void Mesh::compute_bvh(DeviceScene *dscene,
 			bparams.use_qbvh = params->use_qbvh;
 			bparams.use_unaligned_nodes = dscene->data.bvh.have_curves &&
 			                              params->use_bvh_unaligned_nodes;
-			bparams.num_motion_curve_steps = params->num_bvh_motion_curve_steps;
+			bparams.num_motion_triangle_steps = params->num_bvh_time_steps;
+			bparams.num_motion_curve_steps = params->num_bvh_time_steps;
 
 			delete bvh;
 			bvh = BVH::create(bparams, objects);
@@ -1822,7 +1823,8 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *
 	bparams.use_spatial_split = scene->params.use_bvh_spatial_split;
 	bparams.use_unaligned_nodes = dscene->data.bvh.have_curves &&
 	                              scene->params.use_bvh_unaligned_nodes;
-	bparams.num_motion_curve_steps = scene->params.num_bvh_motion_curve_steps;
+	bparams.num_motion_triangle_steps = scene->params.num_bvh_time_steps;
+	bparams.num_motion_curve_steps = scene->params.num_bvh_time_steps;
 
 	delete bvh;
 	bvh = BVH::create(bparams, scene->objects);
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index 948697dd13..8768682043 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -143,7 +143,7 @@ public:
 	} bvh_type;
 	bool use_bvh_spatial_split;
 	bool use_bvh_unaligned_nodes;
-	int num_bvh_motion_curve_steps;
+	int num_bvh_time_steps;
 	bool use_qbvh;
 	bool persistent_data;
 	int texture_limit;
@@ -154,7 +154,7 @@ public:
 		bvh_type = BVH_DYNAMIC;
 		use_bvh_spatial_split = false;
 		use_bvh_unaligned_nodes = true;
-		num_bvh_motion_curve_steps = 0;
+		num_bvh_time_steps = 0;
 		use_qbvh = false;
 		persistent_data = false;
 		texture_limit = 0;
@@ -165,7 +165,7 @@ public:
 		&& bvh_type == params.bvh_type
 		&& use_bvh_spatial_split == params.use_bvh_spatial_split
 		&& use_bvh_unaligned_nodes == params.use_bvh_unaligned_nodes
-		&& num_bvh_motion_curve_steps == params.num_bvh_motion_curve_steps
+		&& num_bvh_time_steps == params.num_bvh_time_steps
 		&& use_qbvh == params.use_qbvh
 		&& persistent_data == params.persistent_data
 		&& texture_limit == params.texture_limit); }




More information about the Bf-blender-cvs mailing list