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