diff --git a/source/blender/render/hydra/scene_delegate/blender_scene_delegate.cc b/source/blender/render/hydra/scene_delegate/blender_scene_delegate.cc index 7cc48f1e2b47..12a7c2edb004 100644 --- a/source/blender/render/hydra/scene_delegate/blender_scene_delegate.cc +++ b/source/blender/render/hydra/scene_delegate/blender_scene_delegate.cc @@ -301,9 +301,7 @@ void BlenderSceneDelegate::update_objects(Object *object) if (obj_data) { obj_data->update_parent(); obj_data->update(); - return; - } - if (view3d && !BKE_object_is_visible_in_viewport(view3d, object)) { + obj_data->update_visibility(); return; } objects_[id] = ObjectData::create(this, object, id); @@ -326,8 +324,13 @@ void BlenderSceneDelegate::update_instancers(Object *object) if (i_data) { if (object->transflag & OB_DUPLI) { i_data->update(); + i_data->update_visibility(); } else { + InstancerData *parent_i_data = instancer_data(instancer_prim_id(object->parent)); + if (object->parent && parent_i_data) { + parent_i_data->update_visibility(); + } i_data->remove(); instancers_.erase(id); } @@ -336,9 +339,6 @@ void BlenderSceneDelegate::update_instancers(Object *object) if ((object->transflag & OB_DUPLI) == 0) { return; } - if (view3d && !BKE_object_is_visible_in_viewport(view3d, object)) { - return; - } instancers_[id] = std::make_unique(this, object, id); i_data = instancer_data(id); i_data->init(); @@ -376,8 +376,8 @@ void BlenderSceneDelegate::check_updates() DEGIDIterData data = {0}; data.graph = depsgraph; data.only_updated = true; - ITER_BEGIN ( - DEG_iterator_ids_begin, DEG_iterator_ids_next, DEG_iterator_ids_end, &data, ID *, id) { + ITER_BEGIN (DEG_iterator_ids_begin, DEG_iterator_ids_next, DEG_iterator_ids_end, &data, ID *, id) + { CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, @@ -406,12 +406,15 @@ void BlenderSceneDelegate::check_updates() } break; case ID_SCE: { - if (id->recalc & ID_RECALC_BASE_FLAGS) { - do_update_visibility = true; + if (id->recalc & ID_RECALC_COPY_ON_WRITE && !(id->recalc & ID_RECALC_SELECT)) { + do_update_collection = true; } if (id->recalc & (ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY)) { do_update_collection = true; } + if (id->recalc & ID_RECALC_BASE_FLAGS) { + do_update_visibility = true; + } if (id->recalc & ID_RECALC_AUDIO_VOLUME) { if ((scene->world && !world_data_) || (!scene->world && world_data_)) { do_update_world = true; @@ -440,8 +443,7 @@ void BlenderSceneDelegate::add_new_objects() { DEGObjectIterSettings settings = {0}; settings.depsgraph = depsgraph; - settings.flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_VISIBLE | - DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET; + settings.flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET; DEGObjectIterData data = {0}; data.settings = &settings; data.graph = settings.depsgraph; @@ -451,7 +453,8 @@ void BlenderSceneDelegate::add_new_objects() DEG_iterator_objects_end, &data, Object *, - object) { + object) + { update_objects(object); update_instancers(object); @@ -476,7 +479,8 @@ void BlenderSceneDelegate::remove_unused_objects() DEG_iterator_objects_end, &data, Object *, - object) { + object) + { if (ObjectData::is_supported(object)) { available_objects.insert(object_prim_id(object).GetName()); } @@ -485,25 +489,29 @@ void BlenderSceneDelegate::remove_unused_objects() ITER_END; /* Remove unused instancers */ - for (auto it = instancers_.begin(); it != instancers_.end(); ++it) { - if (available_objects.find(it->first.GetName()) != available_objects.end()) { + auto it_inst = instancers_.begin(); + while (it_inst != instancers_.end()) { + if (available_objects.find(it_inst->first.GetName()) != available_objects.end()) { /* Remove objects from instancers */ - it->second->check_remove(available_objects); - continue; + it_inst->second->check_remove(available_objects); + ++it_inst; + } + else { + it_inst->second->remove(); + instancers_.erase(it_inst++); } - it->second->remove(); - instancers_.erase(it); - it = instancers_.begin(); } /* Remove unused objects */ - for (auto it = objects_.begin(); it != objects_.end(); ++it) { - if (available_objects.find(it->first.GetName()) != available_objects.end()) { - continue; + auto it_obj = objects_.begin(); + while (it_obj != objects_.end()) { + if (available_objects.find(it_obj->first.GetName()) != available_objects.end()) { + ++it_obj; + } + else { + it_obj->second->remove(); + objects_.erase(it_obj++); } - it->second->remove(); - objects_.erase(it); - it = objects_.begin(); } /* Remove unused materials */ @@ -521,13 +529,15 @@ void BlenderSceneDelegate::remove_unused_objects() for (auto &it : instancers_) { it.second->available_materials(available_materials); } - for (auto it = materials_.begin(); it != materials_.end(); ++it) { - if (available_materials.find(it->first) != available_materials.end()) { - continue; + auto it_mat = materials_.begin(); + while (it_mat != materials_.end()) { + if (available_materials.find(it_mat->first) != available_materials.end()) { + ++it_mat; + } + else { + it_mat->second->remove(); + materials_.erase(it_mat++); } - it->second->remove(); - materials_.erase(it); - it = materials_.begin(); } } @@ -554,7 +564,8 @@ void BlenderSceneDelegate::update_visibility() DEG_iterator_objects_end, &data, Object *, - object) { + object) + { if (!object_data(object_prim_id(object))) { update_objects(object); diff --git a/source/blender/render/hydra/scene_delegate/blender_scene_delegate.h b/source/blender/render/hydra/scene_delegate/blender_scene_delegate.h index 11aef5cb3bd7..d7eff5135869 100644 --- a/source/blender/render/hydra/scene_delegate/blender_scene_delegate.h +++ b/source/blender/render/hydra/scene_delegate/blender_scene_delegate.h @@ -22,9 +22,10 @@ namespace blender::render::hydra { extern struct CLG_LogRef *LOG_RENDER_HYDRA_SCENE; class BlenderSceneDelegate : public pxr::HdSceneDelegate { - friend ObjectData; /* has access to instances */ - friend MeshData; /* has access to materials */ - friend MaterialData; /* has access to objects and instancers */ + friend ObjectData; /* has access to instances */ + friend InstancerData; /* has access to instances */ + friend MeshData; /* has access to materials */ + friend MaterialData; /* has access to objects and instancers */ public: enum class EngineType { VIEWPORT = 1, FINAL, PREVIEW }; diff --git a/source/blender/render/hydra/scene_delegate/instancer.cc b/source/blender/render/hydra/scene_delegate/instancer.cc index e10cd9972574..60521e4e4e24 100644 --- a/source/blender/render/hydra/scene_delegate/instancer.cc +++ b/source/blender/render/hydra/scene_delegate/instancer.cc @@ -4,6 +4,9 @@ #include #include +#include "BKE_object.h" +#include "DEG_depsgraph_query.h" + #include "blender_scene_delegate.h" #include "instancer.h" @@ -66,7 +69,8 @@ void InstancerData::update() Object *object = (Object *)id; if (id->recalc & ID_RECALC_GEOMETRY || (object->data && ((ID *)object->data)->recalc & ID_RECALC_GEOMETRY) || - id->recalc & ID_RECALC_TRANSFORM) { + id->recalc & ID_RECALC_TRANSFORM) + { set_instances(); scene_delegate_->GetRenderIndex().GetChangeTracker().MarkInstancerDirty( prim_id, pxr::HdChangeTracker::AllDirty); @@ -83,10 +87,66 @@ pxr::VtValue InstancerData::get_data(pxr::TfToken const &key) const return ret; } +bool InstancerData::is_duplicator_visible(BlenderSceneDelegate *scene_delegate, Object *object) +{ + bool ret = true; + + if (object->transflag & OB_DUPLI) { + int flag = DEG_get_mode(scene_delegate->depsgraph) == DAG_EVAL_VIEWPORT ? + OB_DUPLI_FLAG_VIEWPORT : + OB_DUPLI_FLAG_RENDER; + ret = object->duplicator_visibility_flag & flag; + } + + return ret; +} + +bool InstancerData::update_duplicator_visibility() +{ + bool prev_visible = duplicator_visible; + duplicator_visible = is_duplicator_visible(scene_delegate_, (Object *)id); + bool ret = duplicator_visible != prev_visible; + if (ret) { + ID_LOG(2, ""); + } + return ret; +} + +bool InstancerData::update_instances_visibility() +{ + bool prev_visible = instances_visible; + instances_visible = BKE_object_visibility((Object *)id, + DEG_get_mode(scene_delegate_->depsgraph)) & + OB_VISIBLE_INSTANCES; + bool ret = instances_visible != prev_visible; + if (ret) { + ID_LOG(2, ""); + } + return ret; +} + bool InstancerData::update_visibility() { bool ret = ObjectData::update_visibility(); - if (ret) { + bool dup_ret = update_duplicator_visibility(); + bool inst_ret = update_instances_visibility(); + + Object *ob = ((Object *)id)->parent; + InstancerData *parent_i_data = scene_delegate_->instancer_data( + scene_delegate_->instancer_prim_id(ob)); + + if (dup_ret || (ob && parent_i_data && parent_i_data->visible != duplicator_visible)) { + auto &change_tracker = scene_delegate_->GetRenderIndex().GetChangeTracker(); + if (ob && parent_i_data) { + parent_i_data->visible = duplicator_visible; + change_tracker.MarkInstancerDirty(parent_i_data->prim_id, + pxr::HdChangeTracker::DirtyVisibility); + } + visible = instances_visible; + change_tracker.MarkInstancerDirty(prim_id, pxr::HdChangeTracker::DirtyVisibility); + } + + if (ret || inst_ret) { auto &change_tracker = scene_delegate_->GetRenderIndex().GetChangeTracker(); change_tracker.MarkInstancerDirty(prim_id, pxr::HdChangeTracker::DirtyVisibility); for (auto &it : mesh_instances_) { @@ -103,7 +163,7 @@ bool InstancerData::update_visibility() } } } - return ret; + return ret || dup_ret || inst_ret; } pxr::GfMatrix4d InstancerData::get_transform(pxr::SdfPath const &id) const @@ -174,7 +234,8 @@ void InstancerData::check_update(Object *object) if (l_it != light_instances_.end()) { Object *obj = (Object *)l_it->second.data->id; if (obj->id.recalc & (ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY) || - ((ID *)obj->data)->recalc & ID_RECALC_GEOMETRY) { + ((ID *)obj->data)->recalc & ID_RECALC_GEOMETRY) + { set_instances(); } return; diff --git a/source/blender/render/hydra/scene_delegate/instancer.h b/source/blender/render/hydra/scene_delegate/instancer.h index d0454903abf8..9c3beff76c59 100644 --- a/source/blender/render/hydra/scene_delegate/instancer.h +++ b/source/blender/render/hydra/scene_delegate/instancer.h @@ -25,6 +25,7 @@ class InstancerData : public ObjectData { public: InstancerData(BlenderSceneDelegate *scene_delegate, Object *object, pxr::SdfPath const &prim_id); static bool is_supported(Object *object); + static bool is_duplicator_visible(BlenderSceneDelegate *scene_delegate, Object *object); void init() override; void insert() override; @@ -32,7 +33,10 @@ class InstancerData : public ObjectData { void update() override; pxr::VtValue get_data(pxr::TfToken const &key) const override; + bool update_visibility() override; + bool update_duplicator_visibility(); + bool update_instances_visibility(); pxr::GfMatrix4d get_transform(pxr::SdfPath const &id) const; pxr::HdPrimvarDescriptorVector primvar_descriptors(pxr::HdInterpolation interpolation) const; @@ -45,6 +49,9 @@ class InstancerData : public ObjectData { void update_as_parent(); void update_double_sided(MaterialData *mat_data); + bool duplicator_visible = true; + bool instances_visible = true; + private: pxr::SdfPath object_prim_id(Object *object) const; pxr::SdfPath light_prim_id(LightInstance const &inst, int index) const; diff --git a/source/blender/render/hydra/scene_delegate/mesh.cc b/source/blender/render/hydra/scene_delegate/mesh.cc index 0bae621a101b..dcb47524b7d3 100644 --- a/source/blender/render/hydra/scene_delegate/mesh.cc +++ b/source/blender/render/hydra/scene_delegate/mesh.cc @@ -27,7 +27,8 @@ void MeshData::init() Object *object = (Object *)id; if (object->type == OB_MESH && object->mode == OB_MODE_OBJECT && - BLI_listbase_is_empty(&object->modifiers)) { + BLI_listbase_is_empty(&object->modifiers)) + { write_mesh((Mesh *)object->data); } else { diff --git a/source/blender/render/hydra/scene_delegate/object.cc b/source/blender/render/hydra/scene_delegate/object.cc index 3e750df0c72b..0d5ec26ceff8 100644 --- a/source/blender/render/hydra/scene_delegate/object.cc +++ b/source/blender/render/hydra/scene_delegate/object.cc @@ -2,6 +2,7 @@ * Copyright 2011-2022 Blender Foundation */ #include "BKE_object.h" +#include "DEG_depsgraph_query.h" #include "blender_scene_delegate.h" #include "light.h" @@ -59,14 +60,30 @@ bool ObjectData::is_supported(Object *object) return false; } +bool ObjectData::is_visible(BlenderSceneDelegate *scene_delegate, Object *object) +{ + bool ret = true; + if (DEG_get_mode(scene_delegate->depsgraph) == DAG_EVAL_VIEWPORT) { + ret = BKE_object_is_visible_in_viewport(scene_delegate->view3d, object); + if (ret && object->transflag & OB_DUPLI) { + ret = object->duplicator_visibility_flag & OB_DUPLI_FLAG_VIEWPORT; + } + } + else { + if (object->transflag & OB_DUPLI) { + ret = object->duplicator_visibility_flag & OB_DUPLI_FLAG_RENDER; + } + if (object->parent && (object->parent->transflag & OB_DUPLI)) { + ret = false; + } + } + return ret; +} + bool ObjectData::update_visibility() { - if (!scene_delegate_->view3d) { - return false; - } - bool prev_visible = visible; - visible = BKE_object_is_visible_in_viewport(scene_delegate_->view3d, (Object *)id); + visible = is_visible(scene_delegate_, (Object *)id); bool ret = visible != prev_visible; if (ret) { ID_LOG(2, ""); diff --git a/source/blender/render/hydra/scene_delegate/object.h b/source/blender/render/hydra/scene_delegate/object.h index b6d5e4e48d5e..6ed40aa579a3 100644 --- a/source/blender/render/hydra/scene_delegate/object.h +++ b/source/blender/render/hydra/scene_delegate/object.h @@ -22,6 +22,7 @@ class ObjectData : public IdData { Object *object, pxr::SdfPath const &prim_id); static bool is_supported(Object *object); + static bool is_visible(BlenderSceneDelegate *scene_delegate, Object *object); virtual bool update_visibility(); void update_parent();