34bool BlenderSync::BKE_object_is_modified(BL::Object &b_ob)
37 if (b_ob.type() == BL::Object::type_META) {
41 else if (ccl::BKE_object_is_modified(b_ob, b_scene, preview)) {
47 for (BL::MaterialSlot &b_slot : b_ob.material_slots) {
48 if (b_slot.link() == BL::MaterialSlot::link_OBJECT) {
57bool BlenderSync::object_is_geometry(
BObjectInfo &b_ob_info)
65 BL::Object::type_enum type = b_ob_info.
iter_object.type();
67 if (type == BL::Object::type_VOLUME || type == BL::Object::type_CURVES ||
68 type == BL::Object::type_POINTCLOUD)
74 return b_ob_data.is_a(&RNA_Mesh);
77bool BlenderSync::object_can_have_geometry(BL::Object &b_ob)
79 BL::Object::type_enum type = b_ob.type();
81 case BL::Object::type_MESH:
82 case BL::Object::type_CURVE:
83 case BL::Object::type_SURFACE:
84 case BL::Object::type_META:
85 case BL::Object::type_FONT:
86 case BL::Object::type_CURVES:
87 case BL::Object::type_POINTCLOUD:
88 case BL::Object::type_VOLUME:
95bool BlenderSync::object_is_light(BL::Object &b_ob)
97 BL::ID b_ob_data = b_ob.data();
99 return (b_ob_data && b_ob_data.is_a(&RNA_Light));
102bool BlenderSync::object_is_camera(BL::Object &b_ob)
104 BL::ID b_ob_data = b_ob.data();
106 return (b_ob_data && b_ob_data.is_a(&RNA_Camera));
109void BlenderSync::sync_object_motion_init(BL::Object &b_parent, BL::Object &b_ob,
Object *
object)
114 object->set_motion(motion);
116 Geometry *geom =
object->get_geometry();
121 int motion_steps = 0;
122 bool use_motion_blur =
false;
128 use_motion_blur =
true;
135 geom->set_use_motion_blur(use_motion_blur);
140 geom->set_motion_steps(motion_steps);
146 motion[motion_steps / 2] =
object->get_tfm();
149 object->set_motion(motion);
151 for (
size_t step = 0;
step < motion_steps;
step++) {
152 motion_times.insert(object->motion_time(step));
157Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
158 BL::ViewLayer &b_view_layer,
159 BL::DepsgraphObjectInstance &b_instance,
161 bool use_particle_hair,
167 const bool is_instance = b_instance.is_instance();
168 BL::Object b_ob = b_instance.object();
169 BL::Object b_parent = is_instance ? b_instance.
parent() : b_instance.object();
170 BObjectInfo b_ob_info{b_ob, is_instance ? b_instance.instance_object() : b_ob, b_ob.data()};
171 const bool motion = motion_time != 0.0f;
173 int *persistent_id =
NULL;
174 BL::Array<int, OBJECT_PERSISTENT_ID_SIZE> persistent_id_array;
176 persistent_id_array = b_instance.persistent_id();
177 persistent_id = persistent_id_array.data;
186 if (!motion && object_is_light(b_ob)) {
194 if (!((layer_flag & view_layer.holdout_layer) && (layer_flag & view_layer.exclude_layer)))
200 is_instance ? b_instance.random_id() : 0,
209 if (!object_is_geometry(b_ob_info)) {
214 if (culling.
test(scene, b_ob, tfm)) {
220 bool use_holdout = b_parent.holdout_get(
PointerRNA_NULL, b_view_layer);
223 if (b_parent.ptr.data != b_ob.ptr.data) {
229 if (use_holdout && (layer_flag & view_layer.exclude_layer)) {
235 bool use_indirect_only = !use_holdout &&
237 if (use_indirect_only) {
238 visibility &= ~PATH_RAY_CAMERA;
242 if (visibility == 0) {
248 TaskPool *object_geom_task_pool = (is_instance) ?
NULL : geom_task_pool;
256 object = object_map.
find(key);
258 if (
object && object->use_motion()) {
261 if (time_index >= 0) {
263 motion[time_index] = tfm;
264 object->set_motion(motion);
268 if (object->get_geometry()) {
269 sync_geometry_motion(
270 b_depsgraph, b_ob_info,
object, motion_time, use_particle_hair, object_geom_task_pool);
278 bool object_updated = object_map.
add_or_update(&
object, b_ob, b_parent, key) ||
279 (tfm !=
object->get_tfm());
283 b_depsgraph, b_ob_info, object_updated, use_particle_hair, object_geom_task_pool);
284 object->set_geometry(geometry);
288 if (sync_object_attributes(b_instance,
object)) {
289 object_updated =
true;
293 object->set_use_holdout(use_holdout);
295 object->set_visibility(visibility);
297 object->set_is_shadow_catcher(b_ob.is_shadow_catcher() || b_parent.is_shadow_catcher());
299 float shadow_terminator_shading_offset =
get_float(cobject,
"shadow_terminator_offset");
300 object->set_shadow_terminator_shading_offset(shadow_terminator_shading_offset);
302 float shadow_terminator_geometry_offset =
get_float(cobject,
303 "shadow_terminator_geometry_offset");
304 object->set_shadow_terminator_geometry_offset(shadow_terminator_geometry_offset);
306 float ao_distance =
get_float(cobject,
"ao_distance");
307 if (ao_distance == 0.0f && b_parent.ptr.data != b_ob.ptr.data) {
309 ao_distance =
get_float(cparent,
"ao_distance");
311 object->set_ao_distance(ao_distance);
313 bool is_caustics_caster =
get_boolean(cobject,
"is_caustics_caster");
314 object->set_is_caustics_caster(is_caustics_caster);
316 bool is_caustics_receiver =
get_boolean(cobject,
"is_caustics_receiver");
317 object->set_is_caustics_receiver(is_caustics_receiver);
320 BL::Object parent = b_ob.parent();
323 while (parent.parent()) {
324 parent = parent.parent();
326 parent_name = parent.name();
329 parent_name = b_ob.name();
331 object->set_asset_name(parent_name);
336 if (object->is_modified() || object_updated ||
337 (object->get_geometry() && object->get_geometry()->is_modified()))
339 object->name = b_ob.name().c_str();
340 object->set_pass_id(b_ob.pass_index());
344 object->set_tfm(tfm);
348 object->set_dupli_generated(0.5f *
get_float3(b_instance.orco()) -
350 object->set_dupli_uv(
get_float2(b_instance.uv()));
351 object->set_random_id(b_instance.random_id());
360 string lightgroup = b_ob.lightgroup();
361 if (lightgroup.empty()) {
362 lightgroup = b_parent.lightgroup();
364 object->set_lightgroup(ustring(lightgroup));
371 object->tag_update(scene);
374 sync_object_motion_init(b_parent, b_ob,
object);
378 sync_dupli_particle(b_parent, b_instance,
object);
395 if (use_instancer && b_instance.is_instance()) {
406bool BlenderSync::sync_object_attributes(BL::DepsgraphObjectInstance &b_instance,
Object *
object)
413 bool changed =
false;
415 for (
int i = attributes.size() - 1; i >= 0; i--) {
416 if (!requests.
find(attributes[i].name())) {
417 attributes.erase(attributes.begin() + i);
424 ustring name = req.
name;
426 std::string real_name;
429 if (type == BL::ShaderNodeAttribute::attribute_type_OBJECT ||
430 type == BL::ShaderNodeAttribute::attribute_type_INSTANCER)
432 bool use_instancer = (type == BL::ShaderNodeAttribute::attribute_type_INSTANCER);
436 ParamValue *param =
NULL;
438 for (
size_t i = 0; i < attributes.size(); i++) {
439 if (attributes[i].name() == name) {
440 param = &attributes[i];
446 ParamValue new_param(name, TypeDesc::TypeFloat4, 1, &value);
447 assert(new_param.datasize() ==
sizeof(value));
451 attributes.push_back(new_param);
453 else if (memcmp(param->data(), &value,
sizeof(value)) != 0) {
465void BlenderSync::sync_procedural(BL::Object &b_ob,
466 BL::MeshSequenceCacheModifier &b_mesh_cache,
467 bool has_subdivision_modifier)
470 BL::CacheFile cache_file = b_mesh_cache.cache_file();
471 void *cache_file_key = cache_file.ptr.data;
473 AlembicProcedural *procedural =
static_cast<AlembicProcedural *
>(
474 procedural_map.
find(cache_file_key));
476 if (procedural ==
nullptr) {
477 procedural = scene->create_node<AlembicProcedural>();
478 procedural_map.
add(cache_file_key, procedural);
481 procedural_map.
used(procedural);
484 float current_frame =
static_cast<float>(b_scene.frame_current());
485 if (cache_file.override_frame()) {
486 current_frame = cache_file.frame();
489 if (!cache_file.override_frame()) {
490 procedural->set_start_frame(
static_cast<float>(b_scene.frame_start()));
491 procedural->set_end_frame(
static_cast<float>(b_scene.frame_end()));
494 procedural->set_frame(current_frame);
495 procedural->set_frame_rate(b_scene.render().fps() / b_scene.render().fps_base());
496 procedural->set_frame_offset(cache_file.frame_offset());
499 procedural->set_filepath(ustring(absolute_path));
502 for (BL::CacheFileLayer &layer : cache_file.layers) {
503 if (layer.hide_layer()) {
508 layers.push_back_slow(ustring(absolute_path));
510 procedural->set_layers(layers);
512 procedural->set_scale(cache_file.scale());
514 procedural->set_use_prefetch(cache_file.use_prefetch());
515 procedural->set_prefetch_cache_size(cache_file.prefetch_cache_size());
518 ustring object_path = ustring(b_mesh_cache.object_path());
520 AlembicObject *abc_object = procedural->get_or_create_object(object_path);
523 abc_object->set_used_shaders(used_shaders);
526 const float subd_dicing_rate =
max(0.1f,
RNA_float_get(&cobj,
"dicing_rate") * dicing_rate);
527 abc_object->set_subd_dicing_rate(subd_dicing_rate);
528 abc_object->set_subd_max_level(max_subdivisions);
530 abc_object->set_ignore_subdivision(!has_subdivision_modifier);
532 if (abc_object->is_modified() || procedural->is_modified()) {
533 procedural->tag_update(scene);
538 (void)has_subdivision_modifier;
542void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph,
543 BL::SpaceView3D &b_v3d,
550 bool motion = motion_time != 0.0f;
559 motion_times.clear();
562 geometry_motion_synced.clear();
564 instance_geometries_by_object.clear();
571 bool use_portal =
false;
574 BL::ViewLayer b_view_layer = b_depsgraph.view_layer_eval();
575 BL::Depsgraph::object_instances_iterator b_instance_iter;
577 for (b_depsgraph.object_instances.begin(b_instance_iter);
578 b_instance_iter != b_depsgraph.object_instances.end() && !cancel;
581 BL::DepsgraphObjectInstance b_instance = *b_instance_iter;
582 BL::Object b_ob = b_instance.object();
585 const bool show_in_viewport = !b_v3d || b_ob.visible_in_viewport_get(b_v3d);
586 if (show_in_viewport ==
false) {
596 const bool sync_hair = b_instance.show_particles() && object_has_particle_hair(b_ob);
599 if (b_instance.show_self()) {
601 bool use_procedural =
false;
602 bool has_subdivision_modifier =
false;
608 use_procedural = b_mesh_cache && b_mesh_cache.cache_file().use_render_procedural();
611 if (use_procedural) {
615 sync_procedural(b_ob, b_mesh_cache, has_subdivision_modifier);
621 sync_object(b_depsgraph,
629 sync_hair ?
NULL : &geom_task_pool);
635 sync_object(b_depsgraph,
653 if (!cancel && !motion) {
654 sync_background_light(b_v3d, use_portal);
667 geometry_motion_synced.clear();
670void BlenderSync::sync_motion(BL::RenderSettings &b_render,
671 BL::Depsgraph &b_depsgraph,
672 BL::SpaceView3D &b_v3d,
673 BL::Object &b_override,
676 void **python_thread_state)
683 BL::Object b_cam = b_scene.camera();
688 int frame_center = b_scene.frame_current();
689 float subframe_center = b_scene.frame_subframe();
690 float frame_center_delta = 0.0f;
695 float shuttertime = scene->camera->get_shuttertime();
697 frame_center_delta = -shuttertime * 0.5f;
701 frame_center_delta = shuttertime * 0.5f;
704 float time = frame_center + subframe_center + frame_center_delta;
706 float subframe = time - frame;
708 b_engine.frame_set(frame, subframe);
711 sync_camera_motion(b_render, b_cam, width, height, 0.0f);
713 sync_objects(b_depsgraph, b_v3d);
720 for (
size_t step = 0;
step < camera_motion_steps;
step++) {
721 motion_times.insert(scene->camera->motion_time(step));
726 geometry_motion_attribute_synced.clear();
727 for (
Geometry *geom : scene->geometry) {
729 geometry_motion_attribute_synced.insert(geom);
734 foreach (
float relative_time, motion_times) {
736 if (relative_time == 0.0f) {
740 VLOG_WORK <<
"Synchronizing motion for the relative time " << relative_time <<
".";
743 float shuttertime = scene->motion_shutter_time();
746 float time = frame_center + subframe_center + frame_center_delta +
747 relative_time * shuttertime * 0.5f;
749 float subframe = time - frame;
753 b_engine.frame_set(frame, subframe);
757 sync_camera_motion(b_render, b_cam, width, height, relative_time);
760 sync_objects(b_depsgraph, b_v3d, relative_time);
763 geometry_motion_attribute_synced.clear();
769 b_engine.frame_set(frame_center, subframe_center);
bool BKE_object_dupli_find_rgba_attribute(const Object *ob, const DupliObject *dupli, const Object *dupli_parent, const char *name, float r_value[4])
constexpr PointerRNA PointerRNA_NULL
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
Attribute * find(ustring name) const
static uint64_t get_shadow_set_membership(const BL::Object &parent, const BL::Object &object)
static uint64_t get_light_set_membership(const BL::Object &parent, const BL::Object &object)
static uint get_receiver_light_set(const BL::Object &parent, const BL::Object &object)
static uint get_blocker_shadow_set(const BL::Object &parent, const BL::Object &object)
void init_object(Scene *scene, BL::Object &b_ob)
bool test(Scene *scene, BL::Object &b_ob, Transform &tfm)
bool has_motion_blur() const
void set_sync_status(const string &status_, const string &substatus_="")
bool add_or_update(T **r_data, const BL::ID &id)
void add(const K &key, T *data)
T * find(const BL::ID &id)
void post_sync(bool do_delete=true)
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 string blender_absolute_path(BL::BlendData &b_data, BL::ID &b_id, const string &path)
static float2 get_float2(const BL::Array< float, 2 > &array)
static Transform get_transform(const BL::Array< float, 16 > &array)
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)
BL::ShaderNodeAttribute::attribute_type_enum BlenderAttributeType
#define CCL_NAMESPACE_END
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
static uint hash_string(const char *str)
ccl_device_inline uint hash_uint2(uint kx, uint ky)
ccl_device_inline float3 object_color(KernelGlobals kg, int object)
@ ATTR_STD_MOTION_VERTEX_POSITION
@ PATH_RAY_ALL_VISIBILITY
CCL_NAMESPACE_BEGIN ccl_device_inline float2 zero_float2()
CCL_NAMESPACE_BEGIN ccl_device_inline float3 zero_float3()
T step(const T &edge, const T &value)
VecBase< float, 4 > float4
void python_thread_state_restore(void **python_thread_state)
void python_thread_state_save(void **python_thread_state)
PointerRNA RNA_pointer_get(PointerRNA *ptr, const char *name)
float RNA_float_get(PointerRNA *ptr, const char *name)
bool is_real_object_data() const
int motion_step(float time) const
static const uint MAX_MOTION_STEPS
void wait_work(Summary *stats=NULL)