Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/blender/blender_object.cpp
| Context not available. | |||||
| } | } | ||||
| /* Object */ | /* Object */ | ||||
| Object *BlenderSync::sync_task(BL::Depsgraph &b_depsgraph, | |||||
easythrees: This is the function that should be called in a multi-threaded fashion. I add this to the task… | |||||
| BL::ViewLayer &b_view_layer, | |||||
| BL::DepsgraphObjectInstance &b_instance, | |||||
| float motion_time, | |||||
| bool use_particle_hair, | |||||
| bool show_lights, | |||||
| BlenderObjectCulling &culling, | |||||
| bool *use_portal, | |||||
| SyncObject &curr_obj) | |||||
| { | |||||
| const bool is_instance = curr_obj.is_instance; | |||||
| BL::Object b_ob = curr_obj.b_object; | |||||
| BL::Object b_parent = curr_obj.b_parent; | |||||
| BL::Object b_ob_instance = curr_obj.b_ob_instance; | |||||
| const bool motion = motion_time != 0.0f; | |||||
| /*const*/ Transform tfm = curr_obj.tfm; | |||||
| int *persistent_id = curr_obj.persistent_id; | |||||
| /* light is handled separately */ | |||||
| if (!motion && curr_obj.is_light) { | |||||
| if (!show_lights) { | |||||
| return NULL; | |||||
| } | |||||
| /* TODO: don't use lights for excluded layers used as mask layer, | |||||
| * when dynamic overrides are back. */ | |||||
| #if 0 | |||||
| if (!((layer_flag & view_layer.holdout_layer) && (layer_flag & view_layer.exclude_layer))) | |||||
| #endif | |||||
| { | |||||
| sync_light(b_parent, | |||||
| persistent_id, | |||||
| curr_obj.b_object, // b_ob, | |||||
| b_ob_instance, | |||||
| is_instance ? curr_obj.random_id : 0, | |||||
| tfm, | |||||
| use_portal); | |||||
| } | |||||
| return NULL; | |||||
| } | |||||
| /* only interested in object that we can create meshes from */ | |||||
| if (!curr_obj.is_mesh) { | |||||
| return NULL; | |||||
| } | |||||
| /* Perform object culling. */ | |||||
| // if (culling.test(scene, b_ob, tfm)) { | |||||
| if (culling.test(scene, curr_obj.b_object, tfm)) { | |||||
| return NULL; | |||||
| } | |||||
| /* Visibility flags for both parent and child. */ | |||||
| bool use_holdout = curr_obj.is_holdout; | |||||
| uint visibility = curr_obj.base_visibility; | |||||
| // if (b_parent.ptr.data != b_ob.ptr.data) { | |||||
| if (b_parent.ptr.data != curr_obj.b_object.ptr.data) { | |||||
| visibility &= curr_obj.parent_visibility; | |||||
| } | |||||
| /* Clear camera visibility for indirect only objects. */ | |||||
| bool use_indirect_only = !use_holdout && | |||||
| b_parent.indirect_only_get(PointerRNA_NULL, b_view_layer); | |||||
| if (use_indirect_only) { | |||||
| visibility &= ~PATH_RAY_CAMERA; | |||||
| } | |||||
| /* Don't export completely invisible objects. */ | |||||
| if (visibility == 0) { | |||||
| return NULL; | |||||
| } | |||||
| /* key to lookup object */ | |||||
| // ObjectKey key(b_parent, persistent_id, b_ob_instance, use_particle_hair); | |||||
| ObjectKey key(b_parent, persistent_id, curr_obj.b_ob_instance, use_particle_hair); | |||||
| Object *object; | |||||
| /* motion vector case */ | |||||
| if (motion) { | |||||
| mutex.lock(); | |||||
| object = object_map.find(key); | |||||
| if (object && object->use_motion()) { | |||||
| /* Set transform at matching motion time step. */ | |||||
| int time_index = object->motion_step(motion_time); | |||||
| if (time_index >= 0) { | |||||
| object->motion[time_index] = tfm; | |||||
| } | |||||
| /* mesh deformation */ | |||||
| if (object->geometry) | |||||
| // sync_geometry_motion(b_depsgraph, b_ob, object, motion_time, use_particle_hair); | |||||
| sync_geometry_motion(b_depsgraph, b_ob, object, motion_time, use_particle_hair); | |||||
| } | |||||
| mutex.unlock(); | |||||
| return object; | |||||
| } | |||||
| /* test if we need to sync */ | |||||
| bool object_updated = false; | |||||
| mutex.lock(); | |||||
| // if (object_map.add_or_update(&object, b_ob, b_parent, key)) { | |||||
| if (object_map.add_or_update(&object, curr_obj.b_object, b_parent, key)) | |||||
| { | |||||
| object_updated = true; | |||||
| } | |||||
| mutex.unlock(); | |||||
| /* mesh sync */ | |||||
| mutex.lock(); | |||||
| // object->geometry = sync_geometry(b_depsgraph, b_ob, b_ob_instance, object_updated, use_particle_hair); | |||||
| object->geometry = sync_geometry( | |||||
| b_depsgraph, curr_obj.b_object, curr_obj.b_ob_instance, object_updated, use_particle_hair, curr_obj); | |||||
| mutex.unlock(); | |||||
| /* special case not tracked by object update flags */ | |||||
| /* holdout */ | |||||
| if (use_holdout != object->use_holdout) { | |||||
| object->use_holdout = use_holdout; | |||||
| scene->object_manager->tag_update(scene); | |||||
| object_updated = true; | |||||
| } | |||||
| if (visibility != object->visibility) { | |||||
| object->visibility = visibility; | |||||
| object_updated = true; | |||||
| } | |||||
| bool is_shadow_catcher = curr_obj.is_shadow_catcher; | |||||
| if (is_shadow_catcher != object->is_shadow_catcher) { | |||||
| object->is_shadow_catcher = is_shadow_catcher; | |||||
| object_updated = true; | |||||
| } | |||||
| float shadow_terminator_offset = curr_obj.shadow_terminator_offset; | |||||
| if (shadow_terminator_offset != object->shadow_terminator_offset) { | |||||
| object->shadow_terminator_offset = shadow_terminator_offset; | |||||
| object_updated = true; | |||||
| } | |||||
| /* sync the asset name for Cryptomatte */ | |||||
| BL::Object parent = b_ob.parent(); | |||||
| ustring parent_name; | |||||
| if (parent) { | |||||
| while (parent.parent()) { | |||||
| parent = parent.parent(); | |||||
| } | |||||
| parent_name = parent.name(); | |||||
| } | |||||
| else { | |||||
| parent_name = b_ob.name(); | |||||
| } | |||||
| if (object->asset_name != parent_name) { | |||||
| object->asset_name = parent_name; | |||||
| object_updated = true; | |||||
| } | |||||
| /* object sync | |||||
| * transform comparison should not be needed, but duplis don't work perfect | |||||
| * in the depsgraph and may not signal changes, so this is a workaround */ | |||||
| if (object_updated || (object->geometry && object->geometry->need_update) || | |||||
| curr_obj.tfm != object->tfm) { | |||||
| /* | |||||
| object->name = b_ob.name().c_str(); | |||||
| object->pass_id = b_ob.pass_index(); | |||||
| object->color = get_float3(b_ob.color()); | |||||
| object->tfm = tfm; | |||||
| */ | |||||
| object->name = curr_obj.b_object.name().c_str(); | |||||
| object->pass_id = curr_obj.b_object.pass_index(); | |||||
| object->color = get_float3(curr_obj.b_object.color()); | |||||
| object->tfm = curr_obj.tfm; | |||||
| object->motion.clear(); | |||||
| /* motion blur */ | |||||
| Scene::MotionType need_motion = scene->need_motion(); | |||||
| if (need_motion != Scene::MOTION_NONE && object->geometry) { | |||||
| Geometry *geom = object->geometry; | |||||
| geom->use_motion_blur = false; | |||||
| geom->motion_steps = 0; | |||||
| uint motion_steps; | |||||
| if (need_motion == Scene::MOTION_BLUR) { | |||||
| // motion_steps = object_motion_steps(b_parent, b_ob, Object::MAX_MOTION_STEPS); | |||||
| motion_steps = object_motion_steps(curr_obj.b_parent, curr_obj.b_object, Object::MAX_MOTION_STEPS); | |||||
| geom->motion_steps = motion_steps; | |||||
| // if (motion_steps && object_use_deform_motion(b_parent, b_ob)) { | |||||
| if (motion_steps && object_use_deform_motion(curr_obj.b_parent, curr_obj.b_object)) { | |||||
| geom->use_motion_blur = true; | |||||
| } | |||||
| } | |||||
| else { | |||||
| motion_steps = 3; | |||||
| geom->motion_steps = motion_steps; | |||||
| } | |||||
| object->motion.clear(); | |||||
| object->motion.resize(motion_steps, transform_empty()); | |||||
| if (motion_steps) { | |||||
| object->motion[motion_steps / 2] = tfm; | |||||
| for (size_t step = 0; step < motion_steps; step++) { | |||||
| motion_times.insert(object->motion_time(step)); | |||||
| } | |||||
| } | |||||
| } | |||||
| /* dupli texture coordinates and random_id */ | |||||
| if (is_instance) { | |||||
| object->dupli_generated = curr_obj.dupli_generated; | |||||
| object->dupli_uv = curr_obj.dupli_uv; | |||||
| object->random_id = curr_obj.random_id; | |||||
| } | |||||
| else { | |||||
| object->dupli_generated = make_float3(0.0f, 0.0f, 0.0f); | |||||
| object->dupli_uv = make_float2(0.0f, 0.0f); | |||||
| object->random_id = hash_uint2(hash_string(object->name.c_str()), 0); | |||||
| } | |||||
| object->tag_update(scene); | |||||
| } | |||||
| if (is_instance) { | |||||
| /* Sync possible particle data. */ | |||||
| // sync_dupli_particle(b_parent, b_instance, object); | |||||
| sync_dupli_particle(curr_obj.b_parent, b_instance, object); | |||||
| } | |||||
| return object; | |||||
| } | |||||
| Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, | Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, | ||||
| BL::ViewLayer &b_view_layer, | BL::ViewLayer &b_view_layer, | ||||
| Context not available. | |||||
| const bool show_lights = BlenderViewportParameters(b_v3d).use_scene_lights; | const bool show_lights = BlenderViewportParameters(b_v3d).use_scene_lights; | ||||
| BL::ViewLayer b_view_layer = b_depsgraph.view_layer_eval(); | BL::ViewLayer b_view_layer = b_depsgraph.view_layer_eval(); | ||||
| BL::Depsgraph::object_instances_iterator b_instance_iter; | BL::Depsgraph::object_instances_iterator b_instance_iter; | ||||
| #if 1 | |||||
| for (b_depsgraph.object_instances.begin(b_instance_iter); | |||||
| b_instance_iter != b_depsgraph.object_instances.end() && !cancel; | |||||
| ++b_instance_iter) { | |||||
| BL::DepsgraphObjectInstance b_instance = *b_instance_iter; | |||||
| BL::Object b_ob = b_instance.object(); | |||||
| /* Viewport visibility. */ | |||||
| const bool show_in_viewport = !b_v3d || b_ob.visible_in_viewport_get(b_v3d); | |||||
| if (show_in_viewport == false) { | |||||
| continue; | |||||
| } | |||||
| SyncObject curr_object; | |||||
| curr_object.tfm = get_transform(b_ob.matrix_world()); | |||||
| curr_object.is_instance = b_instance.is_instance(); | |||||
| if (curr_object.is_instance) { | |||||
| // NOTE: instance_object is a real object from the dependency graph, but it | |||||
| // does not have instance transform (which gets acquired separately). | |||||
| curr_object.b_object = b_instance.instance_object(); | |||||
| } | |||||
| else { | |||||
| // NOTE: Non-instanced objects points to real object in the dependency, | |||||
| // (as opposite to the instance case when object is a temporary copy with | |||||
| // some fields overwritten). | |||||
| curr_object.b_object = b_instance.object(); | |||||
| } | |||||
| curr_object.b_parent = curr_object.is_instance ? b_instance.parent() : b_instance.object(); | |||||
| curr_object.b_ob_instance = curr_object.is_instance ? b_instance.instance_object() : b_ob; | |||||
| // NOTE: Store all fields like persistent_id | |||||
| // (refer to BKE_duplilist.h to see the | |||||
| // definition of DupliObject) | |||||
| BL::Array<int, OBJECT_PERSISTENT_ID_SIZE> persistent_id_array; | |||||
| if (curr_object.is_instance) { | |||||
| persistent_id_array = b_instance.persistent_id(); | |||||
| curr_object.persistent_id = persistent_id_array.data; | |||||
| } | |||||
| curr_object.random_id = b_instance.random_id(); | |||||
| curr_object.dupli_generated = 0.5f * get_float3(b_instance.orco()) - | |||||
| make_float3(0.5f, 0.5f, 0.5f); | |||||
| curr_object.dupli_uv = get_float2(b_instance.uv()); | |||||
| // | |||||
| PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles"); | |||||
| curr_object.is_holdout = get_boolean(cobject, "is_holdout") || | |||||
| curr_object.b_parent.holdout_get(PointerRNA_NULL, b_view_layer); | |||||
| curr_object.base_visibility = object_ray_visibility(b_ob) & PATH_RAY_ALL_VISIBILITY; | |||||
| curr_object.parent_visibility = object_ray_visibility(curr_object.b_parent); | |||||
| curr_object.is_shadow_catcher = get_boolean(cobject, "is_shadow_catcher"); | |||||
| curr_object.shadow_terminator_offset = get_float(cobject, "shadow_terminator_offset"); | |||||
| curr_object.is_light = object_is_light(curr_object.b_object); | |||||
| curr_object.is_mesh = object_is_mesh(curr_object.b_object); | |||||
| curr_object.name = curr_object.b_object.name(); | |||||
| /* Load per-object culling data. */ | |||||
| culling.init_object(scene, b_ob); | |||||
| /* Object itself. */ | |||||
| if (b_instance.show_self()) { | |||||
| task_pool.push([&] { | |||||
easythreesAuthorUnsubmitted Done Inline ActionsTask pool here to launch the new sync task function. easythrees: Task pool here to launch the new sync task function. | |||||
| sync_task(b_depsgraph, | |||||
| b_view_layer, | |||||
| b_instance, | |||||
| motion_time, | |||||
| false, | |||||
| show_lights, | |||||
| culling, | |||||
| &use_portal, | |||||
| curr_object); | |||||
| }); | |||||
| /* | |||||
| sync_task(b_depsgraph, | |||||
| b_view_layer, | |||||
| b_instance, | |||||
| motion_time, | |||||
| false, | |||||
| show_lights, | |||||
| culling, | |||||
| &use_portal, | |||||
| curr_object); | |||||
| */ | |||||
| } | |||||
| /* Particle hair as separate object. */ | |||||
| /* | |||||
| if (b_instance.show_particles() && object_has_particle_hair(b_ob)) { | |||||
| sync_object(b_depsgraph, | |||||
| b_view_layer, | |||||
| b_instance, | |||||
| motion_time, | |||||
| true, | |||||
| show_lights, | |||||
| culling, | |||||
| &use_portal); | |||||
| } | |||||
| */ | |||||
| cancel = progress.get_cancel(); | |||||
| } | |||||
| #else | |||||
| for (b_depsgraph.object_instances.begin(b_instance_iter); | for (b_depsgraph.object_instances.begin(b_instance_iter); | ||||
| b_instance_iter != b_depsgraph.object_instances.end() && !cancel; | b_instance_iter != b_depsgraph.object_instances.end() && !cancel; | ||||
| ++b_instance_iter) { | ++b_instance_iter) { | ||||
| Context not available. | |||||
| cancel = progress.get_cancel(); | cancel = progress.get_cancel(); | ||||
| } | } | ||||
| #endif | |||||
| progress.set_sync_status(""); | progress.set_sync_status(""); | ||||
| Context not available. | |||||
This is the function that should be called in a multi-threaded fashion. I add this to the task pool in sync_objects(...)