Blender V4.3
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 use_scene_camera_cull_ = scene->camera->get_camera_type() != CAMERA_PANORAMA &&
26 !b_scene.render().use_multiview() &&
27 get_boolean(cscene, "use_camera_cull");
28 use_scene_distance_cull_ = scene->camera->get_camera_type() != CAMERA_PANORAMA &&
29 !b_scene.render().use_multiview() &&
30 get_boolean(cscene, "use_distance_cull");
31
32 camera_cull_margin_ = get_float(cscene, "camera_cull_margin");
33 distance_cull_margin_ = get_float(cscene, "distance_cull_margin");
34
35 if (distance_cull_margin_ == 0.0f) {
36 use_scene_distance_cull_ = false;
37 }
38 }
39}
40
41void BlenderObjectCulling::init_object(Scene *scene, BL::Object &b_ob)
42{
43 if (!use_scene_camera_cull_ && !use_scene_distance_cull_) {
44 return;
45 }
46
47 PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles");
48
49 use_camera_cull_ = use_scene_camera_cull_ && get_boolean(cobject, "use_camera_cull");
50 use_distance_cull_ = use_scene_distance_cull_ && get_boolean(cobject, "use_distance_cull");
51
52 if (use_camera_cull_ || use_distance_cull_) {
53 /* Need to have proper projection matrix. */
54 scene->camera->update(scene);
55 }
56}
57
58bool BlenderObjectCulling::test(Scene *scene, BL::Object &b_ob, Transform &tfm)
59{
60 if (!use_camera_cull_ && !use_distance_cull_) {
61 return false;
62 }
63
64 /* Compute world space bounding box corners. */
65 float3 bb[8];
66 BL::Array<float, 24> boundbox = b_ob.bound_box();
67 for (int i = 0; i < 8; ++i) {
68 float3 p = make_float3(boundbox[3 * i + 0], boundbox[3 * i + 1], boundbox[3 * i + 2]);
69 bb[i] = transform_point(&tfm, p);
70 }
71
72 bool camera_culled = use_camera_cull_ && test_camera(scene, bb);
73 bool distance_culled = use_distance_cull_ && test_distance(scene, bb);
74
75 return ((camera_culled && distance_culled) || (camera_culled && !use_distance_cull_) ||
76 (distance_culled && !use_camera_cull_));
77}
78
79/* TODO(sergey): Not really optimal, consider approaches based on k-DOP in order
80 * to reduce number of objects which are wrongly considered visible.
81 */
82bool BlenderObjectCulling::test_camera(Scene *scene, float3 bb[8])
83{
84 Camera *cam = scene->camera;
85 const ProjectionTransform &worldtondc = cam->worldtondc;
87 bb_max = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
88 bool all_behind = true;
89 for (int i = 0; i < 8; ++i) {
90 float3 p = bb[i];
91 float4 b = make_float4(p.x, p.y, p.z, 1.0f);
92 float4 c = make_float4(
93 dot(worldtondc.x, b), dot(worldtondc.y, b), dot(worldtondc.z, b), dot(worldtondc.w, b));
94 p = float4_to_float3(c / c.w);
95 if (c.z < 0.0f) {
96 p.x = 1.0f - p.x;
97 p.y = 1.0f - p.y;
98 }
99 if (c.z >= -camera_cull_margin_) {
100 all_behind = false;
101 }
102 bb_min = min(bb_min, p);
103 bb_max = max(bb_max, p);
104 }
105 if (all_behind) {
106 return true;
107 }
108 return (bb_min.x >= 1.0f + camera_cull_margin_ || bb_min.y >= 1.0f + camera_cull_margin_ ||
109 bb_max.x <= -camera_cull_margin_ || bb_max.y <= -camera_cull_margin_);
110}
111
112bool BlenderObjectCulling::test_distance(Scene *scene, float3 bb[8])
113{
114 float3 camera_position = transform_get_column(&scene->camera->get_matrix(), 3);
116 bb_max = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
117
118 /* Find min & max points for x & y & z on bounding box */
119 for (int i = 0; i < 8; ++i) {
120 float3 p = bb[i];
121 bb_min = min(bb_min, p);
122 bb_max = max(bb_max, p);
123 }
124
125 float3 closest_point = max(min(bb_max, camera_position), bb_min);
126 return (len_squared(camera_position - closest_point) >
127 distance_cull_margin_ * distance_cull_margin_);
128}
129
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)
local_group_size(16, 16) .push_constant(Type b
additional_info("compositor_sum_squared_difference_float_shared") .push_constant(Type output_img float dot(value.rgb, luminance_coefficients)") .define("LOAD(value)"
static float get_float(PointerRNA &ptr, const char *name)
static bool get_boolean(PointerRNA &ptr, const char *name)
#define CCL_NAMESPACE_END
ccl_device_forceinline float4 make_float4(const float x, const float y, const float z, const float w)
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
ccl_device_inline float3 camera_position(KernelGlobals kg)
@ CAMERA_PANORAMA
ccl_device_inline float len_squared(const float2 a)
PointerRNA RNA_pointer_get(PointerRNA *ptr, const char *name)
#define min(a, b)
Definition sort.c:32
#define FLT_MAX
Definition stdcycles.h:14
ProjectionTransform worldtondc
float z
Definition sky_float3.h:27
float y
Definition sky_float3.h:27
float x
Definition sky_float3.h:27
ccl_device_inline float3 transform_get_column(const Transform *t, int column)
Definition transform.h:326
CCL_NAMESPACE_END CCL_NAMESPACE_BEGIN ccl_device_inline float3 transform_point(ccl_private const Transform *t, const float3 a)
Definition transform.h:63
float max
ccl_device_inline float3 float4_to_float3(const float4 a)
Definition util/math.h:535