Blender V5.0
light_tree_debug.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2025 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
6
7#include "scene/light.h"
8#include "scene/light_tree.h"
9#include "scene/object.h"
10#include "scene/scene.h"
11
12#include "util/path.h"
13#include "util/string.h"
14
16
17static string get_node_id(const LightTreeNode &node)
18{
19 return string_printf("node@%p", &node);
20}
21
22static string get_emitter_id(const LightTreeEmitter &emitter)
23{
24 return string_printf("emitter@%p", &emitter);
25}
26
27static string set_membership_str(const uint64_t set_membership)
28{
29 if (set_membership == ~uint64_t(0)) {
30 return "ALL";
31 }
32 return std::to_string(set_membership);
33}
34
35static void recursive_print_node(FILE *file, const LightTreeNode &node)
36{
37 int field = 0;
38
39 string label = string_printf("<f%d> node @%p", field++, &node);
40 if (node.is_instance()) {
41 label += string_printf("| <f%d> instance", field++);
42 }
43 if (node.is_leaf()) {
44 label += string_printf("| <f%d> leaf", field++);
45 }
46 if (node.is_inner()) {
47 label += string_printf("| <f%d> inner", field++);
48 }
49 if (node.is_distant()) {
50 label += string_printf("| <f%d> distant", field++);
51 }
52
53 if (node.light_link.set_membership == ~uint64_t(0)) {
54 label += string_printf("| <f%d> set membership:ALL", field++);
55 }
56 else {
57 label += string_printf("| <f%d> set membership:%s",
58 field++,
60 }
61
62 label += string_printf(
63 "| <f%d> shareable:%s", field++, node.light_link.shareable ? "True" : "False");
64
65 if (node.is_inner()) {
66 label += string_printf("| <left> left");
67 label += string_printf("| <right> right");
68 }
69 else if (node.is_leaf()) {
70 label += string_printf("| <emitters> emitters");
71 }
72
73 fprintf(file, "\"%s\" [\n", get_node_id(node).c_str());
74 fprintf(file, " label = \"%s\"\n", label.c_str());
75 fprintf(file, " shape = \"record\"\n");
76 fprintf(file, "];\n");
77
78 if (node.is_inner()) {
79 const LightTreeNode &left_node = *node.get_inner().children[LightTree::left];
80 const LightTreeNode &right_node = *node.get_inner().children[LightTree::right];
81
82 recursive_print_node(file, left_node);
83 recursive_print_node(file, right_node);
84 }
85}
86
87static void print_emitters(FILE *file, const Scene &scene, const LightTree &tree)
88{
89 const size_t num_emitters = tree.num_emitters();
90 const LightTreeEmitter *emitters = tree.get_emitters();
91 for (size_t i = 0; i < num_emitters; ++i) {
92 const LightTreeEmitter &emitter = emitters[i];
93
94 int field = 0;
95
96 string label = string_printf("<f%d> emitter %s", field++, std::to_string(i).c_str());
97
98 /* Emitter details (type, object or light name). */
99 const Object &object = *scene.objects[emitter.object_id];
100 if (emitter.is_light()) {
101 label += string_printf("|<f%d> light", field++);
102 }
103 else if (emitter.is_triangle()) {
104 label += string_printf("|<f%d> triangle", field++);
105 }
106 else if (emitter.is_mesh()) {
107 label += string_printf("|<f%d> mesh", field++);
108 }
109 label += string_printf("|<f%d> %s", field++, object.name.c_str());
110
111 /* Light linking. */
112 if (emitter.light_set_membership == ~uint64_t(0)) {
113 label += string_printf("|<f%d> set membership:ALL", field++);
114 }
115 else {
116 label += string_printf("|<f%d> set membership:%s",
117 field++,
119 }
120
121 /* Bounding box. */
122 label += string_printf("|<f%d> bbox.min (%f %f %f)",
123 field++,
124 double(emitter.measure.bbox.min.x),
125 double(emitter.measure.bbox.min.y),
126 double(emitter.measure.bbox.min.z));
127 label += string_printf("|<f%d> bbox.max (%f %f %f)",
128 field++,
129 double(emitter.measure.bbox.max.x),
130 double(emitter.measure.bbox.max.y),
131 double(emitter.measure.bbox.max.z));
132
133 /* Orientation bounds. */
134 label += string_printf("|<f%d> bcone.axis (%f %f %f)",
135 field++,
136 double(emitter.measure.bcone.axis.x),
137 double(emitter.measure.bcone.axis.y),
138 double(emitter.measure.bcone.axis.z));
139 label += string_printf("|<f%d> theta_o %f, theta_e %f",
140 field++,
141 double(emitter.measure.bcone.theta_o),
142 double(emitter.measure.bcone.theta_e));
143
144 /* Print node to the file. */
145 fprintf(file, "\"%s\" [\n", get_emitter_id(emitter).c_str());
146 fprintf(file, " label = \"%s\"\n", label.c_str());
147 fprintf(file, " shape = \"record\"\n");
148 fprintf(file, "];\n");
149 }
150}
151
152static void recursive_print_node_relations(FILE *file,
153 const LightTree &tree,
154 const LightTreeNode &node,
155 int &relation_id)
156{
157 const string from_node_id = get_node_id(node);
158
159 if (node.is_leaf() || node.is_distant()) {
160 const LightTreeEmitter *emitters = tree.get_emitters();
161 for (int i = 0; i < node.get_leaf().num_emitters; i++) {
162 const LightTreeEmitter &emitter = emitters[node.get_leaf().first_emitter_index + i];
163 fprintf(file,
164 "\"%s\":<emitters> -> \"%s\":f0 [ id = %d ];\n",
165 from_node_id.c_str(),
166 get_emitter_id(emitter).c_str(),
167 relation_id++);
168 }
169 return;
170 }
171
172 if (!node.is_inner()) {
173 return;
174 }
175
176 const LightTreeNode &left_node = *node.get_inner().children[LightTree::left];
177 const LightTreeNode &right_node = *node.get_inner().children[LightTree::right];
178
179 const string left_node_id = get_node_id(left_node);
180 const string right_node_id = get_node_id(right_node);
181
182 fprintf(file,
183 "\"%s\":left -> \"%s\":f0 [ id = %d ];\n",
184 from_node_id.c_str(),
185 left_node_id.c_str(),
186 relation_id++);
187
188 fprintf(file,
189 "\"%s\":right -> \"%s\":f0 [ id = %d ];\n",
190 from_node_id.c_str(),
191 right_node_id.c_str(),
192 relation_id++);
193
194 recursive_print_node_relations(file, tree, left_node, relation_id);
195 recursive_print_node_relations(file, tree, right_node, relation_id);
196}
197
199 const LightTree &tree,
200 const LightTreeNode &root_node,
201 const string &filename)
202{
203 FILE *file = path_fopen(filename, "w");
204 if (!file) {
205 return;
206 }
207
208 int relation_id = 0;
209
210 fprintf(file, "digraph g {\n");
211 fprintf(file, "graph [\n");
212 fprintf(file, " rankdir = \"LR\"\n");
213 fprintf(file, "];\n");
214 recursive_print_node(file, root_node);
215 print_emitters(file, scene, tree);
216 recursive_print_node_relations(file, tree, root_node, relation_id);
217 fprintf(file, "}\n");
218
219 fclose(file);
220}
221
222static string get_knode_id(const KernelLightTreeNode &knode)
223{
224 return string_printf("knode@%p", &knode);
225}
226
227static void recursive_print_knode(FILE *file,
228 const uint knode_index,
229 const KernelLightTreeNode *knodes,
230 int &relation_id)
231{
232 const KernelLightTreeNode &knode = knodes[knode_index];
233
234 /* The distant node is also considered o leaf node. */
235 const bool is_leaf = knode.type >= LIGHT_TREE_LEAF;
236 const bool is_inner = !is_leaf;
237
238 assert(!is_inner || knode.type != LIGHT_TREE_INSTANCE);
239
240 int field = 0;
241
242 string label = string_printf("<f%d> knode %u", field++, knode_index);
243
244 /* Bounding box. */
245 label += string_printf("|<f%d> min (%f %f %f)",
246 field++,
247 double(knode.bbox.min.x),
248 double(knode.bbox.min.y),
249 double(knode.bbox.min.z));
250 label += string_printf("|<f%d> max (%f %f %f)",
251 field++,
252 double(knode.bbox.max.x),
253 double(knode.bbox.max.y),
254 double(knode.bbox.max.z));
255
256 /* Orientation bounds. */
257 label += string_printf("|<f%d> bcone.axis (%f %f %f)",
258 field++,
259 double(knode.bcone.axis.x),
260 double(knode.bcone.axis.y),
261 double(knode.bcone.axis.z));
262 label += string_printf("|<f%d> theta_o %f, theta_e %f",
263 field++,
264 double(knode.bcone.theta_o),
265 double(knode.bcone.theta_e));
266
267 label += string_printf("|<f%d> energy %f", field++, knode.energy);
268
269 if (is_leaf) {
270 label += string_printf("|<f%d> first emitter %d", field++, knode.leaf.first_emitter);
271 label += string_printf("|<f%d> num emitters %d", field++, knode.num_emitters);
272 }
273
274 label += string_printf("|<f%d> bit trail %u", field++, knode.bit_trail);
275 label += string_printf("|<f%d> bit skip %d", field++, int(knode.bit_skip));
276
277 if (is_inner) {
278 label += string_printf("| <left> left");
279 label += string_printf("| <right> right");
280 }
281
282 const string knode_id = get_knode_id(knode);
283
284 /* Print node to the file. */
285 fprintf(file, "\"%s\" [\n", knode_id.c_str());
286 fprintf(file, " label = \"%s\"\n", label.c_str());
287 fprintf(file, " shape = \"record\"\n");
288 fprintf(file, "];\n");
289
290 /* Print relations. */
291 if (is_inner) {
292 recursive_print_knode(file, knode.inner.left_child, knodes, relation_id);
293 recursive_print_knode(file, knode.inner.right_child, knodes, relation_id);
294
295 fprintf(file,
296 "\"%s\":left -> \"%s\":f0 [ id = %d ];\n",
297 knode_id.c_str(),
298 get_knode_id(knodes[knode.inner.left_child]).c_str(),
299 relation_id++);
300 fprintf(file,
301 "\"%s\":right -> \"%s\":f0 [ id = %d ];\n",
302 knode_id.c_str(),
303 get_knode_id(knodes[knode.inner.right_child]).c_str(),
304 relation_id++);
305 }
306}
307
308void klight_tree_plot_to_file(uint root, const KernelLightTreeNode *knodes, const string &filename)
309{
310 FILE *file = path_fopen(filename, "w");
311 if (!file) {
312 return;
313 }
314
315 int relation_id = 0;
316
317 fprintf(file, "digraph g {\n");
318 fprintf(file, "graph [\n");
319 fprintf(file, " rankdir = \"LR\"\n");
320 fprintf(file, "];\n");
321 recursive_print_knode(file, root, knodes, relation_id);
322 fprintf(file, "}\n");
323
324 fclose(file);
325}
326
unsigned int uint
unsigned long long int uint64_t
#define CCL_NAMESPACE_END
KDTree_3d * tree
#define assert(assertion)
@ LIGHT_TREE_INSTANCE
@ LIGHT_TREE_LEAF
void klight_tree_plot_to_file(uint root, const KernelLightTreeNode *knodes, const string &filename)
static CCL_NAMESPACE_BEGIN string get_node_id(const LightTreeNode &node)
static void recursive_print_node_relations(FILE *file, const LightTree &tree, const LightTreeNode &node, int &relation_id)
static string set_membership_str(const uint64_t set_membership)
static void recursive_print_knode(FILE *file, const uint knode_index, const KernelLightTreeNode *knodes, int &relation_id)
static void recursive_print_node(FILE *file, const LightTreeNode &node)
void light_tree_plot_to_file(const Scene &scene, const LightTree &tree, const LightTreeNode &root_node, const string &filename)
static string get_emitter_id(const LightTreeEmitter &emitter)
static void print_emitters(FILE *file, const Scene &scene, const LightTree &tree)
static string get_knode_id(const KernelLightTreeNode &knode)
FILE * path_fopen(const string &path, const string &mode)
Definition path.cpp:975
const char * name
CCL_NAMESPACE_BEGIN string string_printf(const char *format,...)
Definition string.cpp:23
float3 max
Definition boundbox.h:20
float3 min
Definition boundbox.h:20
packed_float3 min
packed_float3 max
packed_float3 axis
LightTreeNodeType type
KernelBoundingBox bbox
struct KernelLightTreeNode::@075060275333356206225201163255143122031204113015::@121232343267032302300332005257270111102366024356 inner
KernelBoundingCone bcone
struct KernelLightTreeNode::@075060275333356206225201163255143122031204113015::@354167317357124241334100100220231122277063225056 leaf
__forceinline bool is_mesh() const
Definition light_tree.h:205
__forceinline bool is_triangle() const
Definition light_tree.h:210
uint64_t light_set_membership
Definition light_tree.h:195
LightTreeMeasure measure
Definition light_tree.h:197
__forceinline bool is_light() const
Definition light_tree.h:215
OrientationBounds bcone
Definition light_tree.h:66
unique_ptr< LightTreeNode > children[2]
Definition light_tree.h:268
__forceinline Inner & get_inner()
Definition light_tree.h:301
__forceinline bool is_leaf() const
Definition light_tree.h:365
__forceinline bool is_inner() const
Definition light_tree.h:370
LightTreeLightLink light_link
Definition light_tree.h:251
__forceinline bool is_instance() const
Definition light_tree.h:360
__forceinline Leaf & get_leaf()
Definition light_tree.h:291
__forceinline bool is_distant() const
Definition light_tree.h:375
unique_ptr_vector< Object > objects
Definition scene.h:141
float z
Definition sky_math.h:136
float y
Definition sky_math.h:136
float x
Definition sky_math.h:136
i
Definition text_draw.cc:230
ccl_device_inline bool is_leaf(const ccl_global KernelLightTreeNode *knode)
Definition tree.h:84