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
path: root/intern
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@gmail.com>2016-11-13 02:45:16 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2016-11-20 17:25:47 +0300
commitaea4ed00d5a7fe661f12fbe1a16ad6574d9be8ea (patch)
treead892c3792071b7fa5515cdc277a865c58c39516 /intern
parente8641d44740ed0e2c4a2a7bc4fb61aacec203c48 (diff)
Cycles: refactor culling code into utility class.
Diffstat (limited to 'intern')
-rw-r--r--intern/cycles/blender/blender_object.cpp271
-rw-r--r--intern/cycles/blender/blender_sync.h6
2 files changed, 150 insertions, 127 deletions
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index 84701a22d0a..681a22e1f07 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -88,6 +88,143 @@ static uint object_ray_visibility(BL::Object& b_ob)
return flag;
}
+/* Culling */
+
+class BlenderObjectCulling
+{
+public:
+ BlenderObjectCulling(Scene *scene, BL::Scene& b_scene)
+ : use_scene_camera_cull(false),
+ use_camera_cull(false),
+ camera_cull_margin(0.0f),
+ use_scene_distance_cull(false),
+ use_distance_cull(false),
+ distance_cull_margin(0.0f)
+ {
+ if(b_scene.render().use_simplify()) {
+ PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
+
+ use_scene_camera_cull = scene->camera->type != CAMERA_PANORAMA &&
+ !b_scene.render().use_multiview() &&
+ get_boolean(cscene, "use_camera_cull");
+ use_scene_distance_cull = scene->camera->type != CAMERA_PANORAMA &&
+ !b_scene.render().use_multiview() &&
+ get_boolean(cscene, "use_distance_cull");
+
+ camera_cull_margin = get_float(cscene, "camera_cull_margin");
+ distance_cull_margin = get_float(cscene, "distance_cull_margin");
+
+ if (distance_cull_margin == 0.0f) {
+ use_scene_distance_cull = false;
+ }
+ }
+ }
+
+ void init_object(Scene *scene, BL::Object& b_ob)
+ {
+ if(!use_scene_camera_cull && !use_scene_distance_cull) {
+ return;
+ }
+
+ PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles");
+
+ use_camera_cull = use_scene_camera_cull && get_boolean(cobject, "use_camera_cull");
+ use_distance_cull = use_scene_distance_cull && get_boolean(cobject, "use_distance_cull");
+
+ if(use_camera_cull || use_distance_cull) {
+ /* Need to have proper projection matrix. */
+ scene->camera->update();
+ }
+ }
+
+ bool test(Scene *scene, BL::Object& b_ob, Transform& tfm)
+ {
+ if(!use_camera_cull && !use_distance_cull) {
+ return false;
+ }
+
+ /* Compute world space bounding box corners. */
+ float3 bb[8];
+ BL::Array<float, 24> boundbox = b_ob.bound_box();
+ for(int i = 0; i < 8; ++i) {
+ float3 p = make_float3(boundbox[3 * i + 0],
+ boundbox[3 * i + 1],
+ boundbox[3 * i + 2]);
+ bb[i] = transform_point(&tfm, p);
+ }
+
+ bool camera_culled = use_camera_cull && test_camera(scene, bb);
+ bool distance_culled = use_distance_cull && test_distance(scene, bb);
+
+ return ((camera_culled && distance_culled) ||
+ (camera_culled && !use_distance_cull) ||
+ (distance_culled && !use_camera_cull));
+ }
+
+private:
+ /* TODO(sergey): Not really optimal, consider approaches based on k-DOP in order
+ * to reduce number of objects which are wrongly considered visible.
+ */
+ bool test_camera(Scene *scene, float3 bb[8])
+ {
+ Camera *cam = scene->camera;
+ Transform& worldtondc = cam->worldtondc;
+ float3 bb_min = make_float3(FLT_MAX, FLT_MAX, FLT_MAX),
+ bb_max = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
+ bool all_behind = true;
+ for(int i = 0; i < 8; ++i) {
+ float3 p = bb[i];
+ float4 b = make_float4(p.x, p.y, p.z, 1.0f);
+ float4 c = make_float4(dot(worldtondc.x, b),
+ dot(worldtondc.y, b),
+ dot(worldtondc.z, b),
+ dot(worldtondc.w, b));
+ p = float4_to_float3(c / c.w);
+ if(c.z < 0.0f) {
+ p.x = 1.0f - p.x;
+ p.y = 1.0f - p.y;
+ }
+ if(c.z >= -camera_cull_margin) {
+ all_behind = false;
+ }
+ bb_min = min(bb_min, p);
+ bb_max = max(bb_max, p);
+ }
+ if(all_behind) {
+ return true;
+ }
+ return (bb_min.x >= 1.0f + camera_cull_margin ||
+ bb_min.y >= 1.0f + camera_cull_margin ||
+ bb_max.x <= -camera_cull_margin ||
+ bb_max.y <= -camera_cull_margin);
+ }
+
+ bool test_distance(Scene *scene, float3 bb[8])
+ {
+ float3 camera_position = transform_get_column(&scene->camera->matrix, 3);
+ float3 bb_min = make_float3(FLT_MAX, FLT_MAX, FLT_MAX),
+ bb_max = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
+
+ /* Find min & max points for x & y & z on bounding box */
+ for(int i = 0; i < 8; ++i) {
+ float3 p = bb[i];
+ bb_min = min(bb_min, p);
+ bb_max = max(bb_max, p);
+ }
+
+ float3 closest_point = max(min(bb_max,camera_position),bb_min);
+ return (len_squared(camera_position - closest_point) >
+ distance_cull_margin * distance_cull_margin);
+ }
+
+ bool use_scene_camera_cull;
+ bool use_camera_cull;
+ float camera_cull_margin;
+ bool use_scene_distance_cull;
+ bool use_distance_cull;
+ float distance_cull_margin;
+};
+
/* Light */
void BlenderSync::sync_light(BL::Object& b_parent,
@@ -235,80 +372,6 @@ void BlenderSync::sync_background_light(bool use_portal)
/* Object */
-/* TODO(sergey): Not really optimal, consider approaches based on k-DOP in order
- * to reduce number of objects which are wrongly considered visible.
- */
-static bool object_boundbox_clip(Scene *scene,
- BL::Object& b_ob,
- Transform& tfm,
- float margin)
-{
- Camera *cam = scene->camera;
- Transform& worldtondc = cam->worldtondc;
- BL::Array<float, 24> boundbox = b_ob.bound_box();
- float3 bb_min = make_float3(FLT_MAX, FLT_MAX, FLT_MAX),
- bb_max = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
- bool all_behind = true;
- for(int i = 0; i < 8; ++i) {
- float3 p = make_float3(boundbox[3 * i + 0],
- boundbox[3 * i + 1],
- boundbox[3 * i + 2]);
- p = transform_point(&tfm, p);
-
- float4 b = make_float4(p.x, p.y, p.z, 1.0f);
- float4 c = make_float4(dot(worldtondc.x, b),
- dot(worldtondc.y, b),
- dot(worldtondc.z, b),
- dot(worldtondc.w, b));
- p = float4_to_float3(c / c.w);
- if(c.z < 0.0f) {
- p.x = 1.0f - p.x;
- p.y = 1.0f - p.y;
- }
- if(c.z >= -margin) {
- all_behind = false;
- }
- bb_min = min(bb_min, p);
- bb_max = max(bb_max, p);
- }
- if(!all_behind) {
- if(bb_min.x >= 1.0f + margin ||
- bb_min.y >= 1.0f + margin ||
- bb_max.x <= -margin ||
- bb_max.y <= -margin)
- {
- return true;
- }
- return false;
- }
- return true;
-}
-
-static bool object_distance_clip(Scene *scene,
- BL::Object& b_ob,
- Transform& tfm,
- float margin)
-{
- BL::Array<float, 24> boundbox = b_ob.bound_box();
- float3 camera_position = transform_get_column(&scene->camera->matrix, 3);
-
- float3 bb_min = make_float3(FLT_MAX, FLT_MAX, FLT_MAX),
- bb_max = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
-
- /* Find min & max points for x & y & z on bounding box */
- for(int i = 0; i < 8; ++i) {
- float3 p = make_float3(boundbox[3 * i + 0],
- boundbox[3 * i + 1],
- boundbox[3 * i + 2]);
- p = transform_point(&tfm, p);
- bb_min = min(bb_min, p);
- bb_max = max(bb_max, p);
- }
-
- float3 closest_point = max(min(bb_max,camera_position),bb_min);
- return (len_squared(camera_position - closest_point) > margin * margin);
-}
-
Object *BlenderSync::sync_object(BL::Object& b_parent,
int persistent_id[OBJECT_PERSISTENT_ID_SIZE],
BL::DupliObject& b_dupli_ob,
@@ -316,10 +379,7 @@ Object *BlenderSync::sync_object(BL::Object& b_parent,
uint layer_flag,
float motion_time,
bool hide_tris,
- bool use_camera_cull,
- bool use_distance_cull,
- float camera_cull_margin,
- float distance_cull_margin,
+ BlenderObjectCulling& culling,
bool *use_portal)
{
BL::Object b_ob = (b_dupli_ob ? b_dupli_ob.object() : b_parent);
@@ -335,17 +395,12 @@ Object *BlenderSync::sync_object(BL::Object& b_parent,
}
/* only interested in object that we can create meshes from */
- if(!object_is_mesh(b_ob))
+ if(!object_is_mesh(b_ob)) {
return NULL;
+ }
/* Perform object culling. */
- bool camera_culled = use_camera_cull && object_boundbox_clip(scene, b_ob, tfm, camera_cull_margin);
- bool distance_culled = use_distance_cull && object_distance_clip(scene, b_ob, tfm, distance_cull_margin);
-
- if ((camera_culled && distance_culled) ||
- (camera_culled && !use_distance_cull) ||
- (distance_culled && !use_camera_cull))
- {
+ if(culling.test(scene, b_ob, tfm)) {
return NULL;
}
@@ -581,28 +636,8 @@ void BlenderSync::sync_objects(BL::SpaceView3D& b_v3d, float motion_time)
mesh_motion_synced.clear();
}
- bool allow_camera_cull = false;
- bool allow_distance_cull = false;
- float camera_cull_margin = 0.0f;
- float distance_cull_margin = 0.0f;
- if(b_scene.render().use_simplify()) {
- PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
- allow_camera_cull = scene->camera->type != CAMERA_PANORAMA &&
- !b_scene.render().use_multiview() &&
- get_boolean(cscene, "use_camera_cull");
- allow_distance_cull = scene->camera->type != CAMERA_PANORAMA &&
- !b_scene.render().use_multiview() &&
- get_boolean(cscene, "use_distance_cull");
- if(allow_camera_cull) {
- camera_cull_margin = get_float(cscene, "camera_cull_margin");
- }
- if(allow_distance_cull) {
- distance_cull_margin = get_float(cscene, "distance_cull_margin");
- if (distance_cull_margin == 0.0f) {
- allow_distance_cull = false;
- }
- }
- }
+ /* initialize culling */
+ BlenderObjectCulling culling(scene, b_scene);
/* object loop */
BL::Scene::object_bases_iterator b_base;
@@ -634,13 +669,9 @@ void BlenderSync::sync_objects(BL::SpaceView3D& b_v3d, float motion_time)
if(!hide) {
progress.set_sync_status("Synchronizing object", b_ob.name());
- PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles");
- bool use_camera_cull = allow_camera_cull && get_boolean(cobject, "use_camera_cull");
- bool use_distance_cull = allow_distance_cull && get_boolean(cobject, "use_distance_cull");
- if(use_camera_cull || use_distance_cull) {
- /* Need to have proper projection matrix. */
- scene->camera->update();
- }
+ /* load per-object culling data */
+ culling.init_object(scene, b_ob);
+
if(b_ob.is_duplicator() && !object_render_hide_duplis(b_ob)) {
/* dupli objects */
b_ob.dupli_list_create(b_scene, dupli_settings);
@@ -667,10 +698,7 @@ void BlenderSync::sync_objects(BL::SpaceView3D& b_v3d, float motion_time)
ob_layer,
motion_time,
hide_tris,
- use_camera_cull,
- use_distance_cull,
- camera_cull_margin,
- distance_cull_margin,
+ culling,
&use_portal);
/* sync possible particle data, note particle_id
@@ -699,10 +727,7 @@ void BlenderSync::sync_objects(BL::SpaceView3D& b_v3d, float motion_time)
ob_layer,
motion_time,
hide_tris,
- use_camera_cull,
- use_distance_cull,
- camera_cull_margin,
- distance_cull_margin,
+ culling,
&use_portal);
}
}
diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h
index aa6b0d66e80..6984cbda259 100644
--- a/intern/cycles/blender/blender_sync.h
+++ b/intern/cycles/blender/blender_sync.h
@@ -35,6 +35,7 @@
CCL_NAMESPACE_BEGIN
class Background;
+class BlenderObjectCulling;
class Camera;
class Film;
class Light;
@@ -122,10 +123,7 @@ private:
uint layer_flag,
float motion_time,
bool hide_tris,
- bool use_camera_cull,
- bool use_distance_cull,
- float camera_cull_margin,
- float distance_cull_margin,
+ BlenderObjectCulling& culling,
bool *use_portal);
void sync_light(BL::Object& b_parent,
int persistent_id[OBJECT_PERSISTENT_ID_SIZE],