Blender V4.3
cycles/blender/util.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#ifndef __BLENDER_UTIL_H__
6#define __BLENDER_UTIL_H__
7
8#include "scene/mesh.h"
9#include "scene/scene.h"
10
11#include "util/algorithm.h"
12#include "util/array.h"
13#include "util/map.h"
14#include "util/path.h"
15#include "util/set.h"
16#include "util/transform.h"
17#include "util/types.h"
18#include "util/vector.h"
19
20#include "BKE_image.hh"
21#include "BKE_mesh.hh"
22
24
26 /* Object directly provided by the depsgraph iterator. This object is only valid during one
27 * iteration and must not be accessed afterwards. Transforms and visibility should be checked on
28 * this object. */
29 BL::Object iter_object;
30
31 /* This object remains alive even after the object iterator is done. It corresponds to one
32 * original object. It is the object that owns the object data below. */
33 BL::Object real_object;
34
35 /* The object-data referenced by the iter object. This is still valid after the depsgraph
36 * iterator is done. It might have a different type compared to real_object.data(). */
38
39 /* True when the current geometry is the data of the referenced object. False when it is a
40 * geometry instance that does not have a 1-to-1 relationship with an object. */
42 {
43 return const_cast<BL::Object &>(real_object).data() == object_data;
44 }
45};
46
47typedef BL::ShaderNodeAttribute::attribute_type_enum BlenderAttributeType;
48BlenderAttributeType blender_attribute_name_split_type(ustring name, string *r_real_name);
49
50void python_thread_state_save(void **python_thread_state);
51void python_thread_state_restore(void **python_thread_state);
52
53static bool mesh_use_corner_normals(BL::Mesh &mesh, Mesh::SubdivisionType subdivision_type)
54{
55 return mesh && (subdivision_type == Mesh::SUBDIVISION_NONE) &&
56 (static_cast<const ::Mesh *>(mesh.ptr.data)->normals_domain(true) ==
58}
59
60static inline BL::Mesh object_to_mesh(BL::BlendData & /*data*/,
61 BObjectInfo &b_ob_info,
62 BL::Depsgraph & /*depsgraph*/,
63 bool /*calc_undeformed*/,
64 Mesh::SubdivisionType subdivision_type)
65{
66 /* TODO: make this work with copy-on-evaluation, modifiers are already evaluated. */
67#if 0
68 bool subsurf_mod_show_render = false;
69 bool subsurf_mod_show_viewport = false;
70
71 if (subdivision_type != Mesh::SUBDIVISION_NONE) {
72 BL::Modifier subsurf_mod = object.modifiers[object.modifiers.length() - 1];
73
74 subsurf_mod_show_render = subsurf_mod.show_render();
75 subsurf_mod_show_viewport = subsurf_mod.show_viewport();
76
77 subsurf_mod.show_render(false);
78 subsurf_mod.show_viewport(false);
79 }
80#endif
81
82 BL::Mesh mesh = (b_ob_info.object_data.is_a(&RNA_Mesh)) ? BL::Mesh(b_ob_info.object_data) :
83 BL::Mesh(PointerRNA_NULL);
84
85 bool use_corner_normals = false;
86
87 if (b_ob_info.is_real_object_data()) {
88 if (mesh) {
89 if (mesh.is_editmode()) {
90 /* Flush edit-mesh to mesh, including all data layers. */
91 BL::Depsgraph depsgraph(PointerRNA_NULL);
92 mesh = b_ob_info.real_object.to_mesh(false, depsgraph);
93 use_corner_normals = mesh_use_corner_normals(mesh, subdivision_type);
94 }
95 else if (mesh_use_corner_normals(mesh, subdivision_type)) {
96 /* Make a copy to split faces. */
97 BL::Depsgraph depsgraph(PointerRNA_NULL);
98 mesh = b_ob_info.real_object.to_mesh(false, depsgraph);
99 use_corner_normals = true;
100 }
101 }
102 else {
103 BL::Depsgraph depsgraph(PointerRNA_NULL);
104 mesh = b_ob_info.real_object.to_mesh(false, depsgraph);
105 use_corner_normals = mesh_use_corner_normals(mesh, subdivision_type);
106 }
107 }
108 else {
109 /* TODO: what to do about non-mesh geometry instances? */
110 use_corner_normals = mesh_use_corner_normals(mesh, subdivision_type);
111 }
112
113#if 0
114 if (subdivision_type != Mesh::SUBDIVISION_NONE) {
115 BL::Modifier subsurf_mod = object.modifiers[object.modifiers.length() - 1];
116
117 subsurf_mod.show_render(subsurf_mod_show_render);
118 subsurf_mod.show_viewport(subsurf_mod_show_viewport);
119 }
120#endif
121
122 if (mesh) {
123 if (use_corner_normals) {
124 mesh.split_faces();
125 }
126
127 if (subdivision_type == Mesh::SUBDIVISION_NONE) {
128 mesh.calc_loop_triangles();
129 }
130 }
131
132 return mesh;
133}
134
135static inline void free_object_to_mesh(BL::BlendData & /*data*/,
136 BObjectInfo &b_ob_info,
137 BL::Mesh &mesh)
138{
139 if (!b_ob_info.is_real_object_data()) {
140 return;
141 }
142 /* Free mesh if we didn't just use the existing one. */
143 BL::Object object = b_ob_info.real_object;
144 if (object.data().ptr.data != mesh.ptr.data) {
145 object.to_mesh_clear();
146 }
147}
148
149static inline void colorramp_to_array(BL::ColorRamp &ramp,
150 array<float3> &ramp_color,
151 array<float> &ramp_alpha,
152 int size)
153{
154 const int full_size = size + 1;
155 ramp_color.resize(full_size);
156 ramp_alpha.resize(full_size);
157
158 for (int i = 0; i < full_size; i++) {
159 float color[4];
160
161 ramp.evaluate(float(i) / float(size), color);
162 ramp_color[i] = make_float3(color[0], color[1], color[2]);
163 ramp_alpha[i] = color[3];
164 }
165}
166
167static inline void curvemap_minmax_curve(/*const*/ BL::CurveMap &curve, float *min_x, float *max_x)
168{
169 *min_x = min(*min_x, curve.points[0].location()[0]);
170 *max_x = max(*max_x, curve.points[curve.points.length() - 1].location()[0]);
171}
172
173static inline void curvemapping_minmax(/*const*/ BL::CurveMapping &cumap,
174 int num_curves,
175 float *min_x,
176 float *max_x)
177{
178 // const int num_curves = cumap.curves.length(); /* Gives linking error so far. */
179 *min_x = FLT_MAX;
180 *max_x = -FLT_MAX;
181 for (int i = 0; i < num_curves; ++i) {
182 BL::CurveMap map(cumap.curves[i]);
183 curvemap_minmax_curve(map, min_x, max_x);
184 }
185}
186
187static inline void curvemapping_to_array(BL::CurveMapping &cumap, array<float> &data, int size)
188{
189 cumap.update();
190 BL::CurveMap curve = cumap.curves[0];
191 const int full_size = size + 1;
192 data.resize(full_size);
193 for (int i = 0; i < full_size; i++) {
194 float t = float(i) / float(size);
195 data[i] = cumap.evaluate(curve, t);
196 }
197}
198
199static inline void curvemapping_float_to_array(BL::CurveMapping &cumap,
201 int size)
202{
203 float min = 0.0f, max = 1.0f;
204
205 curvemapping_minmax(cumap, 1, &min, &max);
206
207 const float range = max - min;
208
209 cumap.update();
210
211 BL::CurveMap map = cumap.curves[0];
212
213 const int full_size = size + 1;
214 data.resize(full_size);
215
216 for (int i = 0; i < full_size; i++) {
217 float t = min + float(i) / float(size) * range;
218 data[i] = cumap.evaluate(map, t);
219 }
220}
221
222static inline void curvemapping_color_to_array(BL::CurveMapping &cumap,
224 int size,
225 bool rgb_curve)
226{
227 float min_x = 0.0f, max_x = 1.0f;
228
229 /* TODO(sergey): There is no easy way to automatically guess what is
230 * the range to be used here for the case when mapping is applied on
231 * top of another mapping (i.e. R curve applied on top of common
232 * one).
233 *
234 * Using largest possible range form all curves works correct for the
235 * cases like vector curves and should be good enough heuristic for
236 * the color curves as well.
237 *
238 * There might be some better estimations here tho.
239 */
240 const int num_curves = rgb_curve ? 4 : 3;
241 curvemapping_minmax(cumap, num_curves, &min_x, &max_x);
242
243 const float range_x = max_x - min_x;
244
245 cumap.update();
246
247 BL::CurveMap mapR = cumap.curves[0];
248 BL::CurveMap mapG = cumap.curves[1];
249 BL::CurveMap mapB = cumap.curves[2];
250
251 const int full_size = size + 1;
252 data.resize(full_size);
253
254 if (rgb_curve) {
255 BL::CurveMap mapI = cumap.curves[3];
256 for (int i = 0; i < full_size; i++) {
257 const float t = min_x + float(i) / float(size) * range_x;
258 data[i] = make_float3(cumap.evaluate(mapR, cumap.evaluate(mapI, t)),
259 cumap.evaluate(mapG, cumap.evaluate(mapI, t)),
260 cumap.evaluate(mapB, cumap.evaluate(mapI, t)));
261 }
262 }
263 else {
264 for (int i = 0; i < full_size; i++) {
265 float t = min_x + float(i) / float(size) * range_x;
266 data[i] = make_float3(
267 cumap.evaluate(mapR, t), cumap.evaluate(mapG, t), cumap.evaluate(mapB, t));
268 }
269 }
270}
271
272static inline bool BKE_object_is_modified(BL::Object &self, BL::Scene &scene, bool preview)
273{
274 return self.is_modified(scene, (preview) ? (1 << 0) : (1 << 1)) ? true : false;
275}
276
277static inline bool BKE_object_is_deform_modified(BObjectInfo &self, BL::Scene &scene, bool preview)
278{
279 if (!self.is_real_object_data()) {
280 /* Comes from geometry nodes, can't use heuristic to guess if it's animated. */
281 return true;
282 }
283
284 /* Use heuristic to quickly check if object is potentially animated. */
285 return self.real_object.is_deform_modified(scene, (preview) ? (1 << 0) : (1 << 1)) ? true :
286 false;
287}
288
289static inline int render_resolution_x(BL::RenderSettings &b_render)
290{
291 return b_render.resolution_x() * b_render.resolution_percentage() / 100;
292}
293
294static inline int render_resolution_y(BL::RenderSettings &b_render)
295{
296 return b_render.resolution_y() * b_render.resolution_percentage() / 100;
297}
298
299static inline string image_user_file_path(BL::BlendData &data,
300 BL::ImageUser &iuser,
301 BL::Image &ima,
302 int cfra)
303{
304 char filepath[1024];
305 iuser.tile(0);
307 static_cast<Image *>(ima.ptr.data), static_cast<ImageUser *>(iuser.ptr.data), cfra);
308 BKE_image_user_file_path_ex(static_cast<Main *>(data.ptr.data),
309 static_cast<ImageUser *>(iuser.ptr.data),
310 static_cast<Image *>(ima.ptr.data),
311 filepath,
312 false,
313 true);
314
315 return string(filepath);
316}
317
318static inline int image_user_frame_number(BL::ImageUser &iuser, BL::Image &ima, int cfra)
319{
321 static_cast<Image *>(ima.ptr.data), static_cast<ImageUser *>(iuser.ptr.data), cfra);
322 return iuser.frame_current();
323}
324
325static inline unsigned char *image_get_pixels_for_frame(BL::Image &image, int frame, int tile)
326{
327 return BKE_image_get_pixels_for_frame(static_cast<Image *>(image.ptr.data), frame, tile);
328}
329
330static inline float *image_get_float_pixels_for_frame(BL::Image &image, int frame, int tile)
331{
332 return BKE_image_get_float_pixels_for_frame(static_cast<Image *>(image.ptr.data), frame, tile);
333}
334
335static inline bool image_is_builtin(BL::Image &ima, BL::RenderEngine &engine)
336{
337 const BL::Image::source_enum image_source = ima.source();
338 if (image_source == BL::Image::source_TILED) {
339 /* If any tile is marked as generated, then treat the entire Image as built-in. */
340 for (BL::UDIMTile &tile : ima.tiles) {
341 if (tile.is_generated_tile()) {
342 return true;
343 }
344 }
345 }
346
347 return ima.packed_file() || image_source == BL::Image::source_GENERATED ||
348 image_source == BL::Image::source_MOVIE ||
349 (engine.is_preview() && image_source != BL::Image::source_SEQUENCE);
350}
351
352static inline void render_add_metadata(BL::RenderResult &b_rr, string name, string value)
353{
354 b_rr.stamp_data_add_field(name.c_str(), value.c_str());
355}
356
357/* Utilities */
358
359static inline Transform get_transform(const BL::Array<float, 16> &array)
360{
361 ProjectionTransform projection;
362
363 /* We assume both types to be just 16 floats, and transpose because blender
364 * use column major matrix order while we use row major. */
365 memcpy((void *)&projection, &array, sizeof(float) * 16);
366 projection = projection_transpose(projection);
367
368 /* Drop last row, matrix is assumed to be affine transform. */
369 return projection_to_transform(projection);
370}
371
372static inline float2 get_float2(const BL::Array<float, 2> &array)
373{
374 return make_float2(array[0], array[1]);
375}
376
377static inline float3 get_float3(const BL::Array<float, 2> &array)
378{
379 return make_float3(array[0], array[1], 0.0f);
380}
381
382static inline float3 get_float3(const BL::Array<float, 3> &array)
383{
384 return make_float3(array[0], array[1], array[2]);
385}
386
387static inline float3 get_float3(const BL::Array<float, 4> &array)
388{
389 return make_float3(array[0], array[1], array[2]);
390}
391
392static inline float4 get_float4(const BL::Array<float, 4> &array)
393{
394 return make_float4(array[0], array[1], array[2], array[3]);
395}
396
397static inline int3 get_int3(const BL::Array<int, 3> &array)
398{
399 return make_int3(array[0], array[1], array[2]);
400}
401
402static inline int4 get_int4(const BL::Array<int, 4> &array)
403{
404 return make_int4(array[0], array[1], array[2], array[3]);
405}
406
407static inline float3 get_float3(PointerRNA &ptr, const char *name)
408{
409 float3 f;
410 RNA_float_get_array(&ptr, name, &f.x);
411 return f;
412}
413
414static inline void set_float3(PointerRNA &ptr, const char *name, float3 value)
415{
416 RNA_float_set_array(&ptr, name, &value.x);
417}
418
419static inline float4 get_float4(PointerRNA &ptr, const char *name)
420{
421 float4 f;
422 RNA_float_get_array(&ptr, name, &f.x);
423 return f;
424}
425
426static inline void set_float4(PointerRNA &ptr, const char *name, float4 value)
427{
428 RNA_float_set_array(&ptr, name, &value.x);
429}
430
431static inline bool get_boolean(PointerRNA &ptr, const char *name)
432{
433 return RNA_boolean_get(&ptr, name) ? true : false;
434}
435
436static inline void set_boolean(PointerRNA &ptr, const char *name, bool value)
437{
438 RNA_boolean_set(&ptr, name, (int)value);
439}
440
441static inline float get_float(PointerRNA &ptr, const char *name)
442{
443 return RNA_float_get(&ptr, name);
444}
445
446static inline void set_float(PointerRNA &ptr, const char *name, float value)
447{
448 RNA_float_set(&ptr, name, value);
449}
450
451static inline int get_int(PointerRNA &ptr, const char *name)
452{
453 return RNA_int_get(&ptr, name);
454}
455
456static inline void set_int(PointerRNA &ptr, const char *name, int value)
457{
458 RNA_int_set(&ptr, name, value);
459}
460
461/* Get a RNA enum value with sanity check: if the RNA value is above num_values
462 * the function will return a fallback default value.
463 *
464 * NOTE: This function assumes that RNA enum values are a continuous sequence
465 * from 0 to num_values-1. Be careful to use it with enums where some values are
466 * deprecated!
467 */
468static inline int get_enum(PointerRNA &ptr,
469 const char *name,
470 int num_values = -1,
471 int default_value = -1)
472{
473 int value = RNA_enum_get(&ptr, name);
474 if (num_values != -1 && value >= num_values) {
475 assert(default_value != -1);
476 value = default_value;
477 }
478 return value;
479}
480
481static inline string get_enum_identifier(PointerRNA &ptr, const char *name)
482{
484 const char *identifier = "";
485 int value = RNA_property_enum_get(&ptr, prop);
486
487 RNA_property_enum_identifier(NULL, &ptr, prop, value, &identifier);
488
489 return string(identifier);
490}
491
492static inline void set_enum(PointerRNA &ptr, const char *name, int value)
493{
494 RNA_enum_set(&ptr, name, value);
495}
496
497static inline void set_enum(PointerRNA &ptr, const char *name, const string &identifier)
498{
499 RNA_enum_set_identifier(NULL, &ptr, name, identifier.c_str());
500}
501
502static inline string get_string(PointerRNA &ptr, const char *name)
503{
504 char cstrbuf[1024];
505 char *cstr = RNA_string_get_alloc(&ptr, name, cstrbuf, sizeof(cstrbuf), NULL);
506 string str(cstr);
507 if (cstr != cstrbuf) {
508 MEM_freeN(cstr);
509 }
510
511 return str;
512}
513
514static inline void set_string(PointerRNA &ptr, const char *name, const string &value)
515{
516 RNA_string_set(&ptr, name, value.c_str());
517}
518
519/* Relative Paths */
520
521static inline string blender_absolute_path(BL::BlendData &b_data, BL::ID &b_id, const string &path)
522{
523 if (path.size() >= 2 && path[0] == '/' && path[1] == '/') {
524 string dirname;
525
526 if (b_id.library()) {
527 BL::ID b_library_id(b_id.library());
528 dirname = blender_absolute_path(b_data, b_library_id, b_id.library().filepath());
529 }
530 else {
531 dirname = b_data.filepath();
532 }
533
534 return path_join(path_dirname(dirname), path.substr(2));
535 }
536
537 return path;
538}
539
540static inline string get_text_datablock_content(const PointerRNA &ptr)
541{
542 if (ptr.data == NULL) {
543 return "";
544 }
545
546 string content;
547 BL::Text::lines_iterator iter;
548 for (iter.begin(ptr); iter; ++iter) {
549 content += iter->body() + "\n";
550 }
551
552 return content;
553}
554
555/* Texture Space */
556
557static inline void mesh_texture_space(const ::Mesh &b_mesh, float3 &loc, float3 &size)
558{
559 float texspace_location[3], texspace_size[3];
560 BKE_mesh_texspace_get(const_cast<::Mesh *>(&b_mesh), texspace_location, texspace_size);
561
562 loc = make_float3(texspace_location[0], texspace_location[1], texspace_location[2]);
563 size = make_float3(texspace_size[0], texspace_size[1], texspace_size[2]);
564
565 if (size.x != 0.0f) {
566 size.x = 0.5f / size.x;
567 }
568 if (size.y != 0.0f) {
569 size.y = 0.5f / size.y;
570 }
571 if (size.z != 0.0f) {
572 size.z = 0.5f / size.z;
573 }
574
575 loc = loc * size - make_float3(0.5f, 0.5f, 0.5f);
576}
577
578/* Object motion steps, returns 0 if no motion blur needed. */
579static inline uint object_motion_steps(BL::Object &b_parent,
580 BL::Object &b_ob,
581 const int max_steps = INT_MAX)
582{
583 /* Get motion enabled and steps from object itself. */
584 PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles");
585 bool use_motion = get_boolean(cobject, "use_motion_blur");
586 if (!use_motion) {
587 return 0;
588 }
589
590 int steps = max(1, get_int(cobject, "motion_steps"));
591
592 /* Also check parent object, so motion blur and steps can be
593 * controlled by dupli-group duplicator for linked groups. */
594 if (b_parent.ptr.data != b_ob.ptr.data) {
595 PointerRNA parent_cobject = RNA_pointer_get(&b_parent.ptr, "cycles");
596 use_motion &= get_boolean(parent_cobject, "use_motion_blur");
597
598 if (!use_motion) {
599 return 0;
600 }
601
602 steps = max(steps, get_int(parent_cobject, "motion_steps"));
603 }
604
605 /* Use uneven number of steps so we get one keyframe at the current frame,
606 * and use 2^(steps - 1) so objects with more/fewer steps still have samples
607 * at the same times, to avoid sampling at many different times. */
608 return min((2 << (steps - 1)) + 1, max_steps);
609}
610
611/* object uses deformation motion blur */
612static inline bool object_use_deform_motion(BL::Object &b_parent, BL::Object &b_ob)
613{
614 PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles");
615 bool use_deform_motion = get_boolean(cobject, "use_deform_motion");
616 /* If motion blur is enabled for the object we also check
617 * whether it's enabled for the parent object as well.
618 *
619 * This way we can control motion blur from the dupli-group
620 * duplicator much easier. */
621 if (use_deform_motion && b_parent.ptr.data != b_ob.ptr.data) {
622 PointerRNA parent_cobject = RNA_pointer_get(&b_parent.ptr, "cycles");
623 use_deform_motion &= get_boolean(parent_cobject, "use_deform_motion");
624 }
625 return use_deform_motion;
626}
627
628static inline BL::FluidDomainSettings object_fluid_gas_domain_find(BL::Object &b_ob)
629{
630 for (BL::Modifier &b_mod : b_ob.modifiers) {
631 if (b_mod.is_a(&RNA_FluidModifier)) {
632 BL::FluidModifier b_mmd(b_mod);
633
634 if (b_mmd.fluid_type() == BL::FluidModifier::fluid_type_DOMAIN &&
635 b_mmd.domain_settings().domain_type() == BL::FluidDomainSettings::domain_type_GAS)
636 {
637 return b_mmd.domain_settings();
638 }
639 }
640 }
641
642 return BL::FluidDomainSettings(PointerRNA_NULL);
643}
644
645static inline BL::MeshSequenceCacheModifier object_mesh_cache_find(BL::Object &b_ob,
646 bool *has_subdivision_modifier)
647{
648 for (int i = b_ob.modifiers.length() - 1; i >= 0; --i) {
649 BL::Modifier b_mod = b_ob.modifiers[i];
650
651 if (b_mod.type() == BL::Modifier::type_MESH_SEQUENCE_CACHE) {
652 BL::MeshSequenceCacheModifier mesh_cache = BL::MeshSequenceCacheModifier(b_mod);
653 return mesh_cache;
654 }
655
656 /* Skip possible particles system modifiers as they do not modify the geometry. */
657 if (b_mod.type() == BL::Modifier::type_PARTICLE_SYSTEM) {
658 continue;
659 }
660
661 if (b_mod.type() == BL::Modifier::type_SUBSURF) {
662 if (has_subdivision_modifier) {
663 *has_subdivision_modifier = true;
664 }
665 continue;
666 }
667
668 break;
669 }
670
671 return BL::MeshSequenceCacheModifier(PointerRNA_NULL);
672}
673
674static inline Mesh::SubdivisionType object_subdivision_type(BL::Object &b_ob,
675 bool preview,
676 bool experimental)
677{
678 PointerRNA cobj = RNA_pointer_get(&b_ob.ptr, "cycles");
679
680 if (cobj.data && !b_ob.modifiers.empty() && experimental) {
681 BL::Modifier mod = b_ob.modifiers[b_ob.modifiers.length() - 1];
682 bool enabled = preview ? mod.show_viewport() : mod.show_render();
683
684 if (enabled && mod.type() == BL::Modifier::type_SUBSURF &&
685 RNA_boolean_get(&cobj, "use_adaptive_subdivision"))
686 {
687 BL::SubsurfModifier subsurf(mod);
688
689 if (subsurf.subdivision_type() == BL::SubsurfModifier::subdivision_type_CATMULL_CLARK) {
691 }
692 else {
694 }
695 }
696 }
697
699}
700
701static inline uint object_ray_visibility(BL::Object &b_ob)
702{
703 uint flag = 0;
704
705 flag |= b_ob.visible_camera() ? PATH_RAY_CAMERA : 0;
706 flag |= b_ob.visible_diffuse() ? PATH_RAY_DIFFUSE : 0;
707 flag |= b_ob.visible_glossy() ? PATH_RAY_GLOSSY : 0;
708 flag |= b_ob.visible_transmission() ? PATH_RAY_TRANSMIT : 0;
709 flag |= b_ob.visible_shadow() ? PATH_RAY_SHADOW : 0;
710 flag |= b_ob.visible_volume_scatter() ? PATH_RAY_VOLUME_SCATTER : 0;
711
712 return flag;
713}
714
715/* Check whether some of "built-in" motion-related attributes are needed to be exported (includes
716 * things like velocity from cache modifier, fluid simulation).
717 *
718 * NOTE: This code is run prior to object motion blur initialization. so can not access properties
719 * set by `sync_object_motion_init()`. */
720static inline bool object_need_motion_attribute(BObjectInfo &b_ob_info, Scene *scene)
721{
722 const Scene::MotionType need_motion = scene->need_motion();
723 if (need_motion == Scene::MOTION_NONE) {
724 /* Simple case: neither motion pass nor motion blur is needed, no need in the motion related
725 * attributes. */
726 return false;
727 }
728
729 if (need_motion == Scene::MOTION_BLUR) {
730 /* A bit tricky and implicit case:
731 * - Motion blur is enabled in the scene, which implies specific number of time steps for
732 * objects.
733 * - If the object has motion blur disabled on it, it will have 0 time steps.
734 * - Motion attribute expects non-zero time steps.
735 *
736 * Avoid adding motion attributes if the motion blur will enforce 0 motion steps. */
737 PointerRNA cobject = RNA_pointer_get(&b_ob_info.real_object.ptr, "cycles");
738 const bool use_motion = get_boolean(cobject, "use_motion_blur");
739 if (!use_motion) {
740 return false;
741 }
742 }
743
744 /* Motion pass which implies 3 motion steps, or motion blur which is not disabled on object
745 * level. */
746 return true;
747}
748
749class EdgeMap {
750 public:
752
753 void clear()
754 {
755 edges_.clear();
756 }
757
758 void insert(int v0, int v1)
759 {
760 get_sorted_verts(v0, v1);
761 edges_.insert(std::pair<int, int>(v0, v1));
762 }
763
764 bool exists(int v0, int v1)
765 {
766 get_sorted_verts(v0, v1);
767 return edges_.find(std::pair<int, int>(v0, v1)) != edges_.end();
768 }
769
770 protected:
771 void get_sorted_verts(int &v0, int &v1)
772 {
773 if (v0 > v1) {
774 swap(v0, v1);
775 }
776 }
777
778 set<std::pair<int, int>> edges_;
779};
780
782
783#endif /* __BLENDER_UTIL_H__ */
void BKE_image_user_frame_calc(Image *ima, ImageUser *iuser, int cfra)
void BKE_image_user_file_path_ex(const Main *bmain, const ImageUser *iuser, const Image *ima, char *filepath, const bool resolve_udim, const bool resolve_multiview)
unsigned char * BKE_image_get_pixels_for_frame(Image *image, int frame, int tile)
float * BKE_image_get_float_pixels_for_frame(Image *image, int frame, int tile)
void BKE_mesh_texspace_get(Mesh *mesh, float r_texspace_location[3], float r_texspace_size[3])
unsigned int uint
const char * dirname(char *path)
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert Invert a color
constexpr PointerRNA PointerRNA_NULL
Definition RNA_types.hh:45
PyObject * self
BPy_StructRNA * depsgraph
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
set< std::pair< int, int > > edges_
void insert(int v0, int v1)
bool exists(int v0, int v1)
void get_sorted_verts(int &v0, int &v1)
T * resize(size_t newsize)
input_tx image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "preview_img") .compute_source("compositor_compute_preview.glsl") .do_static_compilation(true)
static string image_user_file_path(BL::BlendData &data, BL::ImageUser &iuser, BL::Image &ima, int cfra)
static float * image_get_float_pixels_for_frame(BL::Image &image, int frame, int tile)
static uint object_ray_visibility(BL::Object &b_ob)
static float4 get_float4(const BL::Array< float, 4 > &array)
static bool image_is_builtin(BL::Image &ima, BL::RenderEngine &engine)
static uint object_motion_steps(BL::Object &b_parent, BL::Object &b_ob, const int max_steps=INT_MAX)
static int render_resolution_x(BL::RenderSettings &b_render)
static bool mesh_use_corner_normals(BL::Mesh &mesh, Mesh::SubdivisionType subdivision_type)
static float get_float(PointerRNA &ptr, const char *name)
static void curvemapping_float_to_array(BL::CurveMapping &cumap, array< float > &data, int size)
void python_thread_state_restore(void **python_thread_state)
Definition python.cpp:96
static void mesh_texture_space(const ::Mesh &b_mesh, float3 &loc, float3 &size)
static void set_boolean(PointerRNA &ptr, const char *name, bool value)
static bool get_boolean(PointerRNA &ptr, const char *name)
static void set_float3(PointerRNA &ptr, const char *name, float3 value)
static bool BKE_object_is_modified(BL::Object &self, BL::Scene &scene, bool preview)
static int get_int(PointerRNA &ptr, const char *name)
static void free_object_to_mesh(BL::BlendData &, BObjectInfo &b_ob_info, BL::Mesh &mesh)
static string get_enum_identifier(PointerRNA &ptr, const char *name)
static BL::Mesh object_to_mesh(BL::BlendData &, BObjectInfo &b_ob_info, BL::Depsgraph &, bool, Mesh::SubdivisionType subdivision_type)
static string get_text_datablock_content(const PointerRNA &ptr)
static void colorramp_to_array(BL::ColorRamp &ramp, array< float3 > &ramp_color, array< float > &ramp_alpha, int size)
static void curvemapping_to_array(BL::CurveMapping &cumap, array< float > &data, int size)
static float3 get_float3(const BL::Array< float, 2 > &array)
static int render_resolution_y(BL::RenderSettings &b_render)
static bool object_need_motion_attribute(BObjectInfo &b_ob_info, Scene *scene)
static int get_enum(PointerRNA &ptr, const char *name, int num_values=-1, int default_value=-1)
static void set_enum(PointerRNA &ptr, const char *name, int value)
static void render_add_metadata(BL::RenderResult &b_rr, string name, string value)
BlenderAttributeType blender_attribute_name_split_type(ustring name, string *r_real_name)
static void set_float4(PointerRNA &ptr, const char *name, float4 value)
static bool BKE_object_is_deform_modified(BObjectInfo &self, BL::Scene &scene, bool preview)
static int4 get_int4(const BL::Array< int, 4 > &array)
static void curvemapping_color_to_array(BL::CurveMapping &cumap, array< float3 > &data, int size, bool rgb_curve)
static string blender_absolute_path(BL::BlendData &b_data, BL::ID &b_id, const string &path)
static int3 get_int3(const BL::Array< int, 3 > &array)
static unsigned char * image_get_pixels_for_frame(BL::Image &image, int frame, int tile)
static float2 get_float2(const BL::Array< float, 2 > &array)
static Mesh::SubdivisionType object_subdivision_type(BL::Object &b_ob, bool preview, bool experimental)
static void set_int(PointerRNA &ptr, const char *name, int value)
static BL::FluidDomainSettings object_fluid_gas_domain_find(BL::Object &b_ob)
void python_thread_state_save(void **python_thread_state)
Definition python.cpp:91
static void curvemap_minmax_curve(BL::CurveMap &curve, float *min_x, float *max_x)
static string get_string(PointerRNA &ptr, const char *name)
static void set_float(PointerRNA &ptr, const char *name, float value)
static Transform get_transform(const BL::Array< float, 16 > &array)
static void curvemapping_minmax(BL::CurveMapping &cumap, int num_curves, float *min_x, float *max_x)
static BL::MeshSequenceCacheModifier object_mesh_cache_find(BL::Object &b_ob, bool *has_subdivision_modifier)
static bool object_use_deform_motion(BL::Object &b_parent, BL::Object &b_ob)
static void set_string(PointerRNA &ptr, const char *name, const string &value)
BL::ShaderNodeAttribute::attribute_type_enum BlenderAttributeType
static int image_user_frame_number(BL::ImageUser &iuser, BL::Image &ima, int cfra)
ccl_device_inline Transform projection_to_transform(const ProjectionTransform &a)
ccl_device_inline ProjectionTransform projection_transpose(const ProjectionTransform &a)
#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)
#define NULL
ccl_device_forceinline float2 make_float2(const float x, const float y)
ccl_device_forceinline int3 make_int3(const int x, const int y, const int z)
ccl_device_forceinline int4 make_int4(const int x, const int y, const int z, const int w)
draw_view in_light_buf[] float
#define str(s)
bool enabled
ccl_global const KernelWorkTile * tile
@ PATH_RAY_SHADOW
@ PATH_RAY_TRANSMIT
@ PATH_RAY_VOLUME_SCATTER
@ PATH_RAY_GLOSSY
@ PATH_RAY_DIFFUSE
@ PATH_RAY_CAMERA
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
string path_dirname(const string &path)
Definition path.cpp:403
string path_join(const string &dir, const string &file)
Definition path.cpp:417
bool RNA_property_enum_identifier(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **r_identifier)
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
PointerRNA RNA_pointer_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
void RNA_int_set(PointerRNA *ptr, const char *name, int value)
void RNA_float_get_array(PointerRNA *ptr, const char *name, float *values)
void RNA_enum_set_identifier(bContext *C, PointerRNA *ptr, const char *name, const char *id)
int RNA_int_get(PointerRNA *ptr, const char *name)
char * RNA_string_get_alloc(PointerRNA *ptr, const char *name, char *fixedbuf, int fixedlen, int *r_len)
float RNA_float_get(PointerRNA *ptr, const char *name)
void RNA_float_set(PointerRNA *ptr, const char *name, float value)
int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
void RNA_float_set_array(PointerRNA *ptr, const char *name, const float *values)
int RNA_enum_get(PointerRNA *ptr, const char *name)
static const int steps
#define swap(a, b)
Definition sort.c:55
#define min(a, b)
Definition sort.c:32
#define FLT_MAX
Definition stdcycles.h:14
BL::Object real_object
BL::Object iter_object
bool is_real_object_data() const
SubdivisionType
Definition scene/mesh.h:120
@ SUBDIVISION_NONE
Definition scene/mesh.h:121
@ SUBDIVISION_LINEAR
Definition scene/mesh.h:122
@ SUBDIVISION_CATMULL_CLARK
Definition scene/mesh.h:123
void * data
Definition RNA_types.hh:42
MotionType need_motion() const
Definition scene.cpp:362
MotionType
Definition scene.h:177
@ MOTION_NONE
Definition scene.h:177
@ MOTION_BLUR
Definition scene.h:177
float x
Definition sky_float3.h:27
VecBase< float, 4 > float4
float max
ccl_device_inline int mod(int x, int m)
Definition util/math.h:520
PointerRNA * ptr
Definition wm_files.cc:4126
uint8_t flag
Definition wm_window.cc:138