Blender  V3.3
object_cull.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright 2011-2022 Blender Foundation */
3 
4 #include <cstdlib>
5 
6 #include "scene/camera.h"
7 
8 #include "blender/object_cull.h"
9 #include "blender/util.h"
10 
12 
14  : use_scene_camera_cull_(false),
15  use_camera_cull_(false),
16  camera_cull_margin_(0.0f),
17  use_scene_distance_cull_(false),
18  use_distance_cull_(false),
19  distance_cull_margin_(0.0f)
20 {
21  if (b_scene.render().use_simplify()) {
22  PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
23 
24  use_scene_camera_cull_ = scene->camera->get_camera_type() != CAMERA_PANORAMA &&
25  !b_scene.render().use_multiview() &&
26  get_boolean(cscene, "use_camera_cull");
27  use_scene_distance_cull_ = scene->camera->get_camera_type() != CAMERA_PANORAMA &&
28  !b_scene.render().use_multiview() &&
29  get_boolean(cscene, "use_distance_cull");
30 
31  camera_cull_margin_ = get_float(cscene, "camera_cull_margin");
32  distance_cull_margin_ = get_float(cscene, "distance_cull_margin");
33 
34  if (distance_cull_margin_ == 0.0f) {
35  use_scene_distance_cull_ = false;
36  }
37  }
38 }
39 
41 {
42  if (!use_scene_camera_cull_ && !use_scene_distance_cull_) {
43  return;
44  }
45 
46  PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles");
47 
48  use_camera_cull_ = use_scene_camera_cull_ && get_boolean(cobject, "use_camera_cull");
49  use_distance_cull_ = use_scene_distance_cull_ && get_boolean(cobject, "use_distance_cull");
50 
51  if (use_camera_cull_ || use_distance_cull_) {
52  /* Need to have proper projection matrix. */
53  scene->camera->update(scene);
54  }
55 }
56 
58 {
59  if (!use_camera_cull_ && !use_distance_cull_) {
60  return false;
61  }
62 
63  /* Compute world space bounding box corners. */
64  float3 bb[8];
65  BL::Array<float, 24> boundbox = b_ob.bound_box();
66  for (int i = 0; i < 8; ++i) {
67  float3 p = make_float3(boundbox[3 * i + 0], boundbox[3 * i + 1], boundbox[3 * i + 2]);
68  bb[i] = transform_point(&tfm, p);
69  }
70 
71  bool camera_culled = use_camera_cull_ && test_camera(scene, bb);
72  bool distance_culled = use_distance_cull_ && test_distance(scene, bb);
73 
74  return ((camera_culled && distance_culled) || (camera_culled && !use_distance_cull_) ||
75  (distance_culled && !use_camera_cull_));
76 }
77 
78 /* TODO(sergey): Not really optimal, consider approaches based on k-DOP in order
79  * to reduce number of objects which are wrongly considered visible.
80  */
81 bool BlenderObjectCulling::test_camera(Scene *scene, float3 bb[8])
82 {
83  Camera *cam = scene->camera;
84  const ProjectionTransform &worldtondc = cam->worldtondc;
85  float3 bb_min = make_float3(FLT_MAX, FLT_MAX, FLT_MAX),
86  bb_max = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
87  bool all_behind = true;
88  for (int i = 0; i < 8; ++i) {
89  float3 p = bb[i];
90  float4 b = make_float4(p.x, p.y, p.z, 1.0f);
92  dot(worldtondc.x, b), dot(worldtondc.y, b), dot(worldtondc.z, b), dot(worldtondc.w, b));
93  p = float4_to_float3(c / c.w);
94  if (c.z < 0.0f) {
95  p.x = 1.0f - p.x;
96  p.y = 1.0f - p.y;
97  }
98  if (c.z >= -camera_cull_margin_) {
99  all_behind = false;
100  }
101  bb_min = min(bb_min, p);
102  bb_max = max(bb_max, p);
103  }
104  if (all_behind) {
105  return true;
106  }
107  return (bb_min.x >= 1.0f + camera_cull_margin_ || bb_min.y >= 1.0f + camera_cull_margin_ ||
108  bb_max.x <= -camera_cull_margin_ || bb_max.y <= -camera_cull_margin_);
109 }
110 
111 bool BlenderObjectCulling::test_distance(Scene *scene, float3 bb[8])
112 {
114  float3 bb_min = make_float3(FLT_MAX, FLT_MAX, FLT_MAX),
115  bb_max = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
116 
117  /* Find min & max points for x & y & z on bounding box */
118  for (int i = 0; i < 8; ++i) {
119  float3 p = bb[i];
120  bb_min = min(bb_min, p);
121  bb_max = max(bb_max, p);
122  }
123 
124  float3 closest_point = max(min(bb_max, camera_position), bb_min);
125  return (len_squared(camera_position - closest_point) >
126  distance_cull_margin_ * distance_cull_margin_);
127 }
128 
struct Object Object
struct Scene Scene
float float4[4]
BlenderObjectCulling(Scene *scene, BL::Scene &b_scene)
Definition: object_cull.cpp:13
void init_object(Scene *scene, BL::Object &b_ob)
Definition: object_cull.cpp:40
bool test(Scene *scene, BL::Object &b_ob, Transform &tfm)
Definition: object_cull.cpp:57
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
static float get_float(PointerRNA &ptr, const char *name)
static bool get_boolean(PointerRNA &ptr, const char *name)
Scene scene
ccl_device_inline float3 transform_get_column(const Transform *t, int column)
CCL_NAMESPACE_END CCL_NAMESPACE_BEGIN ccl_device_inline float3 transform_point(ccl_private const Transform *t, const float3 a)
ccl_device_inline float3 camera_position(KernelGlobals kg)
@ CAMERA_PANORAMA
Definition: kernel/types.h:466
ccl_device_inline float len_squared(const float3 a)
Definition: math_float3.h:423
#define make_float4(x, y, z, w)
Definition: metal/compat.h:205
#define make_float3(x, y, z)
Definition: metal/compat.h:204
static unsigned c
Definition: RandGen.cpp:83
T dot(const vec_base< T, Size > &a, const vec_base< T, Size > &b)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
PointerRNA RNA_pointer_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5167
#define min(a, b)
Definition: sort.c:35
ProjectionTransform worldtondc
Definition: scene/camera.h:152
struct Object * camera
float z
float y
float x
float max
ccl_device_inline float3 float4_to_float3(const float4 a)
Definition: util/math.h:500