32bool BlenderSync::BKE_object_is_modified(BL::Object &b_ob)
35 if (b_ob.type() == BL::Object::type_META) {
39 if (ccl::BKE_object_is_modified(b_ob, b_scene, preview)) {
45 for (BL::MaterialSlot &b_slot : b_ob.material_slots) {
46 if (b_slot.link() == BL::MaterialSlot::link_OBJECT) {
54bool BlenderSync::object_is_geometry(
BObjectInfo &b_ob_info)
62 const BL::Object::type_enum type = b_ob_info.
iter_object.type();
64 if (type == BL::Object::type_VOLUME || type == BL::Object::type_CURVES ||
65 type == BL::Object::type_POINTCLOUD || type == BL::Object::type_LIGHT)
71 return b_ob_data.is_a(&RNA_Mesh);
74bool BlenderSync::object_can_have_geometry(BL::Object &b_ob)
76 const BL::Object::type_enum type = b_ob.type();
78 case BL::Object::type_MESH:
79 case BL::Object::type_CURVE:
80 case BL::Object::type_SURFACE:
81 case BL::Object::type_META:
82 case BL::Object::type_FONT:
83 case BL::Object::type_CURVES:
84 case BL::Object::type_POINTCLOUD:
85 case BL::Object::type_VOLUME:
92bool BlenderSync::object_is_light(BL::Object &b_ob)
96 return (b_ob_data && b_ob_data.is_a(&RNA_Light));
99bool BlenderSync::object_is_camera(BL::Object &b_ob)
103 return (b_ob_data && b_ob_data.is_a(&RNA_Camera));
106void BlenderSync::sync_object_motion_init(BL::Object &b_parent, BL::Object &b_ob,
Object *
object)
110 array<Transform> motion;
111 object->set_motion(motion);
113 Geometry *geom =
object->get_geometry();
118 int motion_steps = 0;
119 bool use_motion_blur =
false;
125 use_motion_blur =
true;
132 geom->set_use_motion_blur(use_motion_blur);
137 motion[motion_steps / 2] =
object->get_tfm();
140 object->set_motion(motion);
148Object *BlenderSync::sync_object(BL::ViewLayer &b_view_layer,
149 BL::DepsgraphObjectInstance &b_instance,
150 const float motion_time,
151 bool use_particle_hair,
156 const bool is_instance = b_instance.is_instance();
157 BL::Object b_ob = b_instance.object();
158 BL::Object b_parent = is_instance ? b_instance.
parent() : b_instance.object();
159 BL::Object b_real_object = is_instance ? b_instance.instance_object() : b_ob;
161 b_real_object, preview, use_adaptive_subdivision) !=
163 BObjectInfo b_ob_info{
164 b_ob, b_real_object,
object_get_data(b_ob, use_adaptive_subdiv), use_adaptive_subdiv};
165 const bool motion = motion_time != 0.0f;
167 int *persistent_id =
nullptr;
168 BL::Array<int, OBJECT_PERSISTENT_ID_SIZE> persistent_id_array;
170 persistent_id_array = b_instance.persistent_id();
171 persistent_id = persistent_id_array.data;
180 if (!object_is_geometry(b_ob_info)) {
185 if (object_is_light(b_ob)) {
190 else if (culling.
test(scene, b_ob, tfm)) {
196 const bool use_holdout = b_parent.holdout_get(
PointerRNA_NULL, b_view_layer);
199 if (b_parent.ptr.data != b_ob.ptr.data) {
205 if (use_holdout && (layer_flag & view_layer.exclude_layer)) {
211 const bool use_indirect_only = !use_holdout &&
213 if (use_indirect_only) {
214 visibility &= ~PATH_RAY_CAMERA;
218 if (visibility == 0) {
224 TaskPool *object_geom_task_pool = (is_instance) ?
nullptr : geom_task_pool;
227 const ObjectKey key(b_parent, persistent_id, b_ob_info.
real_object, use_particle_hair);
232 object = object_map.find(key);
236 const int time_index =
object->motion_step(motion_time);
237 if (time_index >= 0) {
238 array<Transform> motion =
object->get_motion();
239 motion[time_index] = tfm;
240 object->set_motion(motion);
244 if (object->get_geometry()) {
245 sync_geometry_motion(
246 b_ob_info,
object, motion_time, use_particle_hair, object_geom_task_pool);
254 bool object_updated = object_map.add_or_update(&
object, b_ob, b_parent, key) ||
255 (tfm !=
object->get_tfm());
259 b_ob_info, object_updated, use_particle_hair, object_geom_task_pool);
260 object->set_geometry(geometry);
264 if (sync_object_attributes(b_instance,
object)) {
265 object_updated =
true;
269 object->set_use_holdout(use_holdout);
271 object->set_visibility(visibility);
273 object->set_is_shadow_catcher(b_ob.is_shadow_catcher() || b_parent.is_shadow_catcher());
275 object->set_shadow_terminator_shading_offset(b_ob.shadow_terminator_shading_offset());
277 object->set_shadow_terminator_geometry_offset(b_ob.shadow_terminator_geometry_offset());
279 float ao_distance =
get_float(cobject,
"ao_distance");
280 if (ao_distance == 0.0f && b_parent.ptr.data != b_ob.ptr.data) {
282 ao_distance =
get_float(cparent,
"ao_distance");
284 object->set_ao_distance(ao_distance);
286 const bool is_caustics_caster =
get_boolean(cobject,
"is_caustics_caster");
287 object->set_is_caustics_caster(is_caustics_caster);
289 const bool is_caustics_receiver =
get_boolean(cobject,
"is_caustics_receiver");
290 object->set_is_caustics_receiver(is_caustics_receiver);
292 object->set_is_bake_target(b_ob_info.
real_object == b_bake_target);
295 BL::Object parent = b_ob.parent();
298 while (parent.parent()) {
299 parent = parent.parent();
301 parent_name = parent.name();
304 parent_name = b_ob.name();
306 object->set_asset_name(parent_name);
311 const bool do_sync =
object->is_modified() || object_updated ||
312 (
object->get_geometry() && object->get_geometry()->
is_modified());
314 object->name = b_ob.name().c_str();
315 object->set_pass_id(b_ob.pass_index());
319 object->set_tfm(tfm);
323 object->set_dupli_generated(0.5f *
get_float3(b_instance.orco()) -
325 object->set_dupli_uv(
get_float2(b_instance.uv()));
326 object->set_random_id(b_instance.random_id());
335 string lightgroup = b_ob.lightgroup();
336 if (lightgroup.empty()) {
337 lightgroup = b_parent.lightgroup();
339 object->set_lightgroup(ustring(lightgroup));
347 sync_object_motion_init(b_parent, b_ob,
object);
349 if (do_sync || object->motion_is_modified()) {
350 object->tag_update(scene);
355 sync_dupli_particle(b_parent, b_instance,
object);
372 if (use_instancer && b_instance.is_instance()) {
383bool BlenderSync::sync_object_attributes(BL::DepsgraphObjectInstance &b_instance,
Object *
object)
386 AttributeRequestSet requests =
object->get_geometry()->needed_attributes();
389 vector<ParamValue> &attributes =
object->attributes;
390 bool changed =
false;
392 for (
int i = attributes.size() - 1;
i >= 0;
i--) {
393 if (!requests.
find(attributes[
i].name())) {
394 attributes.erase(attributes.begin() +
i);
400 for (
const AttributeRequest &req : requests.
requests) {
401 const ustring name = req.
name;
403 std::string real_name;
406 if (type == BL::ShaderNodeAttribute::attribute_type_OBJECT ||
407 type == BL::ShaderNodeAttribute::attribute_type_INSTANCER)
409 const bool use_instancer = (type == BL::ShaderNodeAttribute::attribute_type_INSTANCER);
413 ParamValue *param =
nullptr;
415 for (
size_t i = 0;
i < attributes.size();
i++) {
416 if (attributes[
i].name() == name) {
417 param = &attributes[
i];
423 const ParamValue new_param(name, TypeFloat4, 1, &value);
424 assert(new_param.datasize() ==
sizeof(value));
428 attributes.push_back(new_param);
430 else if (!(param->get<
float4>() == value)) {
442void BlenderSync::sync_procedural(BL::Object &b_ob,
443 BL::MeshSequenceCacheModifier &b_mesh_cache,
444 bool has_subdivision_modifier)
447 BL::CacheFile cache_file = b_mesh_cache.cache_file();
448 void *cache_file_key = cache_file.ptr.data;
450 AlembicProcedural *procedural =
static_cast<AlembicProcedural *
>(
451 procedural_map.find(cache_file_key));
453 if (procedural ==
nullptr) {
454 procedural = scene->create_node<AlembicProcedural>();
455 procedural_map.add(cache_file_key, procedural);
458 procedural_map.used(procedural);
461 float current_frame =
static_cast<float>(b_scene.frame_current());
462 if (cache_file.override_frame()) {
463 current_frame = cache_file.frame();
466 if (!cache_file.override_frame()) {
467 procedural->set_start_frame(
static_cast<float>(b_scene.frame_start()));
468 procedural->set_end_frame(
static_cast<float>(b_scene.frame_end()));
471 procedural->set_frame(current_frame);
472 procedural->set_frame_rate(b_scene.render().fps() / b_scene.render().fps_base());
473 procedural->set_frame_offset(cache_file.frame_offset());
476 procedural->set_filepath(ustring(absolute_path));
478 array<ustring> layers;
479 for (BL::CacheFileLayer &layer : cache_file.layers) {
480 if (layer.hide_layer()) {
487 procedural->set_layers(layers);
489 procedural->set_scale(cache_file.scale());
491 procedural->set_use_prefetch(cache_file.use_prefetch());
492 procedural->set_prefetch_cache_size(cache_file.prefetch_cache_size());
495 const ustring object_path = ustring(b_mesh_cache.object_path());
497 AlembicObject *abc_object = procedural->get_or_create_object(object_path);
499 array<Node *> used_shaders = find_used_shaders(b_ob);
500 abc_object->set_used_shaders(used_shaders);
503 const float subd_dicing_rate =
max(0.1f,
RNA_float_get(&cobj,
"dicing_rate") * dicing_rate);
504 abc_object->set_subd_dicing_rate(subd_dicing_rate);
505 abc_object->set_subd_max_level(max_subdivisions);
507 abc_object->set_ignore_subdivision(!has_subdivision_modifier);
509 if (abc_object->is_modified() || procedural->is_modified()) {
510 procedural->tag_update(scene);
515 (void)has_subdivision_modifier;
519void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph,
520 BL::SpaceView3D &b_v3d,
521 const float motion_time)
527 const bool motion = motion_time != 0.0f;
531 geometry_map.pre_sync();
532 object_map.pre_sync();
533 procedural_map.pre_sync();
534 particle_system_map.pre_sync();
535 motion_times.clear();
538 geometry_motion_synced.clear();
541 world_use_portal =
false;
546 instance_geometries_by_object.clear();
550 BlenderObjectCulling culling(scene, b_scene);
554 const bool show_lights = BlenderViewportParameters(b_v3d, use_developer_ui).use_scene_lights;
556 BL::ViewLayer b_view_layer = b_depsgraph.view_layer_eval();
557 BL::Depsgraph::object_instances_iterator b_instance_iter;
559 for (b_depsgraph.object_instances.begin(b_instance_iter);
560 b_instance_iter != b_depsgraph.object_instances.end() && !cancel;
563 BL::DepsgraphObjectInstance b_instance = *b_instance_iter;
564 BL::Object b_ob = b_instance.object();
567 const bool show_in_viewport = !b_v3d || b_ob.visible_in_viewport_get(b_v3d);
568 if (show_in_viewport ==
false) {
578 const bool sync_hair = b_instance.show_particles() && object_has_particle_hair(b_ob);
581 if (b_instance.show_self()) {
583 bool use_procedural =
false;
584 bool has_subdivision_modifier =
false;
588 if (use_experimental_procedural) {
590 use_procedural = b_mesh_cache && b_mesh_cache.cache_file().use_render_procedural();
593 if (use_procedural) {
597 sync_procedural(b_ob, b_mesh_cache, has_subdivision_modifier);
603 sync_object(b_view_layer,
609 sync_hair ?
nullptr : &geom_task_pool);
616 b_view_layer, b_instance, motion_time,
true, show_lights, culling, &geom_task_pool);
619 cancel = progress.get_cancel();
624 progress.set_sync_status(
"");
626 if (!cancel && !motion) {
628 sync_background_light(b_v3d);
633 object_map.post_sync();
634 geometry_map.post_sync();
635 particle_system_map.post_sync();
636 procedural_map.post_sync();
640 geometry_motion_synced.clear();
644void BlenderSync::sync_motion(BL::RenderSettings &b_render,
645 BL::Depsgraph &b_depsgraph,
646 BL::SpaceView3D &b_v3d,
647 BL::Object &b_override,
650 void **python_thread_state)
657 BL::Object b_cam = b_scene.camera();
662 const int frame_center = b_scene.frame_current();
663 const float subframe_center = b_scene.frame_subframe();
664 float frame_center_delta = 0.0f;
669 const float shuttertime = scene->camera->get_shuttertime();
671 frame_center_delta = -shuttertime * 0.5f;
675 frame_center_delta = shuttertime * 0.5f;
678 const float time = frame_center + subframe_center + frame_center_delta;
679 const int frame = (int)
floorf(time);
680 const float subframe = time - frame;
682 b_engine.frame_set(frame, subframe);
685 sync_camera_motion(b_render, b_cam, width, height, 0.0f);
687 sync_objects(b_depsgraph, b_v3d);
694 for (
size_t step = 0;
step < camera_motion_steps;
step++) {
695 motion_times.insert(scene->camera->motion_time(
step));
700 geometry_motion_attribute_synced.clear();
701 for (
Geometry *geom : scene->geometry) {
703 geometry_motion_attribute_synced.insert(geom);
708 for (
const float relative_time : motion_times) {
710 if (relative_time == 0.0f) {
714 VLOG_WORK <<
"Synchronizing motion for the relative time " << relative_time <<
".";
717 const float shuttertime = scene->motion_shutter_time();
720 const float time = frame_center + subframe_center + frame_center_delta +
721 relative_time * shuttertime * 0.5f;
722 const int frame = (int)
floorf(time);
723 const float subframe = time - frame;
727 b_engine.frame_set(frame, subframe);
731 sync_camera_motion(b_render, b_cam, width, height, relative_time);
734 sync_objects(b_depsgraph, b_v3d, relative_time);
737 geometry_motion_attribute_synced.clear();
743 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])
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)
T * resize(const size_t newsize)
void push_back_slow(const T &t)
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 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 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 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)
#define CCL_NAMESPACE_END
VecBase< float, 4 > float4
#define assert(assertion)
VecBase< float, D > step(VecOp< float, D >, VecOp< float, D >) RET
static uint hash_string(const char *str)
ccl_device_inline uint hash_uint2(const uint kx, const uint ky)
ccl_device_inline float3 object_color(KernelGlobals kg, const 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()
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)
const PointerRNA PointerRNA_NULL
float RNA_float_get(PointerRNA *ptr, const char *name)
bool is_real_object_data() const
static const uint MAX_MOTION_STEPS
float motion_time(const int step) const
void wait_work(Summary *stats=nullptr)