Blender V5.0
blender/object.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
7#include "blender/sync.h"
8#include "blender/util.h"
9
10#include "scene/camera.h"
11#include "scene/integrator.h"
12#include "scene/light.h"
13#include "scene/mesh.h"
14#include "scene/object.h"
15#include "scene/particles.h"
16#include "scene/scene.h"
17#include "scene/shader.h"
18#include "scene/shader_graph.h"
19#include "scene/shader_nodes.h"
20
21#include "util/hash.h"
22#include "util/log.h"
23#include "util/task.h"
24
25#include "BKE_duplilist.hh"
26
28
29/* Utilities */
30
31bool BlenderSync::BKE_object_is_modified(BL::Object &b_ob)
32{
33 /* test if we can instance or if the object is modified */
34 if (b_ob.type() == BL::Object::type_META) {
35 /* Multi-user and dupli meta-balls are fused, can't instance. */
36 return true;
37 }
38 if (ccl::BKE_object_is_modified(b_ob, b_scene, preview)) {
39 /* modifiers */
40 return true;
41 }
42
43 /* object level material links */
44 for (BL::MaterialSlot &b_slot : b_ob.material_slots) {
45 if (b_slot.link() == BL::MaterialSlot::link_OBJECT) {
46 return true;
47 }
48 }
49
50 return false;
51}
52
53bool BlenderSync::object_is_geometry(BObjectInfo &b_ob_info)
54{
55 BL::ID b_ob_data = b_ob_info.object_data;
56
57 if (!b_ob_data) {
58 return false;
59 }
60
61 const BL::Object::type_enum type = b_ob_info.iter_object.type();
62
63 if (type == BL::Object::type_VOLUME || type == BL::Object::type_CURVES ||
64 type == BL::Object::type_POINTCLOUD || type == BL::Object::type_LIGHT)
65 {
66 /* Will be exported as geometry. */
67 return true;
68 }
69
70 return b_ob_data.is_a(&RNA_Mesh);
71}
72
73bool BlenderSync::object_can_have_geometry(BL::Object &b_ob)
74{
75 const BL::Object::type_enum type = b_ob.type();
76 switch (type) {
77 case BL::Object::type_MESH:
78 case BL::Object::type_CURVE:
79 case BL::Object::type_SURFACE:
80 case BL::Object::type_META:
81 case BL::Object::type_FONT:
82 case BL::Object::type_CURVES:
83 case BL::Object::type_POINTCLOUD:
84 case BL::Object::type_VOLUME:
85 return true;
86 default:
87 return false;
88 }
89}
90
91bool BlenderSync::object_is_light(BL::Object &b_ob)
92{
93 BL::ID b_ob_data = object_get_data(b_ob, true);
94
95 return (b_ob_data && b_ob_data.is_a(&RNA_Light));
96}
97
98bool BlenderSync::object_is_camera(BL::Object &b_ob)
99{
100 BL::ID b_ob_data = object_get_data(b_ob, true);
101
102 return (b_ob_data && b_ob_data.is_a(&RNA_Camera));
103}
104
105void BlenderSync::sync_object_motion_init(BL::Object &b_parent, BL::Object &b_ob, Object *object)
106{
107 /* Initialize motion blur for object, detecting if it's enabled and creating motion
108 * steps array if so. */
109 array<Transform> motion;
110 object->set_motion(motion);
111
112 Geometry *geom = object->get_geometry();
113 if (!geom) {
114 return;
115 }
116
117 int motion_steps = 0;
118 bool use_motion_blur = false;
119
120 const Scene::MotionType need_motion = scene->need_motion();
121 if (need_motion == Scene::MOTION_BLUR) {
122 motion_steps = object_motion_steps(b_parent, b_ob, Object::MAX_MOTION_STEPS);
123 if (motion_steps && object_use_deform_motion(b_parent, b_ob)) {
124 use_motion_blur = true;
125 }
126 }
127 else if (need_motion != Scene::MOTION_NONE) {
128 motion_steps = 3;
129 }
130
131 geom->set_use_motion_blur(use_motion_blur);
132
133 motion.resize(motion_steps, transform_empty());
134
135 if (motion_steps) {
136 motion[motion_steps / 2] = object->get_tfm();
137
138 /* update motion socket before trying to access object->motion_time */
139 object->set_motion(motion);
140
141 for (size_t step = 0; step < motion_steps; step++) {
142 motion_times.insert(object->motion_time(step));
143 }
144 }
145}
146
147Object *BlenderSync::sync_object(BL::ViewLayer &b_view_layer,
148 BL::DepsgraphObjectInstance &b_instance,
149 const float motion_time,
150 bool use_particle_hair,
151 bool show_lights,
152 BlenderObjectCulling &culling,
153 TaskPool *geom_task_pool)
154{
155 const bool is_instance = b_instance.is_instance();
156 BL::Object b_ob = b_instance.object();
157 BL::Object b_parent = is_instance ? b_instance.parent() : b_instance.object();
158 BL::Object b_real_object = is_instance ? b_instance.instance_object() : b_ob;
159 const bool use_adaptive_subdiv = object_subdivision_type(
160 b_real_object, preview, use_adaptive_subdivision) !=
162 BObjectInfo b_ob_info{
163 b_ob, b_real_object, object_get_data(b_ob, use_adaptive_subdiv), use_adaptive_subdiv};
164 const bool motion = motion_time != 0.0f;
165 /*const*/ Transform tfm = get_transform(b_ob.matrix_world());
166 int *persistent_id = nullptr;
167 BL::Array<int, OBJECT_PERSISTENT_ID_SIZE> persistent_id_array;
168 if (is_instance) {
169 persistent_id_array = b_instance.persistent_id();
170 persistent_id = persistent_id_array.data;
171 if (!motion && !b_ob_info.is_real_object_data()) {
172 /* Remember which object data the geometry is coming from, so that we can sync it when the
173 * object has changed. */
174 instance_geometries_by_object[b_ob_info.real_object.ptr.data].insert(b_ob_info.object_data);
175 }
176 }
177
178 /* only interested in object that we can create geometry from */
179 if (!object_is_geometry(b_ob_info)) {
180 return nullptr;
181 }
182
183 /* Perform object culling. */
184 if (object_is_light(b_ob)) {
185 if (!show_lights) {
186 return nullptr;
187 }
188 }
189 else if (culling.test(scene, b_ob, tfm)) {
190 return nullptr;
191 }
192
193 /* Visibility flags for both parent and child. */
194 PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles");
195 const bool use_holdout = b_parent.holdout_get(PointerRNA_NULL, b_view_layer);
197
198 if (b_parent.ptr.data != b_ob.ptr.data) {
199 visibility &= object_ray_visibility(b_parent);
200 }
201
202 /* TODO: make holdout objects on excluded layer invisible for non-camera rays. */
203#if 0
204 if (use_holdout && (layer_flag & view_layer.exclude_layer)) {
205 visibility &= ~(PATH_RAY_ALL_VISIBILITY - PATH_RAY_CAMERA);
206 }
207#endif
208
209 /* Clear camera visibility for indirect only objects. */
210 const bool use_indirect_only = !use_holdout &&
211 b_parent.indirect_only_get(PointerRNA_NULL, b_view_layer);
212 if (use_indirect_only) {
213 visibility &= ~PATH_RAY_CAMERA;
214 }
215
216 /* Don't export completely invisible objects. */
217 if (visibility == 0) {
218 return nullptr;
219 }
220
221 /* Use task pool only for non-instances, since sync_dupli_particle accesses
222 * geometry. This restriction should be removed for better performance. */
223 TaskPool *object_geom_task_pool = (is_instance) ? nullptr : geom_task_pool;
224
225 /* key to lookup object */
226 const ObjectKey key(b_parent, persistent_id, b_ob_info.real_object, use_particle_hair);
227 Object *object;
228
229 /* motion vector case */
230 if (motion) {
231 object = object_map.find(key);
232
233 if (object && object->use_motion()) {
234 /* Set transform at matching motion time step. */
235 const int time_index = object->motion_step(motion_time);
236 if (time_index >= 0) {
237 array<Transform> motion = object->get_motion();
238 motion[time_index] = tfm;
239 object->set_motion(motion);
240 }
241
242 /* mesh deformation */
243 if (object->get_geometry()) {
244 sync_geometry_motion(
245 b_ob_info, object, motion_time, use_particle_hair, object_geom_task_pool);
246 }
247 }
248
249 return object;
250 }
251
252 /* test if we need to sync */
253 bool object_updated = object_map.add_or_update(&object, b_ob, b_parent, key) ||
254 (tfm != object->get_tfm());
255
256 /* mesh sync */
257 Geometry *geometry = sync_geometry(
258 b_ob_info, object_updated, use_particle_hair, object_geom_task_pool);
259 object->set_geometry(geometry);
260
261 /* special case not tracked by object update flags */
262
263 if (sync_object_attributes(b_instance, object)) {
264 object_updated = true;
265 }
266
267 /* holdout */
268 object->set_use_holdout(use_holdout);
269
270 object->set_visibility(visibility);
271
272 object->set_is_shadow_catcher(b_ob.is_shadow_catcher() || b_parent.is_shadow_catcher());
273
274 object->set_shadow_terminator_shading_offset(b_ob.shadow_terminator_shading_offset());
275
276 object->set_shadow_terminator_geometry_offset(b_ob.shadow_terminator_geometry_offset());
277
278 float ao_distance = get_float(cobject, "ao_distance");
279 if (ao_distance == 0.0f && b_parent.ptr.data != b_ob.ptr.data) {
280 PointerRNA cparent = RNA_pointer_get(&b_parent.ptr, "cycles");
281 ao_distance = get_float(cparent, "ao_distance");
282 }
283 object->set_ao_distance(ao_distance);
284
285 const bool is_caustics_caster = get_boolean(cobject, "is_caustics_caster");
286 object->set_is_caustics_caster(is_caustics_caster);
287
288 const bool is_caustics_receiver = get_boolean(cobject, "is_caustics_receiver");
289 object->set_is_caustics_receiver(is_caustics_receiver);
290
291 object->set_is_bake_target(b_ob_info.real_object == b_bake_target);
292
293 /* sync the asset name for Cryptomatte */
294 BL::Object parent = b_ob.parent();
295 ustring parent_name;
296 if (parent) {
297 while (parent.parent()) {
298 parent = parent.parent();
299 }
300 parent_name = parent.name();
301 }
302 else {
303 parent_name = b_ob.name();
304 }
305 object->set_asset_name(parent_name);
306
307 /* object sync
308 * transform comparison should not be needed, but duplis don't work perfect
309 * in the depsgraph and may not signal changes, so this is a workaround */
310 const bool do_sync = object->is_modified() || object_updated ||
311 (object->get_geometry() && object->get_geometry()->is_modified());
312 if (do_sync) {
313 object->name = b_ob.name().c_str();
314 object->set_pass_id(b_ob.pass_index());
315 const BL::Array<float, 4> object_color = b_ob.color();
316 object->set_color(get_float3(object_color));
317 object->set_alpha(object_color[3]);
318 object->set_tfm(tfm);
319
320 /* dupli texture coordinates and random_id */
321 if (is_instance) {
322 object->set_dupli_generated(0.5f * get_float3(b_instance.orco()) -
323 make_float3(0.5f, 0.5f, 0.5f));
324 object->set_dupli_uv(get_float2(b_instance.uv()));
325 object->set_random_id(b_instance.random_id());
326 }
327 else {
328 object->set_dupli_generated(zero_float3());
329 object->set_dupli_uv(zero_float2());
330 object->set_random_id(hash_uint2(hash_string(object->name.c_str()), 0));
331 }
332
333 /* Light group and linking. */
334 string lightgroup = b_ob.lightgroup();
335 if (lightgroup.empty()) {
336 lightgroup = b_parent.lightgroup();
337 }
338 object->set_lightgroup(ustring(lightgroup));
339
340 object->set_light_set_membership(BlenderLightLink::get_light_set_membership(b_parent, b_ob));
341 object->set_receiver_light_set(BlenderLightLink::get_receiver_light_set(b_parent, b_ob));
342 object->set_shadow_set_membership(BlenderLightLink::get_shadow_set_membership(b_parent, b_ob));
343 object->set_blocker_shadow_set(BlenderLightLink::get_blocker_shadow_set(b_parent, b_ob));
344 }
345
346 sync_object_motion_init(b_parent, b_ob, object);
347
348 if (do_sync || object->motion_is_modified()) {
349 object->tag_update(scene);
350 }
351
352 if (is_instance) {
353 /* Sync possible particle data. */
354 sync_dupli_particle(b_parent, b_instance, object);
355 }
356
357 return object;
358}
359
361
362static float4 lookup_instance_property(BL::DepsgraphObjectInstance &b_instance,
363 const string &name,
364 bool use_instancer)
365{
366 ::Object *ob = (::Object *)b_instance.object().ptr.data;
367 ::DupliObject *dupli = nullptr;
368 ::Object *dupli_parent = nullptr;
369
370 /* If requesting instance data, check the parent particle system and object. */
371 if (use_instancer && b_instance.is_instance()) {
373 dupli_parent = (::Object *)b_instance.parent().ptr.data;
374 }
375
376 float4 value;
377 BKE_object_dupli_find_rgba_attribute(ob, dupli, dupli_parent, name.c_str(), &value.x);
378
379 return value;
380}
381
382bool BlenderSync::sync_object_attributes(BL::DepsgraphObjectInstance &b_instance, Object *object)
383{
384 /* Find which attributes are needed. */
385 AttributeRequestSet requests = object->get_geometry()->needed_attributes();
386
387 /* Delete attributes that became unnecessary. */
388 vector<ParamValue> &attributes = object->attributes;
389 bool changed = false;
390
391 for (int i = attributes.size() - 1; i >= 0; i--) {
392 if (!requests.find(attributes[i].name())) {
393 attributes.erase(attributes.begin() + i);
394 changed = true;
395 }
396 }
397
398 /* Update attribute values. */
399 for (const AttributeRequest &req : requests.requests) {
400 const ustring name = req.name;
401
402 std::string real_name;
404
405 if (type == BL::ShaderNodeAttribute::attribute_type_OBJECT ||
406 type == BL::ShaderNodeAttribute::attribute_type_INSTANCER)
407 {
408 const bool use_instancer = (type == BL::ShaderNodeAttribute::attribute_type_INSTANCER);
409 float4 value = lookup_instance_property(b_instance, real_name, use_instancer);
410
411 /* Try finding the existing attribute value. */
412 ParamValue *param = nullptr;
413
414 for (size_t i = 0; i < attributes.size(); i++) {
415 if (attributes[i].name() == name) {
416 param = &attributes[i];
417 break;
418 }
419 }
420
421 /* Replace or add the value. */
422 const ParamValue new_param(name, TypeFloat4, 1, &value);
423 assert(new_param.datasize() == sizeof(value));
424
425 if (!param) {
426 changed = true;
427 attributes.push_back(new_param);
428 }
429 else if (!(param->get<float4>() == value)) {
430 changed = true;
431 *param = new_param;
432 }
433 }
434 }
435
436 return changed;
437}
438
439/* Object Loop */
440
441void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph,
442 BL::SpaceView3D &b_v3d,
443 const float motion_time)
444{
445 /* Task pool for multithreaded geometry sync. */
446 TaskPool geom_task_pool;
447
448 /* layer data */
449 const bool motion = motion_time != 0.0f;
450
451 if (!motion) {
452 /* prepare for sync */
453 geometry_map.pre_sync();
454 object_map.pre_sync();
455 procedural_map.pre_sync();
456 particle_system_map.pre_sync();
457 motion_times.clear();
458 }
459 else {
460 geometry_motion_synced.clear();
461 }
462
463 if (!motion) {
464 /* Object to geometry instance mapping is built for the reference time, as other
465 * times just look up the corresponding geometry. */
466 instance_geometries_by_object.clear();
467 }
468
469 /* initialize culling */
470 BlenderObjectCulling culling(scene, b_scene);
471
472 /* object loop */
473 bool cancel = false;
474 const bool show_lights = BlenderViewportParameters(b_v3d, use_developer_ui).use_scene_lights;
475
476 BL::ViewLayer b_view_layer = b_depsgraph.view_layer_eval();
477 BL::Depsgraph::object_instances_iterator b_instance_iter;
478
479 for (b_depsgraph.object_instances.begin(b_instance_iter);
480 b_instance_iter != b_depsgraph.object_instances.end() && !cancel;
481 ++b_instance_iter)
482 {
483 BL::DepsgraphObjectInstance b_instance = *b_instance_iter;
484 BL::Object b_ob = b_instance.object();
485
486 /* Viewport visibility. */
487 const bool show_in_viewport = !b_v3d || b_ob.visible_in_viewport_get(b_v3d);
488 if (show_in_viewport == false) {
489 continue;
490 }
491
492 /* Load per-object culling data. */
493 culling.init_object(scene, b_ob);
494
495 /* Ensure the object geom supporting the hair is processed before adding
496 * the hair processing task to the task pool, calling .to_mesh() on the
497 * same object in parallel does not work. */
498 const bool sync_hair = b_instance.show_particles() && object_has_particle_hair(b_ob);
499
500 /* Object itself. */
501 if (b_instance.show_self()) {
502 sync_object(b_view_layer,
503 b_instance,
504 motion_time,
505 false,
506 show_lights,
507 culling,
508 sync_hair ? nullptr : &geom_task_pool);
509 }
510
511 /* Particle hair as separate object. */
512 if (sync_hair) {
513 sync_object(
514 b_view_layer, b_instance, motion_time, true, show_lights, culling, &geom_task_pool);
515 }
516
517 cancel = progress.get_cancel();
518 }
519
520 geom_task_pool.wait_work();
521
522 progress.set_sync_status("");
523
524 if (!cancel && !motion) {
525 /* After object for world_use_portal. */
526 sync_background_light(b_v3d);
527
528 /* Handle removed data and modified pointers, as this may free memory, delete Nodes in the
529 * right order to ensure that dependent data is freed after their users. Objects should be
530 * freed before particle systems and geometries. */
531 object_map.post_sync();
532 geometry_map.post_sync();
533 particle_system_map.post_sync();
534 procedural_map.post_sync();
535 }
536
537 if (motion) {
538 geometry_motion_synced.clear();
539 }
540}
541
542void BlenderSync::sync_motion(BL::RenderSettings &b_render,
543 BL::Depsgraph &b_depsgraph,
544 BL::SpaceView3D &b_v3d,
545 BL::RegionView3D &b_rv3d,
546 const int width,
547 const int height,
548 void **python_thread_state)
549{
550 if (scene->need_motion() == Scene::MOTION_NONE) {
551 return;
552 }
553
554 /* get camera object here to deal with camera switch */
555 BL::Object b_cam = get_camera_object(b_v3d, b_rv3d);
556
557 const int frame_center = b_scene.frame_current();
558 const float subframe_center = b_scene.frame_subframe();
559 float frame_center_delta = 0.0f;
560
561 if (scene->need_motion() != Scene::MOTION_PASS &&
562 scene->camera->get_motion_position() != MOTION_POSITION_CENTER)
563 {
564 const float shuttertime = scene->camera->get_shuttertime();
565 if (scene->camera->get_motion_position() == MOTION_POSITION_END) {
566 frame_center_delta = -shuttertime * 0.5f;
567 }
568 else {
569 assert(scene->camera->get_motion_position() == MOTION_POSITION_START);
570 frame_center_delta = shuttertime * 0.5f;
571 }
572
573 const float time = frame_center + subframe_center + frame_center_delta;
574 const int frame = (int)floorf(time);
575 const float subframe = time - frame;
576 python_thread_state_restore(python_thread_state);
577 b_engine.frame_set(frame, subframe);
578 python_thread_state_save(python_thread_state);
579 if (b_cam) {
580 sync_camera_motion(b_render, b_cam, width, height, 0.0f);
581 }
582 sync_objects(b_depsgraph, b_v3d);
583 }
584
585 /* Insert motion times from camera. Motion times from other objects
586 * have already been added in a sync_objects call. */
587 if (b_cam) {
588 const uint camera_motion_steps = object_motion_steps(b_cam, b_cam);
589 for (size_t step = 0; step < camera_motion_steps; step++) {
590 motion_times.insert(scene->camera->motion_time(step));
591 }
592 }
593
594 /* Check which geometry already has motion blur so it can be skipped. */
595 geometry_motion_attribute_synced.clear();
596 for (Geometry *geom : scene->geometry) {
598 geometry_motion_attribute_synced.insert(geom);
599 }
600 }
601
602 /* note iteration over motion_times set happens in sorted order */
603 for (const float relative_time : motion_times) {
604 /* center time is already handled. */
605 if (relative_time == 0.0f) {
606 continue;
607 }
608
609 LOG_DEBUG << "Synchronizing motion for the relative time " << relative_time << ".";
610
611 /* fixed shutter time to get previous and next frame for motion pass */
612 const float shuttertime = scene->motion_shutter_time();
613
614 /* compute frame and subframe time */
615 const float time = frame_center + subframe_center + frame_center_delta +
616 relative_time * shuttertime * 0.5f;
617 const int frame = (int)floorf(time);
618 const float subframe = time - frame;
619
620 /* change frame */
621 python_thread_state_restore(python_thread_state);
622 b_engine.frame_set(frame, subframe);
623 python_thread_state_save(python_thread_state);
624
625 /* Syncs camera motion if relative_time is one of the camera's motion times. */
626 sync_camera_motion(b_render, b_cam, width, height, relative_time);
627
628 /* sync object */
629 sync_objects(b_depsgraph, b_v3d, relative_time);
630 }
631
632 geometry_motion_attribute_synced.clear();
633
634 /* we need to set the python thread state again because this
635 * function assumes it is being executed from python and will
636 * try to save the thread state */
637 python_thread_state_restore(python_thread_state);
638 b_engine.frame_set(frame_center, subframe_center);
639 python_thread_state_save(python_thread_state);
640}
641
bool BKE_object_dupli_find_rgba_attribute(const Object *ob, const DupliObject *dupli, const Object *dupli_parent, const char *name, float r_value[4])
unsigned int uint
struct TaskPool TaskPool
Definition BLI_task.h:56
struct Object Object
DupliObject * rna_hack_DepsgraphObjectInstance_dupli_object_get(PointerRNA *ptr)
static float4 lookup_instance_property(BL::DepsgraphObjectInstance &b_instance, const string &name, bool use_instancer)
BlenderAttributeType blender_attribute_name_split_type(ustring name, string *r_real_name)
vector< AttributeRequest > requests
bool find(ustring name)
Attribute * find(ustring name) const
void init_object(Scene *scene, BL::Object &b_ob)
bool test(Scene *scene, BL::Object &b_ob, Transform &tfm)
AttributeSet attributes
T * resize(const size_t newsize)
BL::ShaderNodeAttribute::attribute_type_enum BlenderAttributeType
static uint object_ray_visibility(BL::Object &b_ob)
static uint object_motion_steps(BL::Object &b_parent, BL::Object &b_ob, const int max_steps=INT_MAX)
static float get_float(PointerRNA &ptr, const char *name)
static bool get_boolean(PointerRNA &ptr, const char *name)
static float3 get_float3(const BL::Array< float, 2 > &array)
static Mesh::SubdivisionType object_subdivision_type(BL::Object &b_ob, const bool preview, const bool use_adaptive_subdivision)
static float2 get_float2(const BL::Array< float, 2 > &array)
static CCL_NAMESPACE_BEGIN BL::ID object_get_data(const BL::Object &b_ob, const bool use_adaptive_subdivision)
static Transform get_transform(const BL::Array< float, 16 > &array)
static bool object_use_deform_motion(BL::Object &b_parent, BL::Object &b_ob)
#define CCL_NAMESPACE_END
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
#define assert(assertion)
VecBase< float, D > step(VecOp< float, D >, VecOp< float, D >) RET
VecBase< float, 4 > float4
static uint hash_string(const char *str)
Definition hash.h:637
ccl_device_inline uint hash_uint2(const uint kx, const uint ky)
Definition hash.h:139
ccl_device_inline float3 object_color(KernelGlobals kg, const int object)
@ ATTR_STD_MOTION_VERTEX_POSITION
@ PATH_RAY_ALL_VISIBILITY
@ PATH_RAY_CAMERA
@ MOTION_POSITION_END
@ MOTION_POSITION_START
@ MOTION_POSITION_CENTER
#define LOG_DEBUG
Definition log.h:107
CCL_NAMESPACE_BEGIN ccl_device_inline float2 zero_float2()
Definition math_float2.h:13
CCL_NAMESPACE_BEGIN ccl_device_inline float3 zero_float3()
Definition math_float3.h:17
void python_thread_state_restore(void **python_thread_state)
Definition python.cpp:91
void python_thread_state_save(void **python_thread_state)
Definition python.cpp:86
const char * name
#define floorf
PointerRNA RNA_pointer_get(PointerRNA *ptr, const char *name)
const PointerRNA PointerRNA_NULL
BL::Object real_object
BL::Object iter_object
bool is_real_object_data() const
@ SUBDIVISION_NONE
Definition scene/mesh.h:118
ustring name
Definition graph/node.h:177
bool is_modified() const
bool use_motion() const
static const uint MAX_MOTION_STEPS
struct Object * parent
float motion_time(const int step) const
MotionType
Definition scene.h:185
@ MOTION_PASS
Definition scene.h:185
@ MOTION_NONE
Definition scene.h:185
@ MOTION_BLUR
Definition scene.h:185
void wait_work(Summary *stats=nullptr)
Definition task.cpp:27
float x
Definition sky_math.h:225
i
Definition text_draw.cc:230
ccl_device_inline Transform transform_empty()
Definition transform.h:411
PointerRNA * ptr
Definition wm_files.cc:4238