diff --git a/source/blender/render/hydra/CMakeLists.txt b/source/blender/render/hydra/CMakeLists.txt index f60ad496eaf1..883177b61977 100644 --- a/source/blender/render/hydra/CMakeLists.txt +++ b/source/blender/render/hydra/CMakeLists.txt @@ -74,6 +74,8 @@ set(SRC sceneDelegate/light.cc sceneDelegate/world.h sceneDelegate/world.cc + sceneDelegate/instance.h + sceneDelegate/instance.cc ) set(LIB diff --git a/source/blender/render/hydra/finalEngine.cc b/source/blender/render/hydra/finalEngine.cc index 695aba6eb125..b422fb9122b2 100644 --- a/source/blender/render/hydra/finalEngine.cc +++ b/source/blender/render/hydra/finalEngine.cc @@ -23,7 +23,7 @@ void FinalEngine::sync(BL::Depsgraph &b_depsgraph, BL::Context &b_context, pxr:: { sceneDelegate = std::make_unique(renderIndex.get(), SdfPath::AbsoluteRootPath().AppendElementString("scene")); - sceneDelegate->Populate(b_depsgraph, b_context); + sceneDelegate->populate((Depsgraph *)b_depsgraph.ptr.data, (bContext *)b_context.ptr.data); for (auto const& setting : renderSettings) { renderDelegate->SetRenderSetting(setting.first, setting.second); diff --git a/source/blender/render/hydra/sceneDelegate/blenderSceneDelegate.cc b/source/blender/render/hydra/sceneDelegate/blenderSceneDelegate.cc index 12a3dabab13d..22a244d512dd 100644 --- a/source/blender/render/hydra/sceneDelegate/blenderSceneDelegate.cc +++ b/source/blender/render/hydra/sceneDelegate/blenderSceneDelegate.cc @@ -1,27 +1,22 @@ /* SPDX-License-Identifier: Apache-2.0 * Copyright 2011-2022 Blender Foundation */ -#include -#include -#include -#include -#include +#include "DEG_depsgraph_query.h" +#include "DNA_scene_types.h" #include "glog/logging.h" #include "blenderSceneDelegate.h" -#include "object.h" -using namespace std; +using namespace pxr; namespace blender::render::hydra { BlenderSceneDelegate::BlenderSceneDelegate(HdRenderIndex* parentIndex, SdfPath const& delegateID) - : HdSceneDelegate(parentIndex, delegateID), - b_depsgraph(nullptr), - b_context(nullptr), - view3d(nullptr), - is_populated(false) + : HdSceneDelegate(parentIndex, delegateID) + , depsgraph(nullptr) + , context(nullptr) + , view3d(nullptr) { } @@ -54,16 +49,17 @@ void BlenderSceneDelegate::update_material(Material *material) void BlenderSceneDelegate::update_world() { - World *world = (World *)b_depsgraph->scene().world().ptr.data; + Scene *scene = DEG_get_input_scene(depsgraph); + World *world = scene->world; if (!world_data) { if (world) { - world_data = WorldData::init(this, world, (bContext *)b_context->ptr.data); + world_data = WorldData::init(this, world, context); world_data->insert_prim(); } } else { if (world) { - world_data = WorldData::init(this, world, (bContext *)b_context->ptr.data); + world_data = WorldData::init(this, world, context); world_data->mark_prim_dirty(IdData::DirtyBits::AllDirty); } else { @@ -82,55 +78,80 @@ bool BlenderSceneDelegate::GetVisible(SdfPath const &id) return object_data(id)->visible; } -void BlenderSceneDelegate::update_collection() +void BlenderSceneDelegate::update_collection(bool remove, bool visibility) { - /* add new objects */ - std::set available_objects; - for (auto &inst : b_depsgraph->object_instances) { - if (inst.is_instance()) { - continue; + if (visibility) { + /* Check and update visibility */ + for (auto &obj : objects) { + if (obj.second->update_visibility(view3d)) { + obj.second->mark_prim_dirty(IdData::DirtyBits::DirtyVisibility); + }; } - Object *object = (Object *)inst.object().ptr.data; - if (!supported_object(object)) { - continue; - } - available_objects.insert(ObjectData::prim_id(this, object)); + } - if (!is_populated) { + /* Export of new visible objects which were not exported before */ + std::set available_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 | DEG_ITER_OBJECT_FLAG_DUPLI; + DEGObjectIterData data = {0}; + data.settings = &settings; + data.graph = settings.depsgraph; + data.flag = settings.flags; + ITER_BEGIN (DEG_iterator_objects_begin, + DEG_iterator_objects_next, + DEG_iterator_objects_end, + &data, Object *, object) { + if (data.dupli_object_current != nullptr) { + InstanceData i_data(this, data.dupli_object_current); + LOG(INFO) << "Instance: " << i_data.name() << " " << i_data.random_id(); + continue; + } + if (!ObjectData::supported(object)) { + continue; + } + + SdfPath id = ObjectData::prim_id(this, object); + if (remove) { + available_objects.insert(id); + } + + if (!object_data(id)) { add_update_object(object, true, true, true); } } + ITER_END; - if (!is_populated) { - return; - } + if (remove) { + /* remove unused objects */ + for (auto it = objects.begin(); it != objects.end(); ++it) { + if (available_objects.find(it->first) != available_objects.end()) { + continue; + } + it->second->remove_prim(); + objects.erase(it); + it = objects.begin(); + } - /* remove unused objects */ - for (auto it = objects.begin(); it != objects.end(); ++it) { - if (available_objects.find(it->first) != available_objects.end()) { - continue; + /* remove unused materials */ + std::set available_materials; + for (auto &obj : objects) { + MeshData *m_data = dynamic_cast(obj.second.get()); + if (m_data && !m_data->material_id.IsEmpty()) { + available_materials.insert(m_data->material_id); + } } - it->second->remove_prim(); - objects.erase(it); - it = objects.begin(); - } - - /* remove unused materials */ - std::set available_materials; - for (auto &obj : objects) { - MeshData *m_data = dynamic_cast(obj.second.get()); - if (m_data && !m_data->material_id.IsEmpty()) { - available_materials.insert(m_data->material_id); + for (auto it = materials.begin(); it != materials.end(); ++it) { + if (available_materials.find(it->first) != available_materials.end()) { + continue; + } + it->second->remove_prim(); + materials.erase(it); + it = materials.begin(); } } - for (auto it = materials.begin(); it != materials.end(); ++it) { - if (available_materials.find(it->first) != available_materials.end()) { - continue; - } - it->second->remove_prim(); - materials.erase(it); - it = materials.begin(); - } } void BlenderSceneDelegate::add_update_object(Object *object, bool geometry, bool transform, bool shading) @@ -198,31 +219,18 @@ MaterialData *BlenderSceneDelegate::material_data(SdfPath const &id) return it->second.get(); } -bool BlenderSceneDelegate::supported_object(Object *object) +void BlenderSceneDelegate::populate(Depsgraph *deps, bContext *cont) { - return object->type == OB_MESH || - object->type == OB_LAMP || - object->type == OB_SURF || - object->type == OB_FONT || - object->type == OB_CURVES || - object->type == OB_CURVES_LEGACY || - object->type == OB_MBALL; -} + bool is_populated = depsgraph != nullptr; -void BlenderSceneDelegate::Populate(BL::Depsgraph &b_deps, BL::Context &b_cont) -{ - LOG(INFO) << "Populate " << is_populated; - - b_depsgraph = &b_deps; - b_context = &b_cont; - view3d = (View3D *)b_context->space_data().ptr.data; + depsgraph = deps; + context = cont; + view3d = CTX_wm_view3d(context); if (!is_populated) { /* Export initial objects */ - update_collection(); + update_collection(false, false); update_world(); - - is_populated = true; return; } @@ -230,96 +238,75 @@ void BlenderSceneDelegate::Populate(BL::Depsgraph &b_deps, BL::Context &b_cont) bool do_update_collection = false; bool do_update_visibility = false; bool do_update_world = false; + bool transform, geometry, shading; - for (auto &update : b_depsgraph->updates) { - BL::ID id = update.id(); - LOG(INFO) << "Update: " << id.name_full() << " [" - << update.is_updated_transform() - << update.is_updated_geometry() - << update.is_updated_shading() << "]"; + 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) { - if (id.is_a(&RNA_Object)) { - Object *object = (Object *)id.ptr.data; - if (!supported_object(object)) { - continue; - } - add_update_object(object, - update.is_updated_geometry(), - update.is_updated_transform(), - update.is_updated_shading()); - continue; - } + transform = (id->recalc & ID_RECALC_TRANSFORM) != 0; + shading = (id->recalc & (ID_RECALC_SHADING | ID_RECALC_ANIMATION)) != 0; + geometry = (id->recalc & ID_RECALC_GEOMETRY) != 0; - if (id.is_a(&RNA_Material)) { - if (update.is_updated_shading()) { - Material *material = (Material *)id.ptr.data; - update_material(material); - } - continue; - } - - if (id.is_a(&RNA_Collection)) { - if (update.is_updated_transform() && update.is_updated_geometry()) { - do_update_collection = true; - } - continue; - } + LOG(INFO) << "Update: " << id->name << " [" << transform << geometry << shading << "]"; - if (id.is_a(&RNA_Scene)) { - if (!update.is_updated_geometry() && !update.is_updated_transform() && !update.is_updated_shading()) { - do_update_visibility = true; + switch (GS(id->name)) { + case ID_OB: { + Object *object = (Object *)id; + if (!ObjectData::supported(object)) { + break; + } + geometry |= (((ID *)object->data)->recalc & ID_RECALC_GEOMETRY) != 0; + add_update_object(object, geometry, transform, shading); + } + break; - Scene *scene = (Scene *)id.ptr.data; - if ((scene->world && !world_data) || (!scene->world && world_data)) { + case ID_MA: + if (shading) { + Material *material = (Material *)id; + update_material(material); + } + break; + + case ID_GR: + if (transform && geometry) { + do_update_collection = true; + } + break; + + case ID_SCE: + if (!geometry && !transform && !shading) { + Scene *scene = (Scene *)id; + do_update_visibility = true; + + if ((scene->world && !world_data) || (!scene->world && world_data)) { + do_update_world = true; + } + } + break; + + case ID_WO: + if (shading) { do_update_world = true; } - } - continue; - } + break; - if (id.is_a(&RNA_World)) { - if (update.is_updated_shading()) { - do_update_world = true; - } - continue; + default: + break; } } + ITER_END; - if (do_update_collection) { - update_collection(); - } - if (do_update_visibility) { - update_visibility(); + if (do_update_collection || do_update_visibility) { + update_collection(do_update_collection, do_update_visibility); } if (do_update_world) { update_world(); } - -} - -void BlenderSceneDelegate::update_visibility() -{ - /* Check and update visibility */ - for (auto &obj : objects) { - if (obj.second->update_visibility(view3d)) { - obj.second->mark_prim_dirty(IdData::DirtyBits::DirtyVisibility); - }; - } - - /* Export of new visible objects which were not exported before */ - for (auto &inst : b_depsgraph->object_instances) { - if (inst.is_instance()) { - continue; - } - Object *object = (Object *)inst.object().ptr.data; - if (!supported_object(object)) { - continue; - } - - if (!object_data(ObjectData::prim_id(this, object))) { - add_update_object(object, true, true, true); - } - } } HdMeshTopology BlenderSceneDelegate::GetMeshTopology(SdfPath const& id) diff --git a/source/blender/render/hydra/sceneDelegate/blenderSceneDelegate.h b/source/blender/render/hydra/sceneDelegate/blenderSceneDelegate.h index 080eda40e6b6..bace71c8370d 100644 --- a/source/blender/render/hydra/sceneDelegate/blenderSceneDelegate.h +++ b/source/blender/render/hydra/sceneDelegate/blenderSceneDelegate.h @@ -3,65 +3,57 @@ #pragma once -#include - -#include -#include #include -#include -#include -#include "MEM_guardedalloc.h" -#include "RNA_blender_cpp.h" +#include "BKE_context.h" +#include "DEG_depsgraph.h" #include "object.h" #include "mesh.h" #include "light.h" #include "world.h" - -using namespace pxr; +#include "instance.h" namespace blender::render::hydra { -class BlenderSceneDelegate : public HdSceneDelegate { +class BlenderSceneDelegate : public pxr::HdSceneDelegate { public: - BlenderSceneDelegate(HdRenderIndex* renderIndex, SdfPath const &delegateId); + BlenderSceneDelegate(pxr::HdRenderIndex *renderIndex, pxr::SdfPath const &delegateId); ~BlenderSceneDelegate() override = default; - void Populate(BL::Depsgraph &b_deps, BL::Context &b_context); + void populate(Depsgraph *depsgraph, bContext *context); // delegate methods - HdMeshTopology GetMeshTopology(SdfPath const& id) override; - GfMatrix4d GetTransform(SdfPath const& id) override; - VtValue Get(SdfPath const& id, TfToken const& key) override; - VtValue GetLightParamValue(SdfPath const& id, TfToken const& key) override; - HdPrimvarDescriptorVector GetPrimvarDescriptors(SdfPath const& id, HdInterpolation interpolation) override; - SdfPath GetMaterialId(SdfPath const &rprimId) override; - VtValue GetMaterialResource(SdfPath const &materialId) override; - bool GetVisible(SdfPath const &id) override; + pxr::HdMeshTopology GetMeshTopology(pxr::SdfPath const &id) override; + pxr::GfMatrix4d GetTransform(pxr::SdfPath const &id) override; + pxr::VtValue Get(pxr::SdfPath const &id, pxr::TfToken const &key) override; + pxr::VtValue GetLightParamValue(pxr::SdfPath const &id, pxr::TfToken const &key) override; + pxr::HdPrimvarDescriptorVector GetPrimvarDescriptors(pxr::SdfPath const &id, pxr::HdInterpolation interpolation) override; + pxr::SdfPath GetMaterialId(pxr::SdfPath const &rprimId) override; + pxr::VtValue GetMaterialResource(pxr::SdfPath const &materialId) override; + bool GetVisible(pxr::SdfPath const &id) override; private: - ObjectData *object_data(SdfPath const &id); - MeshData *mesh_data(SdfPath const &id); - LightData *light_data(SdfPath const &id); - MaterialData *material_data(SdfPath const &id); - bool supported_object(Object *object); + ObjectData *object_data(pxr::SdfPath const &id); + MeshData *mesh_data(pxr::SdfPath const &id); + LightData *light_data(pxr::SdfPath const &id); + MaterialData *material_data(pxr::SdfPath const &id); void add_update_object(Object *object, bool geometry, bool transform, bool shading); void set_material(MeshData &mesh_data); void update_material(Material *material); void update_world(); - void update_collection(); - void update_visibility(); + void update_collection(bool remove, bool visibility); private: - BL::Depsgraph *b_depsgraph; - BL::Context *b_context; + Depsgraph *depsgraph; + bContext *context; View3D *view3d; - bool is_populated; + ObjectDataMap objects; MaterialDataMap materials; std::unique_ptr world_data; + InstanceDataMap instances; }; } // namespace blender::render::hydra diff --git a/source/blender/render/hydra/sceneDelegate/instance.cc b/source/blender/render/hydra/sceneDelegate/instance.cc new file mode 100644 index 000000000000..84feceddb5b4 --- /dev/null +++ b/source/blender/render/hydra/sceneDelegate/instance.cc @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright 2011-2022 Blender Foundation */ + +#include "instance.h" + +using namespace pxr; + +namespace blender::render::hydra { + +InstanceData::InstanceData(pxr::HdSceneDelegate *scene_delegate, DupliObject *dupli) + : IdData(scene_delegate, (ID *)dupli->ob_data) + , dupli(dupli) +{ +} + +int InstanceData::random_id() +{ + return dupli->random_id; +} + +VtValue InstanceData::get_data(TfToken const &key) +{ + return VtValue(); +} + +void InstanceData::insert_prim() +{ +} + +void InstanceData::remove_prim() +{ +} + +void InstanceData::mark_prim_dirty(DirtyBits dirty_bits) +{ +} + +} // namespace blender::render::hydra diff --git a/source/blender/render/hydra/sceneDelegate/instance.h b/source/blender/render/hydra/sceneDelegate/instance.h new file mode 100644 index 000000000000..f9dd6e0c15af --- /dev/null +++ b/source/blender/render/hydra/sceneDelegate/instance.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright 2011-2022 Blender Foundation */ + +#pragma once + +#include "BKE_duplilist.h" + +#include "id.h" + +namespace blender::render::hydra { + +class InstanceData: public IdData { +public: + InstanceData(pxr::HdSceneDelegate *scene_delegate, DupliObject *dupli); + + int random_id(); + + pxr::VtValue get_data(pxr::TfToken const &key) override; + void insert_prim() override; + void remove_prim() override; + void mark_prim_dirty(DirtyBits dirty_bits) override; + +public: + DupliObject *dupli; +}; + +using InstanceDataMap = pxr::TfHashMap, pxr::SdfPath::Hash>; + +} // namespace blender::render::hydra diff --git a/source/blender/render/hydra/sceneDelegate/light.cc b/source/blender/render/hydra/sceneDelegate/light.cc index f3cddffb438b..3a49dd93e84f 100644 --- a/source/blender/render/hydra/sceneDelegate/light.cc +++ b/source/blender/render/hydra/sceneDelegate/light.cc @@ -151,6 +151,8 @@ void LightData::remove_prim() void LightData::mark_prim_dirty(DirtyBits dirty_bits) { + /* TODO: prim_type was changed we have to do remove..add light */ + HdDirtyBits bits = HdLight::Clean; switch (dirty_bits) { case DirtyBits::DirtyTransform: diff --git a/source/blender/render/hydra/sceneDelegate/material.h b/source/blender/render/hydra/sceneDelegate/material.h index e0ea0c129b54..17a21382a270 100644 --- a/source/blender/render/hydra/sceneDelegate/material.h +++ b/source/blender/render/hydra/sceneDelegate/material.h @@ -13,9 +13,6 @@ namespace blender::render::hydra { -class MaterialData; -using MaterialDataMap = pxr::TfHashMap, pxr::SdfPath::Hash>; - class MaterialData: IdData { public: static std::unique_ptr init(pxr::HdSceneDelegate *scene_delegate, Material *material); @@ -35,4 +32,6 @@ private: pxr::SdfAssetPath mtlx_path; }; +using MaterialDataMap = pxr::TfHashMap, pxr::SdfPath::Hash>; + } // namespace blender::render::hydra diff --git a/source/blender/render/hydra/sceneDelegate/mesh.cc b/source/blender/render/hydra/sceneDelegate/mesh.cc index cec931983feb..51d190992ecc 100644 --- a/source/blender/render/hydra/sceneDelegate/mesh.cc +++ b/source/blender/render/hydra/sceneDelegate/mesh.cc @@ -160,6 +160,14 @@ void MeshData::mark_prim_dirty(DirtyBits dirty_bits) { SdfPath p_id = prim_id(scene_delegate, (Object *)id); if (!scene_delegate->GetRenderIndex().HasRprim(p_id)) { + /* Trying to insert prim */ + insert_prim(); + return; + } + + if (face_vertex_counts.empty()) { + /* Remove prim without faces */ + remove_prim(); return; } diff --git a/source/blender/render/hydra/sceneDelegate/object.cc b/source/blender/render/hydra/sceneDelegate/object.cc index 7bb7912b4cc3..96552c12743b 100644 --- a/source/blender/render/hydra/sceneDelegate/object.cc +++ b/source/blender/render/hydra/sceneDelegate/object.cc @@ -12,6 +12,24 @@ using namespace pxr; namespace blender::render::hydra { +bool ObjectData::supported(Object *object) +{ + switch (object->type) { + case OB_MESH: + case OB_SURF: + case OB_FONT: + case OB_CURVES: + case OB_CURVES_LEGACY: + case OB_MBALL: + case OB_LAMP: + return true; + + default: + break; + } + return false; +} + std::unique_ptr ObjectData::init(pxr::HdSceneDelegate *scene_delegate, Object *object) { switch (object->type) { diff --git a/source/blender/render/hydra/sceneDelegate/object.h b/source/blender/render/hydra/sceneDelegate/object.h index dab439d4559b..f787733355b4 100644 --- a/source/blender/render/hydra/sceneDelegate/object.h +++ b/source/blender/render/hydra/sceneDelegate/object.h @@ -14,11 +14,9 @@ namespace blender::render::hydra { -class ObjectData; -using ObjectDataMap = pxr::TfHashMap, pxr::SdfPath::Hash>; - class ObjectData: public IdData { public: + static bool supported(Object *object); static std::unique_ptr init(pxr::HdSceneDelegate *scene_delegate, Object *object); static pxr::SdfPath prim_id(pxr::HdSceneDelegate *scene_delegate, Object *object); @@ -31,6 +29,6 @@ public: bool visible; }; - +using ObjectDataMap = pxr::TfHashMap, pxr::SdfPath::Hash>; } // namespace blender::render::hydra diff --git a/source/blender/render/hydra/viewportEngine.cc b/source/blender/render/hydra/viewportEngine.cc index 882a3ada8dd6..fc299983e9e4 100644 --- a/source/blender/render/hydra/viewportEngine.cc +++ b/source/blender/render/hydra/viewportEngine.cc @@ -246,7 +246,7 @@ void ViewportEngine::sync(BL::Depsgraph &b_depsgraph, BL::Context &b_context, Hd sceneDelegate = std::make_unique(renderIndex.get(), SdfPath::AbsoluteRootPath().AppendElementString("scene")); } - sceneDelegate->Populate(b_depsgraph, b_context); + sceneDelegate->populate((Depsgraph *)b_depsgraph.ptr.data, (bContext *)b_context.ptr.data); for (auto const& setting : renderSettings) { renderDelegate->SetRenderSetting(setting.first, setting.second);