From de4f158a5dedfad55ebc1d140a1bdc58ceb5a09f Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Wed, 2 Feb 2022 18:18:13 +0000 Subject: [PATCH 01/67] Added bindings for object_instances CollectionPropertyRNA access and extended BlenderPyContext to interface between bindings and caller code. Added access via the iterators on msBlendContext::exportMesh (WIP) --- .../BlenderPyObjects/BlenderPyContext.cpp | 30 +++++++++++++++++++ .../BlenderPyObjects/BlenderPyContext.h | 6 ++++ .../MeshSyncClientBlender/msblenBinder.cpp | 7 +++++ .../MeshSyncClientBlender/msblenContext.cpp | 13 +++++++- 4 files changed, 55 insertions(+), 1 deletion(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp index 4a18d94d..b06eca5c 100644 --- a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp @@ -11,6 +11,8 @@ PropertyRNA* BlenderPyContext_blend_data = nullptr; PropertyRNA* BlenderPyContext_scene = nullptr; FunctionRNA* BlenderPyContext_evaluated_depsgraph_get = nullptr; FunctionRNA* BlenderPyContext_depsgraph_update = nullptr; +PropertyRNA* BlenderPyContext_depsgraph_object_instances = nullptr; + BlenderPyContext BlenderPyContext::get() @@ -36,5 +38,33 @@ void BlenderPyContext::UpdateDepsgraph(Depsgraph* depsgraph) { call(g_context, depsgraph, BlenderPyContext_depsgraph_update); } +void BlenderPyContext::object_instances_begin(CollectionPropertyIterator* it, Depsgraph* depsgraph) { + + PointerRNA* rna; + rna->data = depsgraph; + + CollectionPropertyRNA* cprop = (CollectionPropertyRNA*)BlenderPyContext_depsgraph_object_instances; + + cprop->begin(it, rna); +} + +void BlenderPyContext::object_instances_end(CollectionPropertyIterator* it) { + + CollectionPropertyRNA* cprop = (CollectionPropertyRNA*)BlenderPyContext_depsgraph_object_instances; + cprop->end(it); +} + +void BlenderPyContext::object_instances_next(CollectionPropertyIterator * it){ + CollectionPropertyRNA* cprop = (CollectionPropertyRNA*)BlenderPyContext_depsgraph_object_instances; + cprop->next(it); +} + +mu::float4x4* BlenderPyContext::object_instances_get(CollectionPropertyIterator* it) { + CollectionPropertyRNA* cprop = (CollectionPropertyRNA*)BlenderPyContext_depsgraph_object_instances; + auto ret = cprop->get(it); + auto k = (mu::float4x4*)ret.data; + return k; + +} } // namespace blender diff --git a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.h b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.h index 2150cd1d..d149bdae 100644 --- a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.h +++ b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.h @@ -2,6 +2,7 @@ #include //bContext #include "msblenMacros.h" //MSBLEN_BOILERPLATE2 +#include "MeshUtils/muMath.h" namespace blender { @@ -18,6 +19,11 @@ namespace blender static void UpdateDepsgraph(Depsgraph* depsgraph); + void object_instances_begin(CollectionPropertyIterator* it, Depsgraph* depsgrah); + void object_instances_end(CollectionPropertyIterator* it); + void object_instances_next(CollectionPropertyIterator* it); + mu::float4x4* object_instances_get(CollectionPropertyIterator* it); + }; } // namespace blender diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp index 40012a1b..c374a401 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp @@ -63,6 +63,8 @@ extern PropertyRNA* BlenderPyContext_scene; extern FunctionRNA* BlenderPyContext_evaluated_depsgraph_get; extern FunctionRNA* BlenderPyContext_depsgraph_update; +extern PropertyRNA* BlenderPyContext_depsgraph_object_instances; + bool ready() { return g_context != nullptr; @@ -192,6 +194,11 @@ void setup(py::object bpy_context) } } else if (match_type("Depsgraph")) { + each_prop{ + if (match_prop("object_instances")) { + BlenderPyContext_depsgraph_object_instances = prop; + } + } each_func{ if (match_func("update")) { BlenderPyContext_depsgraph_update = func; diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index def4f7c6..c750b4ce 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -641,8 +641,19 @@ ms::MeshPtr msblenContext::exportMesh(const Object *src) if (need_convert) { if (m_settings.BakeModifiers ) { - Depsgraph* depsgraph = bl::BlenderPyContext::get().evaluated_depsgraph_get(); + auto blContext = bl::BlenderPyContext::get(); + Depsgraph* depsgraph = blContext.evaluated_depsgraph_get(); bobj = (Object*)bl::BlenderPyID(bobj).evaluated_get(depsgraph); + + CollectionPropertyIterator* beginIt; + CollectionPropertyIterator* nextIt; + CollectionPropertyIterator* endIt; + + blContext.object_instances_begin(beginIt, depsgraph); + blContext.object_instances_end(endIt); + for (nextIt = beginIt; nextIt != endIt; blContext.object_instances_next(nextIt)) { + auto matrix = blContext.object_instances_get(nextIt); + } } if (Mesh *tmp = bobj.to_mesh()) { data = tmp; From 03b74ef5047ecdb1430724e15a9b45d84d1335e4 Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Thu, 3 Feb 2022 16:43:12 +0000 Subject: [PATCH 02/67] Correct usage of CollectionPropertyIterator, binded to instance_object for evaluating the RNAPointer to an Object --- .../BlenderPyObjects/BlenderPyContext.cpp | 25 +++++++++++++------ .../BlenderPyObjects/BlenderPyContext.h | 2 +- .../MeshSyncClientBlender/msblenBinder.cpp | 9 +++++++ .../MeshSyncClientBlender/msblenContext.cpp | 22 ++++++++++------ 4 files changed, 41 insertions(+), 17 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp index b06eca5c..7586f141 100644 --- a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp @@ -12,6 +12,7 @@ PropertyRNA* BlenderPyContext_scene = nullptr; FunctionRNA* BlenderPyContext_evaluated_depsgraph_get = nullptr; FunctionRNA* BlenderPyContext_depsgraph_update = nullptr; PropertyRNA* BlenderPyContext_depsgraph_object_instances = nullptr; +PropertyRNA* BlenderPyContext_depsgraph_instance_object = nullptr; @@ -40,12 +41,12 @@ void BlenderPyContext::UpdateDepsgraph(Depsgraph* depsgraph) { void BlenderPyContext::object_instances_begin(CollectionPropertyIterator* it, Depsgraph* depsgraph) { - PointerRNA* rna; - rna->data = depsgraph; + PointerRNA rna; + rna.data = depsgraph; CollectionPropertyRNA* cprop = (CollectionPropertyRNA*)BlenderPyContext_depsgraph_object_instances; - cprop->begin(it, rna); + cprop->begin(it, &rna); } void BlenderPyContext::object_instances_end(CollectionPropertyIterator* it) { @@ -59,12 +60,20 @@ void BlenderPyContext::object_instances_next(CollectionPropertyIterator * it){ cprop->next(it); } -mu::float4x4* BlenderPyContext::object_instances_get(CollectionPropertyIterator* it) { - CollectionPropertyRNA* cprop = (CollectionPropertyRNA*)BlenderPyContext_depsgraph_object_instances; - auto ret = cprop->get(it); - auto k = (mu::float4x4*)ret.data; - return k; +Object* BlenderPyContext::object_instances_get(CollectionPropertyIterator* it) { + + + auto collectionProp = (CollectionPropertyRNA*)BlenderPyContext_depsgraph_object_instances; + auto objectInstanceProp = (PointerPropertyRNA*)BlenderPyContext_depsgraph_instance_object; + auto instance = collectionProp->get(it); + auto object = objectInstanceProp->get(&instance); + + if (object.type == nullptr || object.data == nullptr) { + return nullptr; + } + + return (Object*)object.data; } } // namespace blender diff --git a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.h b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.h index d149bdae..0b7a358f 100644 --- a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.h +++ b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.h @@ -22,7 +22,7 @@ namespace blender void object_instances_begin(CollectionPropertyIterator* it, Depsgraph* depsgrah); void object_instances_end(CollectionPropertyIterator* it); void object_instances_next(CollectionPropertyIterator* it); - mu::float4x4* object_instances_get(CollectionPropertyIterator* it); + Object* object_instances_get(CollectionPropertyIterator* it); }; diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp index c374a401..3d6204c8 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp @@ -65,6 +65,8 @@ extern FunctionRNA* BlenderPyContext_depsgraph_update; extern PropertyRNA* BlenderPyContext_depsgraph_object_instances; +extern PropertyRNA* BlenderPyContext_depsgraph_instance_object; + bool ready() { return g_context != nullptr; @@ -205,6 +207,13 @@ void setup(py::object bpy_context) } } } + else if (match_type("DepsgraphObjectInstance")) { + each_prop{ + if (match_prop("instance_object")) { + BlenderPyContext_depsgraph_instance_object = prop; + } + } + } } #undef each_iprop #undef each_nprop diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index c750b4ce..82d2a979 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -645,15 +645,21 @@ ms::MeshPtr msblenContext::exportMesh(const Object *src) Depsgraph* depsgraph = blContext.evaluated_depsgraph_get(); bobj = (Object*)bl::BlenderPyID(bobj).evaluated_get(depsgraph); - CollectionPropertyIterator* beginIt; - CollectionPropertyIterator* nextIt; - CollectionPropertyIterator* endIt; - - blContext.object_instances_begin(beginIt, depsgraph); - blContext.object_instances_end(endIt); - for (nextIt = beginIt; nextIt != endIt; blContext.object_instances_next(nextIt)) { - auto matrix = blContext.object_instances_get(nextIt); + CollectionPropertyIterator it; + + blContext.object_instances_begin(&it, depsgraph); + auto counter = 0; + for (; it.valid; blContext.object_instances_next(&it)) { + auto instance_object = blContext.object_instances_get(&it); + if (instance_object == nullptr) { + continue; + } + + + + counter++; } + blContext.object_instances_end(&it); } if (Mesh *tmp = bobj.to_mesh()) { data = tmp; From ecc2693412cf7f5dbac77153f716cee3106ae7ae Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Thu, 3 Feb 2022 17:35:41 +0000 Subject: [PATCH 03/67] Filtering out non meshes and non instances --- .../BlenderPyObjects/BlenderPyContext.cpp | 18 ++++++++++++++---- .../BlenderPyObjects/BlenderPyContext.h | 6 +++++- .../Src/MeshSyncClientBlender/msblenBinder.cpp | 5 +++++ .../MeshSyncClientBlender/msblenContext.cpp | 13 ++++++++++++- 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp index 7586f141..95befbf5 100644 --- a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp @@ -13,6 +13,7 @@ FunctionRNA* BlenderPyContext_evaluated_depsgraph_get = nullptr; FunctionRNA* BlenderPyContext_depsgraph_update = nullptr; PropertyRNA* BlenderPyContext_depsgraph_object_instances = nullptr; PropertyRNA* BlenderPyContext_depsgraph_instance_object = nullptr; +PropertyRNA* BlenderPyContext_depsgraph_is_instance = nullptr; @@ -60,13 +61,15 @@ void BlenderPyContext::object_instances_next(CollectionPropertyIterator * it){ cprop->next(it); } -Object* BlenderPyContext::object_instances_get(CollectionPropertyIterator* it) { +PointerRNA BlenderPyContext::object_instances_get(CollectionPropertyIterator* it) { - auto collectionProp = (CollectionPropertyRNA*)BlenderPyContext_depsgraph_object_instances; + return collectionProp->get(it); + +} + +Object* BlenderPyContext::instance_object_get(PointerRNA instance) { auto objectInstanceProp = (PointerPropertyRNA*)BlenderPyContext_depsgraph_instance_object; - - auto instance = collectionProp->get(it); auto object = objectInstanceProp->get(&instance); if (object.type == nullptr || object.data == nullptr) { @@ -76,4 +79,11 @@ Object* BlenderPyContext::object_instances_get(CollectionPropertyIterator* it) { return (Object*)object.data; } + + +bool BlenderPyContext::object_instances_is_instance(PointerRNA object) { + auto booleanProp = (BoolPropertyRNA*)BlenderPyContext_depsgraph_is_instance; + return booleanProp->get(&object); +} + } // namespace blender diff --git a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.h b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.h index 0b7a358f..1eb41b9c 100644 --- a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.h +++ b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.h @@ -22,7 +22,11 @@ namespace blender void object_instances_begin(CollectionPropertyIterator* it, Depsgraph* depsgrah); void object_instances_end(CollectionPropertyIterator* it); void object_instances_next(CollectionPropertyIterator* it); - Object* object_instances_get(CollectionPropertyIterator* it); + PointerRNA object_instances_get(CollectionPropertyIterator* it); + + + Object* instance_object_get(PointerRNA instance); + bool BlenderPyContext::object_instances_is_instance(PointerRNA instance); }; diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp index 3d6204c8..df489800 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp @@ -66,6 +66,7 @@ extern FunctionRNA* BlenderPyContext_depsgraph_update; extern PropertyRNA* BlenderPyContext_depsgraph_object_instances; extern PropertyRNA* BlenderPyContext_depsgraph_instance_object; +extern PropertyRNA* BlenderPyContext_depsgraph_is_instance; bool ready() { @@ -212,6 +213,10 @@ void setup(py::object bpy_context) if (match_prop("instance_object")) { BlenderPyContext_depsgraph_instance_object = prop; } + + if (match_prop("is_instance")) { + BlenderPyContext_depsgraph_is_instance = prop; + } } } } diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index 82d2a979..1da58f1e 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -645,17 +645,28 @@ ms::MeshPtr msblenContext::exportMesh(const Object *src) Depsgraph* depsgraph = blContext.evaluated_depsgraph_get(); bobj = (Object*)bl::BlenderPyID(bobj).evaluated_get(depsgraph); + // Iterate over the object instances collection CollectionPropertyIterator it; blContext.object_instances_begin(&it, depsgraph); auto counter = 0; for (; it.valid; blContext.object_instances_next(&it)) { - auto instance_object = blContext.object_instances_get(&it); + auto instance = blContext.object_instances_get(&it); + auto instance_object = blContext.instance_object_get(instance); + + // if the object is null, skip if (instance_object == nullptr) { continue; } + // if the object is not a mesh object, skip + if (instance_object->type != OB_MESH) { + continue; + } + if (!blContext.object_instances_is_instance(instance)) { + continue; + } counter++; } From 19225c42141b697d09f3bee49b7370dcbfee26bb Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Fri, 4 Feb 2022 17:07:48 +0000 Subject: [PATCH 04/67] Created function for extracting instancing info, added code for storing instancing info in mesh transform --- .../MeshSyncClientBlender/msblenContext.cpp | 120 ++++++++++++++---- .../Src/MeshSyncClientBlender/msblenContext.h | 7 + 2 files changed, 100 insertions(+), 27 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index 1da58f1e..153c575a 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -644,33 +644,6 @@ ms::MeshPtr msblenContext::exportMesh(const Object *src) auto blContext = bl::BlenderPyContext::get(); Depsgraph* depsgraph = blContext.evaluated_depsgraph_get(); bobj = (Object*)bl::BlenderPyID(bobj).evaluated_get(depsgraph); - - // Iterate over the object instances collection - CollectionPropertyIterator it; - - blContext.object_instances_begin(&it, depsgraph); - auto counter = 0; - for (; it.valid; blContext.object_instances_next(&it)) { - auto instance = blContext.object_instances_get(&it); - auto instance_object = blContext.instance_object_get(instance); - - // if the object is null, skip - if (instance_object == nullptr) { - continue; - } - - // if the object is not a mesh object, skip - if (instance_object->type != OB_MESH) { - continue; - } - - if (!blContext.object_instances_is_instance(instance)) { - continue; - } - - counter++; - } - blContext.object_instances_end(&it); } if (Mesh *tmp = bobj.to_mesh()) { data = tmp; @@ -691,6 +664,25 @@ ms::MeshPtr msblenContext::exportMesh(const Object *src) auto task = [this, ret, src, data]() { auto& dst = *ret; doExtractMeshData(dst, src, data, dst.world_matrix); + + auto name = src->id.name; + std::string nameMesh; + dst.getName(nameMesh); + + // if modifier baking is on and there are instances for this mesh + if (m_settings.BakeModifiers && + object_instances.find(name) != object_instances.end()) { + + /// Add mesh instances as a user property + ms::Variant instances; + instances.name = "instances"; + instances.type = ms::Variant::Type::Float4x4; + auto matrices = object_instances[name]; + instances.set(matrices.data(), matrices.size()); + + dst.addUserProperty(std::move(instances)); + } + m_entity_manager.add(ret); }; @@ -1375,6 +1367,10 @@ bool msblenContext::sendObjects(MeshSyncClient::ObjectScope scope, bool dirty_al if (m_settings.sync_meshes) RegisterSceneMaterials(); + if (!extractObjectInstances()) { + return false; + } + if (scope == MeshSyncClient::ObjectScope::Updated) { bl::BData bpy_data = bl::BData(bl::BlenderPyContext::get().data()); if (!bpy_data.objects_is_updated()) @@ -1396,10 +1392,80 @@ bool msblenContext::sendObjects(MeshSyncClient::ObjectScope scope, bool dirty_al eraseStaleObjects(); } + //TODO-Sean Dillon: cleanup object instances array + // How to know when the async mesh export has finished? + WaitAndKickAsyncExport(); return true; } +bool msblenContext::extractObjectInstances() { + + using namespace std; + using namespace mu; + + object_instances.clear(); + + // Geometry nodes are modifiers, if bake is off, send nothing + if (!m_settings.BakeModifiers) { + return true; + } + + // BlenderPyContext is an interface between depsgraph operations and anything that interacts with it + auto blContext = bl::BlenderPyContext::get(); + auto depsgraph = blContext.evaluated_depsgraph_get(); + + // Iterate over the object instances collection of depsgraph + CollectionPropertyIterator it; + + blContext.object_instances_begin(&it, depsgraph); + + for (; it.valid; blContext.object_instances_next(&it)) { + // Get the instance as a Pointer RNA. This is not converted to an object yet + auto instance = blContext.object_instances_get(&it); + + // Convert the instance to an object + auto instance_object = blContext.instance_object_get(instance); + + // If the object is null, skip + if (instance_object == nullptr) + continue; + + if (!is_mesh(instance_object)) + continue; + + // if the object is not an instance, skip + if (!blContext.object_instances_is_instance(instance)) + continue; + + // If the object data is null, skip + auto data = (ID*)instance_object->data; + if (data == nullptr) + continue; + + // If the object has a mesh parent, skip. + // This is because need to capture only the mesh object parent. + // The transform relative to the parent is captured by the local matrix of the object. + auto parent = instance_object->parent; + if (parent != nullptr && is_mesh(parent)) + continue; + + auto name = instance_object->id.name; + if (name != nullptr) { + if (object_instances.find(name) == object_instances.end()) { + matrix_vector v; + object_instances.insert(move(pair(name, move(v)))); + } + + auto world_matrix = getWorldMatrix(instance_object); + object_instances[name].push_back(move(world_matrix)); + } + } + + // Cleanup resources + blContext.object_instances_end(&it); +} + bool msblenContext::sendAnimations(MeshSyncClient::ObjectScope scope) { if (!prepare() || m_sender.isExporting() || m_ignore_events) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h index b674ce3d..4d55484c 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h @@ -45,6 +45,8 @@ class msblenContext { bool sendAnimations(MeshSyncClient::ObjectScope scope); bool ExportCache(const std::string& path, const BlenderCacheSettings& cache_settings); + bool extractObjectInstances(); + void flushPendingList(); private: @@ -162,6 +164,11 @@ class msblenContext { void WaitAndKickAsyncExport(); private: + + typedef std::vector matrix_vector; + typedef std::unordered_map object_instances_t; + object_instances_t object_instances; + BlenderSyncSettings m_settings; BlenderCacheSettings m_cache_settings; std::set m_pending; From 9da1b701c4afd63417514d8151d4cd5f37eeb3bf Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Mon, 7 Feb 2022 18:48:12 +0000 Subject: [PATCH 05/67] Blender to Unity matrix corrections --- .../BlenderPyObjects/BlenderPyContext.cpp | 15 +++++++ .../BlenderPyObjects/BlenderPyContext.h | 5 ++- .../MeshSyncClientBlender/msblenBinder.cpp | 8 ++++ .../MeshSyncClientBlender/msblenContext.cpp | 45 +++++++++++-------- 4 files changed, 53 insertions(+), 20 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp index 95befbf5..ad0cb8bf 100644 --- a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp @@ -14,6 +14,8 @@ FunctionRNA* BlenderPyContext_depsgraph_update = nullptr; PropertyRNA* BlenderPyContext_depsgraph_object_instances = nullptr; PropertyRNA* BlenderPyContext_depsgraph_instance_object = nullptr; PropertyRNA* BlenderPyContext_depsgraph_is_instance = nullptr; +PropertyRNA* BlenderPyContext_depsgraph_world_matrix = nullptr; +PropertyRNA* BlenderPyContext_depsgraph_parent = nullptr; @@ -86,4 +88,17 @@ bool BlenderPyContext::object_instances_is_instance(PointerRNA object) { return booleanProp->get(&object); } +void BlenderPyContext::world_matrix_get(PointerRNA* instance, mu::float4x4* result) +{ + auto floatProp = (FloatPropertyRNA*)BlenderPyContext_depsgraph_world_matrix; + floatProp->getarray(instance, &(result->m[0][0])); // Sean Dillon - TODO: is the matrix object memory guaranteed to be aligned? +} + +Object* BlenderPyContext::instance_parent_get(PointerRNA* instance) { + auto pointerProp = (PointerPropertyRNA*)BlenderPyContext_depsgraph_parent; + auto parent = pointerProp->get(instance); + + return (Object*)parent.data; +} + } // namespace blender diff --git a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.h b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.h index 1eb41b9c..2d527e63 100644 --- a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.h +++ b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.h @@ -26,8 +26,9 @@ namespace blender Object* instance_object_get(PointerRNA instance); - bool BlenderPyContext::object_instances_is_instance(PointerRNA instance); - + bool object_instances_is_instance(PointerRNA instance); + void world_matrix_get(PointerRNA* instance, mu::float4x4* world_matrix); + Object* instance_parent_get(PointerRNA* instance); }; } // namespace blender diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp index df489800..ef62e746 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp @@ -67,6 +67,8 @@ extern PropertyRNA* BlenderPyContext_depsgraph_object_instances; extern PropertyRNA* BlenderPyContext_depsgraph_instance_object; extern PropertyRNA* BlenderPyContext_depsgraph_is_instance; +extern PropertyRNA* BlenderPyContext_depsgraph_world_matrix; +extern PropertyRNA* BlenderPyContext_depsgraph_parent; bool ready() { @@ -217,6 +219,12 @@ void setup(py::object bpy_context) if (match_prop("is_instance")) { BlenderPyContext_depsgraph_is_instance = prop; } + if (match_prop("matrix_world")) { + BlenderPyContext_depsgraph_world_matrix = prop; + } + if (match_prop("parent")) { + BlenderPyContext_depsgraph_parent = prop; + } } } } diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index 153c575a..7eea67b4 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -1393,7 +1393,7 @@ bool msblenContext::sendObjects(MeshSyncClient::ObjectScope scope, bool dirty_al } //TODO-Sean Dillon: cleanup object instances array - // How to know when the async mesh export has finished? + // How to know when the async mesh export has finished? WhenAll task? WaitAndKickAsyncExport(); return true; @@ -1421,44 +1421,53 @@ bool msblenContext::extractObjectInstances() { blContext.object_instances_begin(&it, depsgraph); for (; it.valid; blContext.object_instances_next(&it)) { - // Get the instance as a Pointer RNA. This is not converted to an object yet + // Get the instance as a Pointer RNA. auto instance = blContext.object_instances_get(&it); - // Convert the instance to an object - auto instance_object = blContext.instance_object_get(instance); + // Get the object that the instance refers to + auto object = blContext.instance_object_get(instance); // If the object is null, skip - if (instance_object == nullptr) + if (object == nullptr) continue; - if (!is_mesh(instance_object)) + // if the object is not a mesh, skip + if (!is_mesh(object)) continue; - // if the object is not an instance, skip + // if the instance is not an instance, skip if (!blContext.object_instances_is_instance(instance)) continue; // If the object data is null, skip - auto data = (ID*)instance_object->data; + auto data = (ID*)object->data; if (data == nullptr) continue; - // If the object has a mesh parent, skip. - // This is because need to capture only the mesh object parent. - // The transform relative to the parent is captured by the local matrix of the object. - auto parent = instance_object->parent; - if (parent != nullptr && is_mesh(parent)) - continue; - - auto name = instance_object->id.name; + auto name = object->id.name; if (name != nullptr) { if (object_instances.find(name) == object_instances.end()) { matrix_vector v; object_instances.insert(move(pair(name, move(v)))); } - auto world_matrix = getWorldMatrix(instance_object); - object_instances[name].push_back(move(world_matrix)); + auto world_matrix = float4x4(); + blContext.world_matrix_get(&instance, &world_matrix); + + auto rotation = rotate_x(-90 * DegToRad); + auto rotation180 = rotate_z(180 * DegToRad); + auto scale = float3::one(); + scale.x = -1; + auto result = + to_mat4x4(rotation) * + scale44(scale)* + world_matrix * + to_mat4x4(rotation) * + to_mat4x4(rotation180) * + scale44(scale); + + + object_instances[name].push_back(move(result)); } } From d966266cdaa0849c269bdbc88e2a110f81d657e5 Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Tue, 8 Feb 2022 18:38:30 +0000 Subject: [PATCH 06/67] Instances are associated to the name of the mesh, not the name of the parent object --- .../BlenderPyObjects/BlenderPyContext.cpp | 12 ++++ .../BlenderPyObjects/BlenderPyContext.h | 1 + .../MeshSyncClientBlender/msblenBinder.cpp | 5 ++ .../MeshSyncClientBlender/msblenContext.cpp | 72 ++++++++++++------- 4 files changed, 64 insertions(+), 26 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp index ad0cb8bf..ed76df6a 100644 --- a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp @@ -16,6 +16,7 @@ PropertyRNA* BlenderPyContext_depsgraph_instance_object = nullptr; PropertyRNA* BlenderPyContext_depsgraph_is_instance = nullptr; PropertyRNA* BlenderPyContext_depsgraph_world_matrix = nullptr; PropertyRNA* BlenderPyContext_depsgraph_parent = nullptr; +PropertyRNA* BlenderPyContext_depsgraph_object = nullptr; @@ -101,4 +102,15 @@ Object* BlenderPyContext::instance_parent_get(PointerRNA* instance) { return (Object*)parent.data; } +Object* BlenderPyContext::object_get(PointerRNA instance) { + auto objectInstanceProp = (PointerPropertyRNA*)BlenderPyContext_depsgraph_object; + auto object = objectInstanceProp->get(&instance); + + if (object.type == nullptr || object.data == nullptr) { + return nullptr; + } + + return (Object*)object.data; +} + } // namespace blender diff --git a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.h b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.h index 2d527e63..a4623beb 100644 --- a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.h +++ b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.h @@ -29,6 +29,7 @@ namespace blender bool object_instances_is_instance(PointerRNA instance); void world_matrix_get(PointerRNA* instance, mu::float4x4* world_matrix); Object* instance_parent_get(PointerRNA* instance); + Object* object_get(PointerRNA instance); }; } // namespace blender diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp index ef62e746..b0461e18 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp @@ -70,6 +70,8 @@ extern PropertyRNA* BlenderPyContext_depsgraph_is_instance; extern PropertyRNA* BlenderPyContext_depsgraph_world_matrix; extern PropertyRNA* BlenderPyContext_depsgraph_parent; +extern PropertyRNA* BlenderPyContext_depsgraph_object; + bool ready() { return g_context != nullptr; @@ -225,6 +227,9 @@ void setup(py::object bpy_context) if (match_prop("parent")) { BlenderPyContext_depsgraph_parent = prop; } + if (match_prop("object")) { + BlenderPyContext_depsgraph_object = prop; + } } } } diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index 0f17fcdd..1ce6454d 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -713,15 +713,21 @@ ms::MeshPtr msblenContext::exportMesh(const Object *src) std::string nameMesh; dst.getName(nameMesh); + auto data = (ID*)src->data; + auto meshName = ""; + if (data != nullptr) { + meshName = data->name; + } + // if modifier baking is on and there are instances for this mesh if (m_settings.BakeModifiers && - object_instances.find(name) != object_instances.end()) { + object_instances.find(meshName) != object_instances.end()) { /// Add mesh instances as a user property ms::Variant instances; instances.name = "instances"; instances.type = ms::Variant::Type::Float4x4; - auto matrices = object_instances[name]; + auto matrices = object_instances[meshName]; instances.set(matrices.data(), matrices.size()); dst.addUserProperty(std::move(instances)); @@ -1469,14 +1475,14 @@ bool msblenContext::extractObjectInstances() { auto instance = blContext.object_instances_get(&it); // Get the object that the instance refers to - auto object = blContext.instance_object_get(instance); + auto instance_object = blContext.instance_object_get(instance); // If the object is null, skip - if (object == nullptr) + if (instance_object == nullptr) continue; // if the object is not a mesh, skip - if (!is_mesh(object)) + if (!is_mesh(instance_object)) continue; // if the instance is not an instance, skip @@ -1484,39 +1490,53 @@ bool msblenContext::extractObjectInstances() { continue; // If the object data is null, skip - auto data = (ID*)object->data; + auto data = (ID*)instance_object->data; if (data == nullptr) continue; - auto name = object->id.name; - if (name != nullptr) { - if (object_instances.find(name) == object_instances.end()) { - matrix_vector v; - object_instances.insert(move(pair(name, move(v)))); - } + auto parent = blContext.instance_parent_get(&instance); + if (parent == nullptr) + continue; - auto world_matrix = float4x4(); - blContext.world_matrix_get(&instance, &world_matrix); + auto object = blContext.object_get(instance); + auto object_name = object->id.name; - auto rotation = rotate_x(-90 * DegToRad); - auto rotation180 = rotate_z(180 * DegToRad); - auto scale = float3::one(); - scale.x = -1; - auto result = - to_mat4x4(rotation) * - scale44(scale)* - world_matrix * - to_mat4x4(rotation) * - to_mat4x4(rotation180) * - scale44(scale); + auto object_data = (ID*)object->data; + if (object_data == nullptr) + continue; + auto name = object_data->name; - object_instances[name].push_back(move(result)); + if (name == nullptr) + continue; + + if (object_instances.find(name) == object_instances.end()) { + matrix_vector v; + object_instances.insert(move(pair(name, move(v)))); } + + auto world_matrix = float4x4(); + blContext.world_matrix_get(&instance, &world_matrix); + + auto rotation = rotate_x(-90 * DegToRad); + auto rotation180 = rotate_z(180 * DegToRad); + auto scale = float3::one(); + scale.x = -1; + auto result = + to_mat4x4(rotation) * + scale44(scale)* + world_matrix * + to_mat4x4(rotation) * + to_mat4x4(rotation180) * + scale44(scale); + + object_instances[name].push_back(move(result)); } // Cleanup resources blContext.object_instances_end(&it); + + return true; } bool msblenContext::sendAnimations(MeshSyncClient::ObjectScope scope) From bf50aded6938505e6b890c96614cb1baf688d291 Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Wed, 9 Feb 2022 16:40:58 +0000 Subject: [PATCH 07/67] Extract Geometry node tree input parameters and set them as variant data on the object with the geometry node modifier --- Plugins~/CMakeLists.txt | 2 +- .../BlenderPyObjects/BlenderPyNodeTree.cpp | 30 +++++ .../BlenderPyObjects/BlenderPyNodeTree.h | 19 +++ .../MeshSyncClientBlender/msblenBinder.cpp | 9 ++ .../MeshSyncClientBlender/msblenContext.cpp | 118 +++++++++++++++--- 5 files changed, 158 insertions(+), 20 deletions(-) create mode 100644 Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyNodeTree.cpp create mode 100644 Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyNodeTree.h diff --git a/Plugins~/CMakeLists.txt b/Plugins~/CMakeLists.txt index 768dd78e..b0fa3a5a 100644 --- a/Plugins~/CMakeLists.txt +++ b/Plugins~/CMakeLists.txt @@ -53,7 +53,7 @@ include(UnityPackage) setup_unity_package_version() add_definitions(-DMESHSYNC_DCC_PLUGIN_VER="${UNITY_PACKAGE_VERSION}") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") # Force Unicode character set add_definitions(-DUNICODE -D_UNICODE) diff --git a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyNodeTree.cpp b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyNodeTree.cpp new file mode 100644 index 00000000..27596c90 --- /dev/null +++ b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyNodeTree.cpp @@ -0,0 +1,30 @@ +#include "pch.h" +#include "BlenderPyNodeTree.h" + +namespace blender { + PropertyRNA* BlenderPyNodeTree_inputs = nullptr; + + void blender::BlenderPyNodeTree::inputs_begin(CollectionPropertyIterator* it, bNodeTree* nodeTree) + { + auto cprop = (CollectionPropertyRNA*)BlenderPyNodeTree_inputs; + PointerRNA rna; + rna.data = nodeTree; + cprop->begin(it, &rna); + } + void BlenderPyNodeTree::inputs_next(CollectionPropertyIterator* it) + { + auto cprop = (CollectionPropertyRNA*)BlenderPyNodeTree_inputs; + cprop->next(it); + + } + void BlenderPyNodeTree::inputs_end(CollectionPropertyIterator* it) + { + auto cprop = (CollectionPropertyRNA*)BlenderPyNodeTree_inputs; + cprop->end(it); + } + PointerRNA BlenderPyNodeTree::inputs_get(CollectionPropertyIterator* it) + { + auto cprop = (CollectionPropertyRNA*)BlenderPyNodeTree_inputs; + return cprop->get(it); + } +} diff --git a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyNodeTree.h b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyNodeTree.h new file mode 100644 index 00000000..eef0d842 --- /dev/null +++ b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyNodeTree.h @@ -0,0 +1,19 @@ +#pragma once + +#include //bContext +#include "MeshUtils/muMath.h" +#include +#include + +namespace blender +{ + class BlenderPyNodeTree + { + public: + void inputs_begin(CollectionPropertyIterator* it, bNodeTree* nodeTree); + void inputs_next(CollectionPropertyIterator* it); + void inputs_end(CollectionPropertyIterator* it); + PointerRNA inputs_get(CollectionPropertyIterator* it); + }; + +} // namespace blender diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp index b0461e18..06a86bad 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp @@ -72,6 +72,8 @@ extern PropertyRNA* BlenderPyContext_depsgraph_parent; extern PropertyRNA* BlenderPyContext_depsgraph_object; +extern PropertyRNA* BlenderPyNodeTree_inputs; + bool ready() { return g_context != nullptr; @@ -232,6 +234,13 @@ void setup(py::object bpy_context) } } } + else if (match_type("NodeTree")) { + each_prop{ + if (match_prop("inputs")) { + BlenderPyNodeTree_inputs = prop; + } + } + } } #undef each_iprop #undef each_nprop diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index 1ce6454d..fd02879b 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -15,6 +15,9 @@ #include "MeshSyncClient/SceneCacheUtility.h" #include "BlenderPyObjects/BlenderPyScene.h" //BlenderPyScene +#include "BlenderPyObjects/BlenderPyNodeTree.h" +#include "DNA_node_types.h" +#include @@ -646,6 +649,53 @@ ms::LightPtr msblenContext::exportLight(const Object *src) return ret; } +bool addModifierProperties(ms::Mesh* mesh, ModifierData* modifier, std::stringstream& names) +{ + if (modifier->type != ModifierType::eModifierType_Nodes) { + return false; + } + + auto blNodeTree = bl::BlenderPyNodeTree(); + auto nodeModifier = (NodesModifierData*)modifier; + auto group = nodeModifier->node_group; + CollectionPropertyIterator it; + blNodeTree.inputs_begin(&it, group); + for (; it.valid; blNodeTree.inputs_next(&it)) { + auto input = blNodeTree.inputs_get(&it); + auto socket = (bNodeSocket*)input.data; + auto socket_type = socket->type; + + auto variant = ms::Variant(); + variant.name = socket->name; + + if (socket_type == eNodeSocketDatatype::SOCK_GEOMETRY) { + continue; + } + if (socket_type == eNodeSocketDatatype::SOCK_FLOAT) { + variant.type = ms::Variant::Type::Float; + auto defaultValue = (bNodeSocketValueFloat*)socket->default_value; + variant.set(std::move(defaultValue->value)); + } + if (socket_type == eNodeSocketDatatype::SOCK_INT) { + variant.type = ms::Variant::Type::Int; + auto defaultValue = (bNodeSocketValueInt*)socket->default_value; + variant.set(std::move(defaultValue->value)); + } + if (socket_type == eNodeSocketDatatype::SOCK_VECTOR) { + variant.type = ms::Variant::Type::Float3; + auto defaultValue = (bNodeSocketValueVector*)socket->default_value; + float* v = new float[3]; + copy_v3_v3(v, defaultValue->value); + variant.set(v, 3); + } + + names << variant.name<addUserProperty(std::move(variant)); + } + blNodeTree.inputs_end(&it); + return true; +} + ms::MeshPtr msblenContext::exportMesh(const Object *src) { // ignore particles @@ -709,28 +759,56 @@ ms::MeshPtr msblenContext::exportMesh(const Object *src) auto& dst = *ret; doExtractMeshData(dst, src, data, dst.world_matrix); - auto name = src->id.name; - std::string nameMesh; - dst.getName(nameMesh); - - auto data = (ID*)src->data; - auto meshName = ""; - if (data != nullptr) { - meshName = data->name; - } + // if modifier baking is on + if (m_settings.BakeModifiers){ + + auto data = (ID*)src->data; + auto meshName = ""; + + if (data != nullptr) { + meshName = data->name; + } + // If there are instances if the mesh mesh + if (object_instances.find(meshName) != object_instances.end()) { + + /// Add mesh instances as a user property + ms::Variant instances; + instances.name = "instances"; + instances.type = ms::Variant::Type::Float4x4; + auto matrices = object_instances[meshName]; + instances.set(matrices.data(), matrices.size()); + + dst.addUserProperty(std::move(instances)); + } + + + // Add the geometry node properties as a user property - // if modifier baking is on and there are instances for this mesh - if (m_settings.BakeModifiers && - object_instances.find(meshName) != object_instances.end()) { + // Create a manifest with the names of the modifiers + std::stringstream modifierNames; + bl::BObject bObj(src); + auto modifiers = bObj.modifiers(); + for (auto it = modifiers.begin(); it != modifiers.end();++it) { - /// Add mesh instances as a user property - ms::Variant instances; - instances.name = "instances"; - instances.type = ms::Variant::Type::Float4x4; - auto matrices = object_instances[meshName]; - instances.set(matrices.data(), matrices.size()); + auto modifier = *it; - dst.addUserProperty(std::move(instances)); + // Add each modifier as a variant + addModifierProperties(&dst, modifier, modifierNames); + } + ms::Variant modifierManifest; + modifierManifest.name = "modifiers"; + modifierManifest.type = ms::Variant::Type::String; + + auto streamString = modifierNames.str(); + if (!streamString.empty()) { + + auto names = new char[streamString.length()]; + + streamString.copy(names, streamString.length(), 0); + + modifierManifest.set(names, streamString.length()); + dst.addUserProperty(std::move(modifierManifest)); + } } m_entity_manager.add(ret); @@ -744,6 +822,8 @@ ms::MeshPtr msblenContext::exportMesh(const Object *src) return ret; } + + void msblenContext::doExtractMeshData(ms::Mesh& dst, const Object *obj, Mesh *data, mu::float4x4 world) { if (m_settings.sync_meshes) { From 3144c4bf256ed76ee171699c2c34fd1d997827d6 Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Thu, 10 Feb 2022 11:24:26 +0000 Subject: [PATCH 08/67] move names when setting variant --- Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index fd02879b..7ec6a9ab 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -806,7 +806,7 @@ ms::MeshPtr msblenContext::exportMesh(const Object *src) streamString.copy(names, streamString.length(), 0); - modifierManifest.set(names, streamString.length()); + modifierManifest.set(std::move(names), streamString.length()); dst.addUserProperty(std::move(modifierManifest)); } } From 4f1b0c212f247ba89014bb85465ad771b07111d7 Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Thu, 10 Feb 2022 17:49:14 +0000 Subject: [PATCH 09/67] macrs for compiling object instances code only for blender 3.0.0 and above. Better resource lifetime using exporter events --- .../MeshSyncClientBlender/msblenContext.cpp | 75 ++++++++++++------- .../Src/MeshSyncClientBlender/msblenContext.h | 10 ++- 2 files changed, 53 insertions(+), 32 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index 1ce6454d..a2a728da 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -709,29 +709,10 @@ ms::MeshPtr msblenContext::exportMesh(const Object *src) auto& dst = *ret; doExtractMeshData(dst, src, data, dst.world_matrix); - auto name = src->id.name; - std::string nameMesh; - dst.getName(nameMesh); - - auto data = (ID*)src->data; - auto meshName = ""; - if (data != nullptr) { - meshName = data->name; - } - - // if modifier baking is on and there are instances for this mesh - if (m_settings.BakeModifiers && - object_instances.find(meshName) != object_instances.end()) { - /// Add mesh instances as a user property - ms::Variant instances; - instances.name = "instances"; - instances.type = ms::Variant::Type::Float4x4; - auto matrices = object_instances[meshName]; - instances.set(matrices.data(), matrices.size()); - - dst.addUserProperty(std::move(instances)); - } +#if BLENDER_VERSION >= 300 + addInstanceData(src, dst); +#endif m_entity_manager.add(ret); }; @@ -744,6 +725,32 @@ ms::MeshPtr msblenContext::exportMesh(const Object *src) return ret; } +#if BLENDER_VERSION >= 300 +void msblenContext::addInstanceData(const Object* src, ms::Mesh& dst) +{ + if (!m_settings.BakeModifiers) + return; + + auto data = (ID*)src->data; + auto meshName = ""; + if (data != nullptr) { + meshName = data->name; + } + + if (m_object_instances.find(meshName) == m_object_instances.end()) + return; + + /// Add mesh instances as a user property + ms::Variant instances; + instances.name = "instances"; + instances.type = ms::Variant::Type::Float4x4; + auto matrices = m_object_instances[meshName]; + instances.set(matrices.data(), matrices.size()); + + dst.addUserProperty(std::move(instances)); +} +#endif + void msblenContext::doExtractMeshData(ms::Mesh& dst, const Object *obj, Mesh *data, mu::float4x4 world) { if (m_settings.sync_meshes) { @@ -1417,9 +1424,11 @@ bool msblenContext::sendObjects(MeshSyncClient::ObjectScope scope, bool dirty_al if (m_settings.sync_meshes) RegisterSceneMaterials(); +#if BLENDER_VERSION >= 300 if (!extractObjectInstances()) { return false; } +#endif if (scope == MeshSyncClient::ObjectScope::Updated) { bl::BData bpy_data = bl::BData(bl::BlenderPyContext::get().data()); @@ -1442,19 +1451,17 @@ bool msblenContext::sendObjects(MeshSyncClient::ObjectScope scope, bool dirty_al eraseStaleObjects(); } - //TODO-Sean Dillon: cleanup object instances array - // How to know when the async mesh export has finished? WhenAll task? - WaitAndKickAsyncExport(); return true; } +#if BLENDER_VERSION >= 300 bool msblenContext::extractObjectInstances() { using namespace std; using namespace mu; - object_instances.clear(); + m_object_instances.clear(); // Geometry nodes are modifiers, if bake is off, send nothing if (!m_settings.BakeModifiers) { @@ -1510,9 +1517,9 @@ bool msblenContext::extractObjectInstances() { if (name == nullptr) continue; - if (object_instances.find(name) == object_instances.end()) { + if (m_object_instances.find(name) == m_object_instances.end()) { matrix_vector v; - object_instances.insert(move(pair(name, move(v)))); + m_object_instances.insert(move(pair(name, move(v)))); } auto world_matrix = float4x4(); @@ -1530,7 +1537,7 @@ bool msblenContext::extractObjectInstances() { to_mat4x4(rotation180) * scale44(scale); - object_instances[name].push_back(move(result)); + m_object_instances[name].push_back(move(result)); } // Cleanup resources @@ -1538,6 +1545,7 @@ bool msblenContext::extractObjectInstances() { return true; } +#endif bool msblenContext::sendAnimations(MeshSyncClient::ObjectScope scope) { @@ -1757,5 +1765,14 @@ void msblenContext::WaitAndKickAsyncExport() m_entity_manager.clearDirtyFlags(); m_animations.clear(); }; + + exporter->on_complete = [this]() { + +#if BLENDER_VERSION >= 300 + m_object_instances.clear(); +#endif + + }; + exporter->kick(); } diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h index ca5a6fd4..60c386b4 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h @@ -45,8 +45,6 @@ class msblenContext { bool sendAnimations(MeshSyncClient::ObjectScope scope); bool ExportCache(const std::string& path, const BlenderCacheSettings& cache_settings); - bool extractObjectInstances(); - void flushPendingList(); private: @@ -163,15 +161,21 @@ class msblenContext { void extractLightAnimationData(ms::TransformAnimation& dst, void *obj); void extractMeshAnimationData(ms::TransformAnimation& dst, void *obj); +#if BLENDER_VERSION >= 300 + bool extractObjectInstances(); + void addInstanceData(const Object* src, ms::Mesh& dst); +#endif void DoExportSceneCache(const std::vector& nodes); void WaitAndKickAsyncExport(); private: +#if BLENDER_VERSION >= 300 typedef std::vector matrix_vector; typedef std::unordered_map object_instances_t; - object_instances_t object_instances; + object_instances_t m_object_instances; +#endif BlenderSyncSettings m_settings; BlenderCacheSettings m_cache_settings; From 0e5f180cec4b86b29a61eaff89ddc8a5eabbea1e Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Thu, 17 Feb 2022 10:18:52 +0000 Subject: [PATCH 10/67] Fix for cleaning instances correctly, get updates from depsgraph on any mode (auto or manual) --- Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp | 7 +++---- .../MeshSyncClientBlender/python/3.0.1/unity_mesh_sync.py | 5 +++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp index e257ea09..dc08d7e9 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp @@ -43,7 +43,7 @@ namespace blender { using namespace std; using namespace mu; - instances.clear(); + this->clearObjectInstances(); // BlenderPyContext is an interface between depsgraph operations and anything that interacts with it auto blContext = blender::BlenderPyContext::get(); @@ -100,9 +100,8 @@ namespace blender { void msblenGeometryNodes::clearObjectInstances() { - for (auto it = instances.begin(); it != instances.end(); it++) { - auto data = *it; - data.second.clear(); + for (auto &it :instances) { + it.second.clear(); } } diff --git a/Plugins~/Src/MeshSyncClientBlender/python/3.0.1/unity_mesh_sync.py b/Plugins~/Src/MeshSyncClientBlender/python/3.0.1/unity_mesh_sync.py index 5986f51b..7d7e3e49 100644 --- a/Plugins~/Src/MeshSyncClientBlender/python/3.0.1/unity_mesh_sync.py +++ b/Plugins~/Src/MeshSyncClientBlender/python/3.0.1/unity_mesh_sync.py @@ -25,6 +25,7 @@ class MESHSYNC_PT_Main(MESHSYNC_PT, bpy.types.Panel): def draw(self, context): pass + class MESHSYNC_PT_Server(MESHSYNC_PT, bpy.types.Panel): @@ -119,13 +120,11 @@ def invoke(self, context, event): return {'FINISHED'} MESHSYNC_OT_AutoSync._timer = context.window_manager.event_timer_add(1.0 / 3.0, window=context.window) context.window_manager.modal_handler_add(self) - bpy.app.handlers.depsgraph_update_post.append(on_depsgraph_update_post) return {'RUNNING_MODAL'} else: scene.meshsync_auto_sync = False context.window_manager.event_timer_remove(MESHSYNC_OT_AutoSync._timer) MESHSYNC_OT_AutoSync._timer = None - bpy.app.handlers.depsgraph_update_post.remove(on_depsgraph_update_post) return {'FINISHED'} def modal(self, context, event): @@ -305,6 +304,8 @@ def on_depsgraph_update_post(scene): msb_context.setup(bpy.context) msb_context.OnDepsgraphUpdatePost(graph) +bpy.app.handlers.depsgraph_update_post.append(on_depsgraph_update_post) + import atexit atexit.register(DestroyMeshSyncContext) From a3904ea2913d1ec5f99c027816f872b951c999c5 Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Thu, 17 Feb 2022 10:38:37 +0000 Subject: [PATCH 11/67] Support manual sync when loading new file --- .../Src/MeshSyncClientBlender/python/3.0.1/unity_mesh_sync.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Plugins~/Src/MeshSyncClientBlender/python/3.0.1/unity_mesh_sync.py b/Plugins~/Src/MeshSyncClientBlender/python/3.0.1/unity_mesh_sync.py index 7d7e3e49..c3be33ba 100644 --- a/Plugins~/Src/MeshSyncClientBlender/python/3.0.1/unity_mesh_sync.py +++ b/Plugins~/Src/MeshSyncClientBlender/python/3.0.1/unity_mesh_sync.py @@ -305,6 +305,7 @@ def on_depsgraph_update_post(scene): msb_context.OnDepsgraphUpdatePost(graph) bpy.app.handlers.depsgraph_update_post.append(on_depsgraph_update_post) +bpy.app.handlers.load_post.append(on_depsgraph_update_post) import atexit atexit.register(DestroyMeshSyncContext) From 0594b563b57af861d2dcdf7216e5787787d16fc5 Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Fri, 18 Feb 2022 19:07:06 +0000 Subject: [PATCH 12/67] Implemented instances manager on MeshSyncClient. Converted Geometry nodes class to a geometry nodes utility class --- .../MeshSyncClient/msInstancesManager.h | 38 ++++++++ .../Src/MeshSyncClient/msInstancesManager.cpp | 51 +++++++++++ .../MeshSyncClientBlender/msblenContext.cpp | 31 +++---- .../Src/MeshSyncClientBlender/msblenContext.h | 10 +-- .../msblenGeometryNodes.cpp | 90 ++++--------------- .../msblenGeometryNodes.h | 33 +++---- 6 files changed, 142 insertions(+), 111 deletions(-) create mode 100644 Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h create mode 100644 Plugins~/Src/MeshSyncClient/msInstancesManager.cpp diff --git a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h new file mode 100644 index 00000000..329c955c --- /dev/null +++ b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h @@ -0,0 +1,38 @@ +#pragma once + +#include "MeshSync/MeshSync.h" +#include "MeshSync/SceneGraph/msIdentifier.h" +#include + +#ifndef msRuntime + +msDeclClassPtr(InstanceInfo) + +namespace ms { + + class InstancesManager + { + public: + std::vector getAllInstances(); + std::vector getDirtyInstances(); + void clearDirtyFlags(); + void add(InstanceInfoPtr instanceInfo); + void clear(); + + void setAlwaysMarkDirty(bool alwaysDirty); + + private: + struct Record + { + bool dirty; + InstanceInfoPtr instances; + }; + + std::map m_records; + std::mutex m_mutex; + }; + + + +} // namespace ms +#endif // msRuntime diff --git a/Plugins~/Src/MeshSyncClient/msInstancesManager.cpp b/Plugins~/Src/MeshSyncClient/msInstancesManager.cpp new file mode 100644 index 00000000..388d4d17 --- /dev/null +++ b/Plugins~/Src/MeshSyncClient/msInstancesManager.cpp @@ -0,0 +1,51 @@ +#include "MeshSyncClient/msInstancesManager.h" +#include "pch.h" +#include "MeshSync/SceneGraph/msInstanceInfo.h" + +using namespace std; +namespace ms { + vector ms::InstancesManager::getAllInstances() + { + vector ret; + for (auto& v : m_records) + ret.push_back(v.second.instances); + return ret; + } + + vector InstancesManager::getDirtyInstances() + { + vector ret; + for (auto& p : m_records) { + Record& r = p.second; + if (r.dirty) { + ret.push_back(r.instances); + } + } + return ret; + } + + void InstancesManager::clearDirtyFlags() + { + for (auto& p : m_records) { + Record& r = p.second; + r.dirty = false; + } + } + + /// TODO - Make this thread safe + void InstancesManager::add(InstanceInfoPtr info) + { + auto& rec = m_records[info->path]; + rec.instances = info; + rec.dirty = true; + } + + void InstancesManager::clear() + { + m_records.clear(); + } + + void InstancesManager::setAlwaysMarkDirty(bool alwaysDirty) { + // For the moment, we always mark it as dirty, do nothing + } +} diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index 40700c9b..4ef4ea69 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -75,6 +75,7 @@ void msblenContext::Destroy() { m_texture_manager.clear(); m_material_manager.clear(); m_entity_manager.clear(); + m_instances_manager.clear(); } @@ -709,12 +710,6 @@ ms::MeshPtr msblenContext::exportMesh(const Object *src) } if (data) { - -#if BLENDER_VERSION >= 300 - // Inject instance info on the mesh - m_geometry_nodes.onMeshExport(src, dst); -#endif - auto task = [this, ret, src, data]() { auto& dst = *ret; doExtractMeshData(dst, src, data, dst.world_matrix); @@ -1607,7 +1602,7 @@ void msblenContext::WaitAndKickAsyncExport() using Exporter = ms::SceneExporter; Exporter *exporter = m_settings.ExportSceneCache ? (Exporter*)&m_cache_writer : (Exporter*)&m_sender; - + // kick async send exporter->on_prepare = [this, exporter]() { if (ms::AsyncSceneSender* sender = dynamic_cast(exporter)) { @@ -1626,6 +1621,7 @@ void msblenContext::WaitAndKickAsyncExport() t.materials = m_material_manager.getDirtyMaterials(); t.transforms = m_entity_manager.getDirtyTransforms(); t.geometries = m_entity_manager.getDirtyGeometries(); + t.instanceInfos = m_instances_manager.getDirtyInstances(); t.animations = m_animations; t.deleted_materials = m_material_manager.getDeleted(); @@ -1644,14 +1640,7 @@ void msblenContext::WaitAndKickAsyncExport() m_material_manager.clearDirtyFlags(); m_entity_manager.clearDirtyFlags(); m_animations.clear(); - }; - - exporter->on_complete = [this]() { - -#if BLENDER_VERSION >= 300 - m_geometry_nodes.onExportComplete(); -#endif - + m_instances_manager.clearDirtyFlags(); }; exporter->kick(); @@ -1665,9 +1654,17 @@ void msblenContext::WaitAndKickAsyncExport() /// void msblenContext::onDepsgraphUpdatedPost(Depsgraph* graph) { - + //TODO - Check thread safety #if BLENDER_VERSION >= 300 - m_geometry_nodes.onDepsgraphUpdatePost(graph); + auto func = [&](std::string str, std::vector mat){ + auto info = ms::InstanceInfo::create(); + info->path = str; + info->transforms = mat; + + m_instances_manager.add(info); + }; + + blender::GeometryNodesUtils::foreach_instance(func); #endif } diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h index 0b039ae5..f3f38d73 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h @@ -21,6 +21,8 @@ #include "MeshSyncClient/AsyncTasksController.h" #include "msblenGeometryNodes.h" +#include "MeshSyncClient/msInstancesManager.h" + class msblenContext; class msblenContext { @@ -187,16 +189,12 @@ class msblenContext { ms::AsyncSceneSender m_sender; ms::SceneCacheWriter m_cache_writer; + ms::InstancesManager m_instances_manager; + // animation export std::map m_anim_records; float m_anim_time = 0.0f; bool m_ignore_events = false; - - // geometry nodes -#if BLENDER_VERSION >= 300 - blender::msblenGeometryNodes m_geometry_nodes; -#endif - }; using msblenContextPtr = std::shared_ptr; #define msblenGetContext() msblenContext::getInstance() diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp index dc08d7e9..99e6bf97 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp @@ -11,14 +11,13 @@ using namespace mu; namespace blender { - // UTILS - +#if BLENDER_VERSION >= 300 /// /// Converts the world matrix from blender to Unity coordinate systems /// /// /// - float4x4& blenderToUnityWorldMatrix(float4x4& blenderMatrix) { + float4x4& GeometryNodesUtils::blenderToUnityWorldMatrix(float4x4& blenderMatrix) { auto rotation = rotate_x(-90 * DegToRad); auto rotation180 = rotate_z(180 * DegToRad); @@ -36,14 +35,9 @@ namespace blender { return move(result); } - // INSTANCES - - void msblenGeometryNodes::findObjectInstances() { - using namespace std; - using namespace mu; - - this->clearObjectInstances(); + void GeometryNodesUtils::foreach_instance(std::function f) + { // BlenderPyContext is an interface between depsgraph operations and anything that interacts with it auto blContext = blender::BlenderPyContext::get(); @@ -71,84 +65,34 @@ namespace blender { continue; auto object = blContext.object_get(instance); + auto object_name = object->id.name; - auto object_data = (ID*)object->data; - if (object_data == nullptr) - continue; - - auto name = object_data->name; - - if (name == nullptr) - continue; + auto blendeName = string(object_name); - if (instances.find(name) == instances.end()) { - matrix_vector v; - instances.insert(move(pair(name, move(v)))); - } + auto unityName = blendeName.substr(2, blendeName.size()); auto world_matrix = float4x4(); blContext.world_matrix_get(&instance, &world_matrix); auto result = blenderToUnityWorldMatrix(world_matrix); - instances[name].push_back(move(result)); + + f(move(unityName), move(result)); } // Cleanup resources blContext.object_instances_end(&it); } - void msblenGeometryNodes::clearObjectInstances() - { - for (auto &it :instances) { - it.second.clear(); - } - } - - void msblenGeometryNodes::addInstanceData(const Object* src, ms::Mesh& dst) - { - auto data = (ID*)src->data; - - if (data == nullptr) - return; - - auto meshName = data->name; + void GeometryNodesUtils::foreach_instance(std::function)> f) { + std::map> map; + foreach_instance([&](string name, float4x4 matrix) { + map[name].push_back(matrix); + }); - auto meshInstances = instances.find(meshName); - if (instances.find(meshName) == instances.end()) - return; - - if (meshInstances->second.size() == 0) - return; - - /// Add mesh instances as a user property - if (dst.findUserProperty("instances")== nullptr){ - - auto matrices = instances[meshName]; - - ms::Variant newProperty; - - newProperty.name = "instances"; - newProperty.type = ms::Variant::Type::Float4x4; - newProperty.set(matrices.data(), matrices.size()); - dst.addUserProperty(move(newProperty)); + for (auto& entry : map) { + f(entry.first, entry.second); } } - - // EVENTS - - void msblenGeometryNodes::onDepsgraphUpdatePost(Depsgraph* graph) - { - findObjectInstances(); - } - - void msblenGeometryNodes::onExportComplete() - { - clearObjectInstances(); - } - - void msblenGeometryNodes::onMeshExport(const Object* obj, ms::Mesh& mesh) - { - addInstanceData(obj, mesh); - } +#endif } diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h index b2a9a7f3..759256c8 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h @@ -5,27 +5,30 @@ #include "DNA_object_types.h" #include "MeshSync/SceneGraph/msMesh.h" #include +#include "MeshSyncClient/msInstancesManager.h" +#include "MeshUtils/muMath.h" namespace blender { - class msblenGeometryNodes +#if BLENDER_VERSION >= 300 + class GeometryNodesUtils { - private: - // Object instances - typedef std::vector matrix_vector; - typedef std::unordered_map object_instances_t; - object_instances_t instances; - void findObjectInstances(); - void clearObjectInstances(); - void addInstanceData(const Object* src, ms::Mesh& dst); + public: + /// + /// /// Converts the world matrix from blender to Unity coordinate system + /// /// + static mu::float4x4& blenderToUnityWorldMatrix(mu::float4x4& blenderMatrix); - public: - // Blender Application events - void onDepsgraphUpdatePost(Depsgraph* graph); + /// + /// Will invoke f for every instance. The first argument of f is the name + /// of the mesh that is being instantiated and the second argumenet is the world matrix + /// of the instance in the Unity3D Coordinate system + /// + /// + static void foreach_instance(std::function f); - // MeshSync events - void onExportComplete(); - void onMeshExport(const Object* obj, ms::Mesh& mesh); + static void foreach_instance(std::function)> f); }; +#endif } From 2816457f48e81fa8931e09dbf3d562abe258b83f Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Mon, 21 Feb 2022 17:07:54 +0000 Subject: [PATCH 13/67] Reduced amount of times instances are accessed. Delete message is populated and handled correctly with regards to the instancing info --- .../MeshSyncClient/msInstancesManager.h | 7 +++- .../Src/MeshSyncClient/msInstancesManager.cpp | 33 ++++++++++++++--- .../MeshSyncClientBlender/msblenContext.cpp | 36 ++++++++++++++----- .../Src/MeshSyncClientBlender/msblenContext.h | 7 ++++ .../msblenGeometryNodes.cpp | 10 +++++- .../msblenGeometryNodes.h | 6 ++++ 6 files changed, 84 insertions(+), 15 deletions(-) diff --git a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h index 329c955c..09ba3897 100644 --- a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h +++ b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h @@ -3,6 +3,7 @@ #include "MeshSync/MeshSync.h" #include "MeshSync/SceneGraph/msIdentifier.h" #include +#include #ifndef msRuntime @@ -15,21 +16,25 @@ namespace ms { public: std::vector getAllInstances(); std::vector getDirtyInstances(); + std::vector& getDeleted(); void clearDirtyFlags(); void add(InstanceInfoPtr instanceInfo); void clear(); + void deleteAll(); void setAlwaysMarkDirty(bool alwaysDirty); private: struct Record { - bool dirty; + bool dirty = true; InstanceInfoPtr instances; }; std::map m_records; + std::vector m_deleted; std::mutex m_mutex; + bool m_always_mark_dirty; }; diff --git a/Plugins~/Src/MeshSyncClient/msInstancesManager.cpp b/Plugins~/Src/MeshSyncClient/msInstancesManager.cpp index 388d4d17..00a79177 100644 --- a/Plugins~/Src/MeshSyncClient/msInstancesManager.cpp +++ b/Plugins~/Src/MeshSyncClient/msInstancesManager.cpp @@ -6,9 +6,11 @@ using namespace std; namespace ms { vector ms::InstancesManager::getAllInstances() { + vector ret; for (auto& v : m_records) ret.push_back(v.second.instances); + return ret; } @@ -24,28 +26,51 @@ namespace ms { return ret; } + vector& InstancesManager::getDeleted() + { + return m_deleted; + } + void InstancesManager::clearDirtyFlags() { for (auto& p : m_records) { Record& r = p.second; r.dirty = false; } + + m_deleted.clear(); } - /// TODO - Make this thread safe void InstancesManager::add(InstanceInfoPtr info) { - auto& rec = m_records[info->path]; + auto path = info->path; + auto it = std::find_if(m_deleted.begin(), m_deleted.end(), [&path](Identifier& v) { return v.name == path; }); + if (it != m_deleted.end()) { + m_deleted.erase(it); + } + + auto& rec = m_records[path]; rec.instances = info; - rec.dirty = true; + + if (m_always_mark_dirty) { + rec.dirty = true; + } } void InstancesManager::clear() { m_records.clear(); + m_deleted.clear(); + } + + void InstancesManager::deleteAll() + { + for (auto& record : m_records) { + m_deleted.push_back(record.second.instances->getIdentifier()); + } } void InstancesManager::setAlwaysMarkDirty(bool alwaysDirty) { - // For the moment, we always mark it as dirty, do nothing + m_always_mark_dirty = alwaysDirty; } } diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index 4ef4ea69..f3cc0673 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -1393,6 +1393,7 @@ bool msblenContext::sendObjects(MeshSyncClient::ObjectScope scope, bool dirty_al m_entity_manager.setAlwaysMarkDirty(dirty_all); m_material_manager.setAlwaysMarkDirty(dirty_all); m_texture_manager.setAlwaysMarkDirty(false); // false because too heavy + m_instances_manager.setAlwaysMarkDirty(dirty_all); if (m_settings.sync_meshes) RegisterSceneMaterials(); @@ -1418,6 +1419,30 @@ bool msblenContext::sendObjects(MeshSyncClient::ObjectScope scope, bool dirty_al eraseStaleObjects(); } +#if BLENDER_VERSION >= 300 + if (m_geometryNodeUtils.getInstancesDirty()) { + + // Assume everything needs to be deleted + m_instances_manager.deleteAll(); + + // Assume everything is now dirty + m_instances_manager.setAlwaysMarkDirty(true); + + auto func = [&](std::string str, std::vector mat) { + auto info = ms::InstanceInfo::create(); + info->path = str; + info->transforms = mat; + + // If an object that is added has been marked for deletion + // it will be removed from the deletion list + m_instances_manager.add(std::move(info)); + }; + + blender::GeometryNodesUtils::foreach_instance(func); + } + m_geometryNodeUtils.setInstancesDirty(false); +#endif + WaitAndKickAsyncExport(); return true; } @@ -1626,6 +1651,7 @@ void msblenContext::WaitAndKickAsyncExport() t.deleted_materials = m_material_manager.getDeleted(); t.deleted_entities = m_entity_manager.getDeleted(); + t.deleted_instanceInfos = m_instances_manager.getDeleted(); if (scale_factor != 1.0f) { ms::ScaleConverter cv(scale_factor); @@ -1656,15 +1682,7 @@ void msblenContext::onDepsgraphUpdatedPost(Depsgraph* graph) { //TODO - Check thread safety #if BLENDER_VERSION >= 300 - auto func = [&](std::string str, std::vector mat){ - auto info = ms::InstanceInfo::create(); - info->path = str; - info->transforms = mat; - - m_instances_manager.add(info); - }; - - blender::GeometryNodesUtils::foreach_instance(func); + m_geometryNodeUtils.setInstancesDirty(true); #endif } diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h index f3f38d73..dc762b89 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h @@ -23,6 +23,10 @@ #include "MeshSyncClient/msInstancesManager.h" +#if BLENDER_VERSION >= 300 +#include +#endif + class msblenContext; class msblenContext { @@ -190,6 +194,9 @@ class msblenContext { ms::SceneCacheWriter m_cache_writer; ms::InstancesManager m_instances_manager; +#if BLENDER_VERSION >= 300 + blender::GeometryNodesUtils m_geometryNodeUtils; +#endif // animation export std::map m_anim_records; diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp index 99e6bf97..4db5b247 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp @@ -85,7 +85,7 @@ namespace blender { } void GeometryNodesUtils::foreach_instance(std::function)> f) { - std::map> map; + map> map; foreach_instance([&](string name, float4x4 matrix) { map[name].push_back(matrix); }); @@ -94,5 +94,13 @@ namespace blender { f(entry.first, entry.second); } } + void GeometryNodesUtils::setInstancesDirty(bool dirty) + { + m_instances_dirty = dirty; + } + bool GeometryNodesUtils::getInstancesDirty() + { + return m_instances_dirty; + } #endif } diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h index 759256c8..bd48a5bb 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h @@ -28,6 +28,12 @@ namespace blender { static void foreach_instance(std::function f); static void foreach_instance(std::function)> f); + + void setInstancesDirty(bool dirty); + bool getInstancesDirty(); + + private: + bool m_instances_dirty; }; #endif } From a0b0af4c164e1882125bfe11691eeb8b9fec9d3c Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Mon, 21 Feb 2022 19:25:48 +0000 Subject: [PATCH 14/67] Better name generation for instance info --- .../msblenGeometryNodes.cpp | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp index 4db5b247..f256e769 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp @@ -4,6 +4,7 @@ #include #include #include "BlenderPyObjects/BlenderPyNodeTree.h" +#include "BlenderPyObjects/BlenderPyScene.h" using namespace std; @@ -38,6 +39,22 @@ namespace blender { void GeometryNodesUtils::foreach_instance(std::function f) { + // Build a table to translate meshNames to object names + auto scene = blContext.scene(); + auto mscene = BlenderPyScene(scene); + + map meshToObject; + + mscene.each_objects([&](Object* obj) { + if (obj->type != OB_MESH) + return; + + auto object_name = obj->id.name; + + auto mesh = (Mesh*)obj->data; + auto mesh_name = mesh->id.name; + meshToObject[mesh_name] = object_name; + }); // BlenderPyContext is an interface between depsgraph operations and anything that interacts with it auto blContext = blender::BlenderPyContext::get(); @@ -65,7 +82,14 @@ namespace blender { continue; auto object = blContext.object_get(instance); - auto object_name = object->id.name; + + if (object->type != OB_MESH) + continue; + + auto mesh = (Mesh*)object->data; + auto mesh_name = mesh->id.name; + + auto object_name = meshToObject[mesh_name]; auto blendeName = string(object_name); From 971f369319c78a9fd47511ee086cb65bfa5676f0 Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Tue, 22 Feb 2022 09:24:32 +0000 Subject: [PATCH 15/67] fixed compilation error --- Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp index f256e769..c6119b95 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp @@ -39,6 +39,7 @@ namespace blender { void GeometryNodesUtils::foreach_instance(std::function f) { + auto blContext = blender::BlenderPyContext::get(); // Build a table to translate meshNames to object names auto scene = blContext.scene(); auto mscene = BlenderPyScene(scene); @@ -57,7 +58,6 @@ namespace blender { }); // BlenderPyContext is an interface between depsgraph operations and anything that interacts with it - auto blContext = blender::BlenderPyContext::get(); auto depsgraph = blContext.evaluated_depsgraph_get(); // Iterate over the object instances collection of depsgraph From 289afed7cd86d54b6a017e475ea2d356e15694aa Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Tue, 22 Feb 2022 11:33:28 +0000 Subject: [PATCH 16/67] small change on name translation --- .../msblenGeometryNodes.cpp | 26 ++++++++++--------- .../msblenGeometryNodes.h | 9 +++++++ 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp index c6119b95..f18b45ef 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp @@ -44,17 +44,18 @@ namespace blender { auto scene = blContext.scene(); auto mscene = BlenderPyScene(scene); - map meshToObject; + map dataToObject; mscene.each_objects([&](Object* obj) { - if (obj->type != OB_MESH) + if (obj == nullptr || obj->data == nullptr) return; auto object_name = obj->id.name; + - auto mesh = (Mesh*)obj->data; - auto mesh_name = mesh->id.name; - meshToObject[mesh_name] = object_name; + auto data = (ID*)obj->data; + auto data_name = getOutlinerName(data->name); + dataToObject[data_name] = getOutlinerName(object_name); }); // BlenderPyContext is an interface between depsgraph operations and anything that interacts with it @@ -87,13 +88,9 @@ namespace blender { continue; auto mesh = (Mesh*)object->data; - auto mesh_name = mesh->id.name; + auto mesh_name = getOutlinerName(mesh->id.name); - auto object_name = meshToObject[mesh_name]; - - auto blendeName = string(object_name); - - auto unityName = blendeName.substr(2, blendeName.size()); + auto object_name = dataToObject[mesh_name]; auto world_matrix = float4x4(); blContext.world_matrix_get(&instance, &world_matrix); @@ -101,7 +98,7 @@ namespace blender { auto result = blenderToUnityWorldMatrix(world_matrix); - f(move(unityName), move(result)); + f(move(object_name), move(result)); } // Cleanup resources @@ -118,6 +115,11 @@ namespace blender { f(entry.first, entry.second); } } + string GeometryNodesUtils::getOutlinerName(char* name) + { + string str(name); + return str.substr(2, str.size() - 2); + } void GeometryNodesUtils::setInstancesDirty(bool dirty) { m_instances_dirty = dirty; diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h index bd48a5bb..2bf4f060 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h @@ -29,6 +29,15 @@ namespace blender { static void foreach_instance(std::function)> f); + /// + /// Converts a name with the type embedded + /// to the name used without in the outliner window + /// i.e. MEMyMesh -> MyMesh + /// + /// + /// + static std::string getOutlinerName(char *name); + void setInstancesDirty(bool dirty); bool getInstancesDirty(); From 20071aea91bdf858caa344b1c82ae744e1feeda4 Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Tue, 22 Feb 2022 14:36:53 +0000 Subject: [PATCH 17/67] Using entity path as instance info path --- .../MeshSyncClientBlender/msblenContext.cpp | 11 ++++++- .../msblenGeometryNodes.cpp | 30 +++++++------------ .../msblenGeometryNodes.h | 9 ------ 3 files changed, 21 insertions(+), 29 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index f3cc0673..600bc1be 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -689,7 +689,16 @@ ms::MeshPtr msblenContext::exportMesh(const Object *src) (!is_editing && m_settings.BakeModifiers ) || !is_mesh(src); if (need_convert) { - if (m_settings.BakeModifiers ) { + + auto forceBakeModifiers = false; + +#if BLENDER_VERSION >= 300 + // If the object has a geometry node modifier, force bake it + auto node_modifier = (NodesModifierData*)FindModifier(src, ModifierType::eModifierType_Nodes); + forceBakeModifiers = node_modifier != nullptr && node_modifier->node_group->type == NTREE_GEOMETRY; +#endif + + if (m_settings.BakeModifiers || forceBakeModifiers) { auto blContext = bl::BlenderPyContext::get(); Depsgraph* depsgraph = blContext.evaluated_depsgraph_get(); bobj = (Object*)bl::BlenderPyID(bobj).evaluated_get(depsgraph); diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp index f18b45ef..b60e9c6d 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp @@ -5,6 +5,7 @@ #include #include "BlenderPyObjects/BlenderPyNodeTree.h" #include "BlenderPyObjects/BlenderPyScene.h" +#include using namespace std; @@ -39,23 +40,19 @@ namespace blender { void GeometryNodesUtils::foreach_instance(std::function f) { + auto blContext = blender::BlenderPyContext::get(); - // Build a table to translate meshNames to object names + // Build a map between data and the objects they belong to auto scene = blContext.scene(); auto mscene = BlenderPyScene(scene); - map dataToObject; + map dataToObject; mscene.each_objects([&](Object* obj) { if (obj == nullptr || obj->data == nullptr) return; - - auto object_name = obj->id.name; - - - auto data = (ID*)obj->data; - auto data_name = getOutlinerName(data->name); - dataToObject[data_name] = getOutlinerName(object_name); + auto data_id = (ID*)obj->data; + dataToObject[data_id->name] = obj; }); // BlenderPyContext is an interface between depsgraph operations and anything that interacts with it @@ -87,10 +84,9 @@ namespace blender { if (object->type != OB_MESH) continue; - auto mesh = (Mesh*)object->data; - auto mesh_name = getOutlinerName(mesh->id.name); - - auto object_name = dataToObject[mesh_name]; + auto data_id = (ID*)object->data; + auto hierarchyObject = dataToObject[data_id->name]; + auto path = get_path(hierarchyObject); auto world_matrix = float4x4(); blContext.world_matrix_get(&instance, &world_matrix); @@ -98,7 +94,7 @@ namespace blender { auto result = blenderToUnityWorldMatrix(world_matrix); - f(move(object_name), move(result)); + f(move(path), move(result)); } // Cleanup resources @@ -115,11 +111,7 @@ namespace blender { f(entry.first, entry.second); } } - string GeometryNodesUtils::getOutlinerName(char* name) - { - string str(name); - return str.substr(2, str.size() - 2); - } + void GeometryNodesUtils::setInstancesDirty(bool dirty) { m_instances_dirty = dirty; diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h index 2bf4f060..bd48a5bb 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h @@ -29,15 +29,6 @@ namespace blender { static void foreach_instance(std::function)> f); - /// - /// Converts a name with the type embedded - /// to the name used without in the outliner window - /// i.e. MEMyMesh -> MyMesh - /// - /// - /// - static std::string getOutlinerName(char *name); - void setInstancesDirty(bool dirty); bool getInstancesDirty(); From 3d46c8a019fe953bf7444b67611d9b1b31957525 Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Wed, 23 Feb 2022 14:41:39 +0000 Subject: [PATCH 18/67] null check guard --- Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp index b60e9c6d..d723146b 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp @@ -34,7 +34,7 @@ namespace blender { to_mat4x4(rotation180) * scale44(scale); - return move(result); + return result; } @@ -86,6 +86,9 @@ namespace blender { auto data_id = (ID*)object->data; auto hierarchyObject = dataToObject[data_id->name]; + if (hierarchyObject == nullptr) + continue; + auto path = get_path(hierarchyObject); auto world_matrix = float4x4(); From f0352d22925da8675b7405eff55877429427fd28 Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Wed, 23 Feb 2022 15:27:24 +0000 Subject: [PATCH 19/67] Covered use case where instances refer to meshes not in scene --- .../Src/MeshSyncClientBlender/msblenGeometryNodes.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp index d723146b..b3f78433 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp @@ -55,6 +55,9 @@ namespace blender { dataToObject[data_id->name] = obj; }); + + + // BlenderPyContext is an interface between depsgraph operations and anything that interacts with it auto depsgraph = blContext.evaluated_depsgraph_get(); @@ -86,8 +89,10 @@ namespace blender { auto data_id = (ID*)object->data; auto hierarchyObject = dataToObject[data_id->name]; - if (hierarchyObject == nullptr) - continue; + + if (hierarchyObject == nullptr) { + hierarchyObject = object; + } auto path = get_path(hierarchyObject); From 53e081bb729c0b65be37c3ceb44b56d8efa2b860 Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Tue, 1 Mar 2022 17:11:26 +0000 Subject: [PATCH 20/67] Support for instances on geometry that is not part of the scene --- .../MeshSyncClient/msInstancesManager.h | 14 ++- .../Src/MeshSyncClient/msInstancesManager.cpp | 72 ++++++++---- .../MeshSyncClientBlender/msblenContext.cpp | 111 +++++++++++++----- .../Src/MeshSyncClientBlender/msblenContext.h | 5 + .../msblenGeometryNodes.cpp | 62 +++++++--- .../msblenGeometryNodes.h | 11 +- 6 files changed, 199 insertions(+), 76 deletions(-) diff --git a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h index 09ba3897..ebba8edb 100644 --- a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h +++ b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h @@ -14,11 +14,13 @@ namespace ms { class InstancesManager { public: - std::vector getAllInstances(); + std::vector getDirtyMeshes(); std::vector getDirtyInstances(); - std::vector& getDeleted(); + std::vector& getDeletedInstanceInfos(); + std::vector& getDeletedMeshes(); void clearDirtyFlags(); void add(InstanceInfoPtr instanceInfo); + void add(TransformPtr mesh); void clear(); void deleteAll(); @@ -27,13 +29,15 @@ namespace ms { private: struct Record { - bool dirty = true; + bool dirtyInstances = false; + bool dirtyMesh = false; InstanceInfoPtr instances; + TransformPtr mesh; }; std::map m_records; - std::vector m_deleted; - std::mutex m_mutex; + std::vector m_deleted_instanceInfo; + std::vector m_deleted_meshes; bool m_always_mark_dirty; }; diff --git a/Plugins~/Src/MeshSyncClient/msInstancesManager.cpp b/Plugins~/Src/MeshSyncClient/msInstancesManager.cpp index 00a79177..fedb05ed 100644 --- a/Plugins~/Src/MeshSyncClient/msInstancesManager.cpp +++ b/Plugins~/Src/MeshSyncClient/msInstancesManager.cpp @@ -4,69 +4,99 @@ using namespace std; namespace ms { - vector ms::InstancesManager::getAllInstances() + std::vector InstancesManager::getDirtyMeshes() { - - vector ret; - for (auto& v : m_records) - ret.push_back(v.second.instances); - + vector ret; + for (auto& p : m_records) { + Record& r = p.second; + if (r.dirtyMesh) { + ret.push_back(r.mesh); + } + } return ret; } - vector InstancesManager::getDirtyInstances() { vector ret; for (auto& p : m_records) { Record& r = p.second; - if (r.dirty) { + if (r.dirtyInstances) { ret.push_back(r.instances); } } return ret; } - vector& InstancesManager::getDeleted() + vector& InstancesManager::getDeletedInstanceInfos() { - return m_deleted; + return m_deleted_instanceInfo; + } + + vector& InstancesManager::getDeletedMeshes() { + return m_deleted_meshes; } void InstancesManager::clearDirtyFlags() { for (auto& p : m_records) { Record& r = p.second; - r.dirty = false; + r.dirtyInstances = false; + r.dirtyMesh = false; + } + + m_deleted_instanceInfo.clear(); + m_deleted_meshes.clear(); + } + + void InstancesManager::add(TransformPtr mesh) { + + auto path = mesh->path; + auto it = std::find_if(m_deleted_meshes.begin(), m_deleted_meshes.end(), [&path](Identifier& v) { return v.name == path; }); + if (it != m_deleted_meshes.end()) { + m_deleted_meshes.erase(it); } - m_deleted.clear(); + auto& rec = m_records[path]; + + if (m_always_mark_dirty || rec.mesh == nullptr || rec.mesh->hash() != mesh->hash()) { + rec.dirtyMesh = true; + } + + rec.mesh = mesh; } void InstancesManager::add(InstanceInfoPtr info) { auto path = info->path; - auto it = std::find_if(m_deleted.begin(), m_deleted.end(), [&path](Identifier& v) { return v.name == path; }); - if (it != m_deleted.end()) { - m_deleted.erase(it); + + auto it = std::find_if(m_deleted_instanceInfo.begin(), m_deleted_instanceInfo.end(), [&path](Identifier& v) { return v.name == path; }); + if (it != m_deleted_instanceInfo.end()) { + m_deleted_instanceInfo.erase(it); } auto& rec = m_records[path]; - rec.instances = info; - - if (m_always_mark_dirty) { - rec.dirty = true; + + //TODO implement hash for InstanceInfo and check + if (m_always_mark_dirty || rec.instances == nullptr) { + rec.dirtyInstances = true; } + + rec.instances = info; } void InstancesManager::clear() { m_records.clear(); - m_deleted.clear(); + m_deleted_instanceInfo.clear(); } void InstancesManager::deleteAll() { for (auto& record : m_records) { - m_deleted.push_back(record.second.instances->getIdentifier()); + m_deleted_instanceInfo.push_back(record.second.instances->getIdentifier()); + if (record.second.mesh != nullptr) { + m_deleted_meshes.push_back(record.second.mesh->getIdentifier()); + } } } diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index 600bc1be..7033758f 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -690,15 +690,7 @@ ms::MeshPtr msblenContext::exportMesh(const Object *src) if (need_convert) { - auto forceBakeModifiers = false; - -#if BLENDER_VERSION >= 300 - // If the object has a geometry node modifier, force bake it - auto node_modifier = (NodesModifierData*)FindModifier(src, ModifierType::eModifierType_Nodes); - forceBakeModifiers = node_modifier != nullptr && node_modifier->node_group->type == NTREE_GEOMETRY; -#endif - - if (m_settings.BakeModifiers || forceBakeModifiers) { + if (m_settings.BakeModifiers) { auto blContext = bl::BlenderPyContext::get(); Depsgraph* depsgraph = blContext.evaluated_depsgraph_get(); bobj = (Object*)bl::BlenderPyID(bobj).evaluated_get(depsgraph); @@ -803,7 +795,12 @@ void msblenContext::doExtractBlendshapeWeights(ms::Mesh& dst, const Object *obj, } } -void msblenContext::doExtractNonEditMeshData(ms::Mesh& dst, const Object *obj, Mesh *data) + +void msblenContext::doExtractNonEditMeshData(ms::Mesh& dst, const Object* obj, Mesh* data) { + doExtractNonEditMeshData(dst, obj, data, m_settings); +} + +void msblenContext::doExtractNonEditMeshData(ms::Mesh& dst, const Object *obj, Mesh *data, BlenderSyncSettings& settings) { bl::BObject bobj(obj); bl::BMesh bmesh(data); @@ -851,7 +848,7 @@ void msblenContext::doExtractNonEditMeshData(ms::Mesh& dst, const Object *obj, M } // normals - if (m_settings.sync_normals) { + if (settings.sync_normals) { #if 0 // per-vertex dst.normals.resize_discard(num_vertices); @@ -870,13 +867,13 @@ void msblenContext::doExtractNonEditMeshData(ms::Mesh& dst, const Object *obj, M // uv - if (m_settings.sync_uvs) { + if (settings.sync_uvs) { blender::BlenderUtility::ApplyBMeshUVToMesh(&bmesh, num_indices, &dst); } // colors - if (m_settings.sync_colors) { + if (settings.sync_colors) { blender::barray_range colors = bmesh.colors(); if (!colors.empty()) { dst.colors.resize_discard(num_indices); @@ -885,7 +882,7 @@ void msblenContext::doExtractNonEditMeshData(ms::Mesh& dst, const Object *obj, M } } - if (!m_settings.BakeModifiers) { + if (!settings.BakeModifiers) { // bones auto extract_bindpose = [](auto *bone) { @@ -894,7 +891,7 @@ void msblenContext::doExtractNonEditMeshData(ms::Mesh& dst, const Object *obj, M return mu::invert(mu::swap_yz(mu::flip_z(mat_bone))); }; - if (m_settings.sync_bones) { + if (settings.sync_bones) { const ArmatureModifierData* arm_mod = (const ArmatureModifierData*)FindModifier( obj, eModifierType_Armature); if (arm_mod) { @@ -935,7 +932,7 @@ void msblenContext::doExtractNonEditMeshData(ms::Mesh& dst, const Object *obj, M } // blend shapes - if (m_settings.sync_blendshapes && mesh.key) { + if (settings.sync_blendshapes && mesh.key) { RawVector basis; int bi = 0; each_key(&mesh, [&](const KeyBlock *kb) { @@ -1099,6 +1096,38 @@ void msblenContext::doExtractEditMeshData(ms::Mesh& dst, const Object *obj, Mesh } } +void msblenContext::doExtactMeshDataWithoutObject(ms::MeshPtr msMesh, Mesh* mesh) +{ + BlenderSyncSettings meshExtractionSettings; + meshExtractionSettings.sync_meshes = true; + meshExtractionSettings.sync_normals = true; + meshExtractionSettings.sync_uvs = true; + meshExtractionSettings.sync_colors = true; + meshExtractionSettings.sync_bones = false; + + auto path = std::string(mesh->id.name); + path += std::to_string(mesh->id.session_uuid); + + + doExtractNonEditMeshData(*(msMesh), nullptr, mesh, meshExtractionSettings); + + if (msMesh->normals.empty()) + msMesh->refine_settings.flags.Set(ms::MESH_REFINE_FLAG_GEN_NORMALS, true); + if (msMesh->tangents.empty()) + msMesh->refine_settings.flags.Set(ms::MESH_REFINE_FLAG_GEN_TANGENTS, true); + + msMesh->path = path; + msMesh->world_matrix = mu::float4x4::identity(); + msMesh->local_matrix = mu::float4x4::identity(); + msMesh->visibility.active = false; + + msMesh->refine_settings.local2world = m_geometryNodeUtils.blenderToUnityWorldMatrixMesh(); + msMesh->refine_settings.flags.Set(ms::MeshRefineFlagsBit::MESH_REFINE_FLAG_LOCAL2WORLD, true); + msMesh->refine_settings.flags.Set(ms::MeshRefineFlagsBit::MESH_REFINE_FLAG_FLIP_FACES, true); + + msMesh->refine(); +} + ms::TransformPtr msblenContext::findBone(Object *armature, Bone *bone) { std::map>::iterator it = m_bones.find(bone); @@ -1393,6 +1422,34 @@ bool msblenContext::sendMaterials(bool dirty_all) return true; } +void msblenContext::exportInstances(std::string str, std::vector mat) { + auto info = ms::InstanceInfo::create(); + info->path = str; + info->transforms = mat; + info->type = ms::InstanceInfo::ReferenceType::ENTITY_PATH; + + // If an object that is added has been marked for deletion + // it will be removed from the deletion list + m_instances_manager.add(std::move(info)); +} + +void msblenContext::exportInstancesWithMesh(Mesh* mesh, std::vector mat) +{ + auto msMesh = ms::Mesh::create(); + + doExtactMeshDataWithoutObject(msMesh, mesh); + + auto info = ms::InstanceInfo::create(); + info->type = ms::InstanceInfo::ReferenceType::MESH_PATH; + info->path = msMesh->path; + info->transforms = mat; + + // If an object that is added has been marked for deletion + // it will be removed from the deletion list + m_instances_manager.add(std::move(info)); + m_instances_manager.add(std::move(msMesh)); +} + bool msblenContext::sendObjects(MeshSyncClient::ObjectScope scope, bool dirty_all) { if (!prepare() || m_sender.isExporting() || m_ignore_events) @@ -1429,7 +1486,7 @@ bool msblenContext::sendObjects(MeshSyncClient::ObjectScope scope, bool dirty_al } #if BLENDER_VERSION >= 300 - if (m_geometryNodeUtils.getInstancesDirty()) { + if (m_geometryNodeUtils.getInstancesDirty() || dirty_all) { // Assume everything needs to be deleted m_instances_manager.deleteAll(); @@ -1437,19 +1494,12 @@ bool msblenContext::sendObjects(MeshSyncClient::ObjectScope scope, bool dirty_al // Assume everything is now dirty m_instances_manager.setAlwaysMarkDirty(true); - auto func = [&](std::string str, std::vector mat) { - auto info = ms::InstanceInfo::create(); - info->path = str; - info->transforms = mat; - - // If an object that is added has been marked for deletion - // it will be removed from the deletion list - m_instances_manager.add(std::move(info)); - }; + auto instancesHandler = std::bind(&msblenContext::exportInstances, this, std::placeholders::_1, std::placeholders::_2); + auto instancesWithMeshHandler = std::bind(&msblenContext::exportInstancesWithMesh, this, std::placeholders::_1, std::placeholders::_2); + blender::GeometryNodesUtils::foreach_instance(instancesHandler, instancesWithMeshHandler); - blender::GeometryNodesUtils::foreach_instance(func); + m_geometryNodeUtils.setInstancesDirty(false); } - m_geometryNodeUtils.setInstancesDirty(false); #endif WaitAndKickAsyncExport(); @@ -1656,11 +1706,13 @@ void msblenContext::WaitAndKickAsyncExport() t.transforms = m_entity_manager.getDirtyTransforms(); t.geometries = m_entity_manager.getDirtyGeometries(); t.instanceInfos = m_instances_manager.getDirtyInstances(); + t.instanceMeshes = m_instances_manager.getDirtyMeshes(); t.animations = m_animations; t.deleted_materials = m_material_manager.getDeleted(); t.deleted_entities = m_entity_manager.getDeleted(); - t.deleted_instanceInfos = m_instances_manager.getDeleted(); + t.deleted_instanceInfos = m_instances_manager.getDeletedInstanceInfos(); + t.deleted_instanceMeshes = m_instances_manager.getDeletedMeshes(); if (scale_factor != 1.0f) { ms::ScaleConverter cv(scale_factor); @@ -1689,7 +1741,6 @@ void msblenContext::WaitAndKickAsyncExport() /// void msblenContext::onDepsgraphUpdatedPost(Depsgraph* graph) { - //TODO - Check thread safety #if BLENDER_VERSION >= 300 m_geometryNodeUtils.setInstancesDirty(true); #endif diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h index dc762b89..ecac06ba 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h @@ -157,7 +157,9 @@ class msblenContext { void doExtractMeshData(ms::Mesh& dst, const Object *obj, Mesh *data, mu::float4x4 world); void doExtractBlendshapeWeights(ms::Mesh& dst, const Object *obj, Mesh *data); void doExtractNonEditMeshData(ms::Mesh& dst, const Object *obj, Mesh *data); + void doExtractNonEditMeshData(ms::Mesh& dst,const Object* obj, Mesh* data, BlenderSyncSettings& settings); void doExtractEditMeshData(ms::Mesh& dst, const Object *obj, Mesh *data); + void doExtactMeshDataWithoutObject(ms::MeshPtr, Mesh*); ms::TransformPtr findBone(Object *armature, Bone *bone); ObjectRecord& touchRecord(const Object *obj, const std::string& base_path = "", bool children = false); @@ -173,6 +175,9 @@ class msblenContext { void DoExportSceneCache(const std::vector& nodes); void WaitAndKickAsyncExport(); + void exportInstances(std::string, std::vector); + void exportInstancesWithMesh(Mesh* mesh, std::vector); + private: BlenderSyncSettings m_settings; diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp index b3f78433..d47a0907 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp @@ -23,22 +23,40 @@ namespace blender { auto rotation = rotate_x(-90 * DegToRad); auto rotation180 = rotate_z(180 * DegToRad); - auto scale = float3::one(); - scale.x = -1; + auto scale_z = float3::one(); + scale_z.z = -1; + + auto scale_x = float3::one(); + scale_x.x = -1; auto result = to_mat4x4(rotation) * - scale44(scale) * + scale44(scale_x) * blenderMatrix * to_mat4x4(rotation) * to_mat4x4(rotation180) * + scale44(scale_z); + + return result; + } + + mu::float4x4& GeometryNodesUtils::blenderToUnityWorldMatrixMesh() + { + auto rotation = rotate_x(90 * DegToRad); + auto scale = float3::one(); + scale.x = -1; + + auto result = + to_mat4x4(rotation) * scale44(scale); return result; } - void GeometryNodesUtils::foreach_instance(std::function f) + void GeometryNodesUtils::foreach_instance( + std::function pathHandler, + std::function meshHandler) { auto blContext = blender::BlenderPyContext::get(); @@ -90,33 +108,41 @@ namespace blender { auto data_id = (ID*)object->data; auto hierarchyObject = dataToObject[data_id->name]; - if (hierarchyObject == nullptr) { - hierarchyObject = object; - } - - auto path = get_path(hierarchyObject); - auto world_matrix = float4x4(); blContext.world_matrix_get(&instance, &world_matrix); - auto result = blenderToUnityWorldMatrix(world_matrix); + auto unityMatrix = blenderToUnityWorldMatrix(world_matrix); - - f(move(path), move(result)); + if (hierarchyObject == nullptr) { + auto mesh = (Mesh*)object->data; + meshHandler(move(mesh),move(unityMatrix)); + } + else { + auto path = get_path(hierarchyObject); + pathHandler(move(path), move(unityMatrix)); + } } // Cleanup resources blContext.object_instances_end(&it); } - void GeometryNodesUtils::foreach_instance(std::function)> f) { - map> map; + void GeometryNodesUtils::foreach_instance( + std::function)> pathHandler, + std::function)> meshHandler) { + map> pathMap; + map> meshMap; foreach_instance([&](string name, float4x4 matrix) { - map[name].push_back(matrix); + pathMap[name].push_back(matrix); + }, [&](Mesh* mesh, float4x4 matrix) { + meshMap[mesh].push_back(matrix); }); - for (auto& entry : map) { - f(entry.first, entry.second); + for (auto& entry : pathMap) { + pathHandler(entry.first, entry.second); + } + for (auto& entry : meshMap) { + meshHandler(entry.first, entry.second); } } diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h index bd48a5bb..55c88e9d 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h @@ -7,6 +7,7 @@ #include #include "MeshSyncClient/msInstancesManager.h" #include "MeshUtils/muMath.h" +#include namespace blender { @@ -19,15 +20,21 @@ namespace blender { /// /// static mu::float4x4& blenderToUnityWorldMatrix(mu::float4x4& blenderMatrix); + static mu::float4x4& blenderToUnityWorldMatrixMesh(); + /// /// Will invoke f for every instance. The first argument of f is the name /// of the mesh that is being instantiated and the second argumenet is the world matrix /// of the instance in the Unity3D Coordinate system /// /// - static void foreach_instance(std::function f); + static void foreach_instance( + std::function pathHandler, + std::function meshHandler); - static void foreach_instance(std::function)> f); + static void foreach_instance( + std::function)> pathHandler, + std::function)> meshHandler); void setInstancesDirty(bool dirty); bool getInstancesDirty(); From 6a7c848f5fab9480042d36c3812d10eacdcdcf8f Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Wed, 9 Mar 2022 10:57:16 +0000 Subject: [PATCH 21/67] Fix for Release compilation not rendering intermediate meshes --- .../Src/MeshSyncClientBlender/msblenGeometryNodes.cpp | 8 ++++---- Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp index d47a0907..98582af3 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp @@ -40,14 +40,14 @@ namespace blender { return result; } - mu::float4x4& GeometryNodesUtils::blenderToUnityWorldMatrixMesh() + mu::float4x4 GeometryNodesUtils::blenderToUnityWorldMatrixMesh() { - auto rotation = rotate_x(90 * DegToRad); + auto rotation = rotate_x(90.0f * DegToRad); auto scale = float3::one(); scale.x = -1; - auto result = - to_mat4x4(rotation) * + auto result = + to_mat4x4(rotation)* scale44(scale); return result; diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h index 55c88e9d..cc42d96e 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h @@ -20,7 +20,7 @@ namespace blender { /// /// static mu::float4x4& blenderToUnityWorldMatrix(mu::float4x4& blenderMatrix); - static mu::float4x4& blenderToUnityWorldMatrixMesh(); + static mu::float4x4 blenderToUnityWorldMatrixMesh(); /// /// Will invoke f for every instance. The first argument of f is the name From ef8bd158ca09ac833702bbb69e8dadfc33942171 Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Thu, 10 Mar 2022 13:49:12 +0000 Subject: [PATCH 22/67] Corrected cmake syntex for using c++17 --- Plugins~/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins~/CMakeLists.txt b/Plugins~/CMakeLists.txt index b0fa3a5a..064f0a06 100644 --- a/Plugins~/CMakeLists.txt +++ b/Plugins~/CMakeLists.txt @@ -53,7 +53,7 @@ include(UnityPackage) setup_unity_package_version() add_definitions(-DMESHSYNC_DCC_PLUGIN_VER="${UNITY_PACKAGE_VERSION}") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++17") # Force Unicode character set add_definitions(-DUNICODE -D_UNICODE) From 58e6eabdb6a9de7a703c4b9a3515e3c7ad6b07ed Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Thu, 10 Mar 2022 13:58:25 +0000 Subject: [PATCH 23/67] Avoid returning address of local var --- Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp | 2 +- Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp index 98582af3..302970ef 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp @@ -19,7 +19,7 @@ namespace blender { /// /// /// - float4x4& GeometryNodesUtils::blenderToUnityWorldMatrix(float4x4& blenderMatrix) { + float4x4 GeometryNodesUtils::blenderToUnityWorldMatrix(float4x4& blenderMatrix) { auto rotation = rotate_x(-90 * DegToRad); auto rotation180 = rotate_z(180 * DegToRad); diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h index cc42d96e..3ce6ed6a 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h @@ -18,7 +18,7 @@ namespace blender { /// /// /// Converts the world matrix from blender to Unity coordinate system /// /// - static mu::float4x4& blenderToUnityWorldMatrix(mu::float4x4& blenderMatrix); + static mu::float4x4 blenderToUnityWorldMatrix(mu::float4x4& blenderMatrix); static mu::float4x4 blenderToUnityWorldMatrixMesh(); From 127a133de1816e008d2580df7215b7ea67c1c4ac Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Thu, 10 Mar 2022 14:26:23 +0000 Subject: [PATCH 24/67] Code depending on geometry nodes compiles only on 3.0.0 and above --- .../MeshSyncClientBlender/msblenContext.cpp | 120 +++++++++--------- .../Src/MeshSyncClientBlender/msblenContext.h | 6 +- 2 files changed, 68 insertions(+), 58 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index 7033758f..bb497d6f 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -1096,37 +1096,6 @@ void msblenContext::doExtractEditMeshData(ms::Mesh& dst, const Object *obj, Mesh } } -void msblenContext::doExtactMeshDataWithoutObject(ms::MeshPtr msMesh, Mesh* mesh) -{ - BlenderSyncSettings meshExtractionSettings; - meshExtractionSettings.sync_meshes = true; - meshExtractionSettings.sync_normals = true; - meshExtractionSettings.sync_uvs = true; - meshExtractionSettings.sync_colors = true; - meshExtractionSettings.sync_bones = false; - - auto path = std::string(mesh->id.name); - path += std::to_string(mesh->id.session_uuid); - - - doExtractNonEditMeshData(*(msMesh), nullptr, mesh, meshExtractionSettings); - - if (msMesh->normals.empty()) - msMesh->refine_settings.flags.Set(ms::MESH_REFINE_FLAG_GEN_NORMALS, true); - if (msMesh->tangents.empty()) - msMesh->refine_settings.flags.Set(ms::MESH_REFINE_FLAG_GEN_TANGENTS, true); - - msMesh->path = path; - msMesh->world_matrix = mu::float4x4::identity(); - msMesh->local_matrix = mu::float4x4::identity(); - msMesh->visibility.active = false; - - msMesh->refine_settings.local2world = m_geometryNodeUtils.blenderToUnityWorldMatrixMesh(); - msMesh->refine_settings.flags.Set(ms::MeshRefineFlagsBit::MESH_REFINE_FLAG_LOCAL2WORLD, true); - msMesh->refine_settings.flags.Set(ms::MeshRefineFlagsBit::MESH_REFINE_FLAG_FLIP_FACES, true); - - msMesh->refine(); -} ms::TransformPtr msblenContext::findBone(Object *armature, Bone *bone) { @@ -1422,33 +1391,7 @@ bool msblenContext::sendMaterials(bool dirty_all) return true; } -void msblenContext::exportInstances(std::string str, std::vector mat) { - auto info = ms::InstanceInfo::create(); - info->path = str; - info->transforms = mat; - info->type = ms::InstanceInfo::ReferenceType::ENTITY_PATH; - - // If an object that is added has been marked for deletion - // it will be removed from the deletion list - m_instances_manager.add(std::move(info)); -} - -void msblenContext::exportInstancesWithMesh(Mesh* mesh, std::vector mat) -{ - auto msMesh = ms::Mesh::create(); - doExtactMeshDataWithoutObject(msMesh, mesh); - - auto info = ms::InstanceInfo::create(); - info->type = ms::InstanceInfo::ReferenceType::MESH_PATH; - info->path = msMesh->path; - info->transforms = mat; - - // If an object that is added has been marked for deletion - // it will be removed from the deletion list - m_instances_manager.add(std::move(info)); - m_instances_manager.add(std::move(msMesh)); -} bool msblenContext::sendObjects(MeshSyncClient::ObjectScope scope, bool dirty_all) { @@ -1747,3 +1690,66 @@ void msblenContext::onDepsgraphUpdatedPost(Depsgraph* graph) } +/// Geometry Nodes Blender Context Functionality /// +#if BLENDER_VERSION >= 300 +void msblenContext::doExtactMeshDataWithoutObject(ms::MeshPtr msMesh, Mesh* mesh) +{ + BlenderSyncSettings meshExtractionSettings; + meshExtractionSettings.sync_meshes = true; + meshExtractionSettings.sync_normals = true; + meshExtractionSettings.sync_uvs = true; + meshExtractionSettings.sync_colors = true; + meshExtractionSettings.sync_bones = false; + + auto path = std::string(mesh->id.name); + path += std::to_string(mesh->id.session_uuid); + + + doExtractNonEditMeshData(*(msMesh), nullptr, mesh, meshExtractionSettings); + + if (msMesh->normals.empty()) + msMesh->refine_settings.flags.Set(ms::MESH_REFINE_FLAG_GEN_NORMALS, true); + if (msMesh->tangents.empty()) + msMesh->refine_settings.flags.Set(ms::MESH_REFINE_FLAG_GEN_TANGENTS, true); + + msMesh->path = path; + msMesh->world_matrix = mu::float4x4::identity(); + msMesh->local_matrix = mu::float4x4::identity(); + msMesh->visibility.active = false; + + msMesh->refine_settings.local2world = m_geometryNodeUtils.blenderToUnityWorldMatrixMesh(); + msMesh->refine_settings.flags.Set(ms::MeshRefineFlagsBit::MESH_REFINE_FLAG_LOCAL2WORLD, true); + msMesh->refine_settings.flags.Set(ms::MeshRefineFlagsBit::MESH_REFINE_FLAG_FLIP_FACES, true); + + msMesh->refine(); +} + +void msblenContext::exportInstances(std::string str, std::vector mat) { + auto info = ms::InstanceInfo::create(); + info->path = str; + info->transforms = mat; + info->type = ms::InstanceInfo::ReferenceType::ENTITY_PATH; + + // If an object that is added has been marked for deletion + // it will be removed from the deletion list + m_instances_manager.add(std::move(info)); +} + +void msblenContext::exportInstancesWithMesh(Mesh* mesh, std::vector mat) +{ + auto msMesh = ms::Mesh::create(); + + doExtactMeshDataWithoutObject(msMesh, mesh); + + auto info = ms::InstanceInfo::create(); + info->type = ms::InstanceInfo::ReferenceType::MESH_PATH; + info->path = msMesh->path; + info->transforms = mat; + + // If an object that is added has been marked for deletion + // it will be removed from the deletion list + m_instances_manager.add(std::move(info)); + m_instances_manager.add(std::move(msMesh)); +} +#endif + diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h index ecac06ba..3460cbd5 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h @@ -159,7 +159,8 @@ class msblenContext { void doExtractNonEditMeshData(ms::Mesh& dst, const Object *obj, Mesh *data); void doExtractNonEditMeshData(ms::Mesh& dst,const Object* obj, Mesh* data, BlenderSyncSettings& settings); void doExtractEditMeshData(ms::Mesh& dst, const Object *obj, Mesh *data); - void doExtactMeshDataWithoutObject(ms::MeshPtr, Mesh*); + + ms::TransformPtr findBone(Object *armature, Bone *bone); ObjectRecord& touchRecord(const Object *obj, const std::string& base_path = "", bool children = false); @@ -175,8 +176,11 @@ class msblenContext { void DoExportSceneCache(const std::vector& nodes); void WaitAndKickAsyncExport(); +#if BLENDER_VERSION >= 300 + void doExtactMeshDataWithoutObject(ms::MeshPtr, Mesh*); void exportInstances(std::string, std::vector); void exportInstancesWithMesh(Mesh* mesh, std::vector); +#endif private: From 636d57a6c219fbfdbb92819364f2ea529ad3d37a Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Thu, 10 Mar 2022 18:59:41 +0000 Subject: [PATCH 25/67] Fix for Python Lib check on Mac --- Plugins~/Build/cmake_modules/Python.cmake | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Plugins~/Build/cmake_modules/Python.cmake b/Plugins~/Build/cmake_modules/Python.cmake index e880f11f..466ae1d9 100644 --- a/Plugins~/Build/cmake_modules/Python.cmake +++ b/Plugins~/Build/cmake_modules/Python.cmake @@ -105,6 +105,12 @@ function(configure_python python_ver_no_dots) " Path: ${PYTHON_SRC_ROOT}" ) endif() + + if(WIN32 AND NOT DEFINED PYTHON_${python_full_version}_LIBRARY) + message(FATAL_ERROR "Failed to find and configure Python libraries for ${python_full_version}. \n" + " Path: ${PYTHON_SRC_ROOT}" + ) + endif() endfunction() From 91c26e112f3d773d7186c61832e81ae3b6f0a18e Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Thu, 10 Mar 2022 19:37:50 +0000 Subject: [PATCH 26/67] Fixed errors when compiling with XCode --- Plugins~/CMakeLists.txt | 6 ++- .../BlenderPyDepsgraphUpdate.cpp | 41 ------------------- .../BlenderPyDepsgraphUpdate.h | 22 ---------- .../MeshSyncClientBlender.cpp | 1 - .../MeshSyncClientBlender/msblenContext.cpp | 1 - .../msblenGeometryNodes.cpp | 1 - 6 files changed, 5 insertions(+), 67 deletions(-) delete mode 100644 Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyDepsgraphUpdate.cpp delete mode 100644 Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyDepsgraphUpdate.h diff --git a/Plugins~/CMakeLists.txt b/Plugins~/CMakeLists.txt index 064f0a06..4578665c 100644 --- a/Plugins~/CMakeLists.txt +++ b/Plugins~/CMakeLists.txt @@ -53,7 +53,11 @@ include(UnityPackage) setup_unity_package_version() add_definitions(-DMESHSYNC_DCC_PLUGIN_VER="${UNITY_PACKAGE_VERSION}") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++17") +if(WIN32) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++17") +elseif(APPLE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") +endif() # Force Unicode character set add_definitions(-DUNICODE -D_UNICODE) diff --git a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyDepsgraphUpdate.cpp b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyDepsgraphUpdate.cpp deleted file mode 100644 index 6b489a02..00000000 --- a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyDepsgraphUpdate.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "BlenderPyDepsgraphUpdate.h" -#include "BlenderPyCommon.h" - -namespace blender { - - PropertyRNA* BlenderPyDepsgraphUpdate_updates = nullptr; - FunctionRNA* BlenderPyDepsgraphUpdate_id_type_updated = nullptr; - extern bContext* g_context; - - - CollectionPropertyRNA* get_property() { - return (CollectionPropertyRNA*)BlenderPyDepsgraphUpdate_updates; - } - - void blender::BlenderPyDepgraphUpdate::updates_begin(CollectionPropertyIterator* it, Depsgraph* graph) - { - PointerRNA rna; - rna.data = graph; - get_property()->begin(it, &rna); - } - - void blender::BlenderPyDepgraphUpdate::updates_next(CollectionPropertyIterator* it) - { - get_property()->next(it); - } - - void blender::BlenderPyDepgraphUpdate::updates_end(CollectionPropertyIterator* it) - { - get_property()->end(it); - } - - PointerRNA blender::BlenderPyDepgraphUpdate::updates_get(CollectionPropertyIterator* it) - { - return get_property()->get(it); - } - - bool blender::BlenderPyDepgraphUpdate::id_type_updated(int type, Depsgraph* graph) { - - return call(g_context, graph, BlenderPyDepsgraphUpdate_id_type_updated, type); - } -} diff --git a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyDepsgraphUpdate.h b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyDepsgraphUpdate.h deleted file mode 100644 index ad545d87..00000000 --- a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyDepsgraphUpdate.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include //bContext -#include "MeshUtils/muMath.h" -#include -#include - -namespace blender -{ - class BlenderPyDepgraphUpdate - { - public: - - void updates_begin(CollectionPropertyIterator* it, Depsgraph* graph); - void updates_next(CollectionPropertyIterator* it); - void updates_end(CollectionPropertyIterator* it); - PointerRNA updates_get(CollectionPropertyIterator* it); - - bool id_type_updated(int type, Depsgraph* graph); - }; - -} // namespace blender diff --git a/Plugins~/Src/MeshSyncClientBlender/MeshSyncClientBlender.cpp b/Plugins~/Src/MeshSyncClientBlender/MeshSyncClientBlender.cpp index 877ec126..b9288ec7 100644 --- a/Plugins~/Src/MeshSyncClientBlender/MeshSyncClientBlender.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/MeshSyncClientBlender.cpp @@ -1,7 +1,6 @@ #include "pch.h" #include "msblenBinder.h" #include "msblenContext.h" -#include "BlenderPyObjects/BlenderPyDepsgraphUpdate.h" #include "BlenderPyObjects/BlenderPyContext.h" #include "MeshSyncClient/ExportTarget.h" diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index bb497d6f..fb14cf1a 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -16,7 +16,6 @@ #include "BlenderPyObjects/BlenderPyScene.h" //BlenderPyScene #include "BlenderPyObjects/BlenderPyNodeTree.h" -#include "BlenderPyObjects/BlenderPyDepsgraphUpdate.h" #include "DNA_node_types.h" #include diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp index 302970ef..6231a076 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp @@ -1,5 +1,4 @@ #include "msblenGeometryNodes.h" -#include "BlenderPyObjects/BlenderPyDepsgraphUpdate.h" #include #include #include From 0f7582e834695ab85ecbe7b3548a9a0da68b446f Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Thu, 10 Mar 2022 20:06:34 +0000 Subject: [PATCH 27/67] Removed unused extern properties that caused importation errors --- Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp index 7cc8e07a..99735b7e 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp @@ -76,9 +76,6 @@ extern PropertyRNA* BlenderPyNodeTree_inputs; extern PropertyRNA* BlenderPyNodeTree_nodes; extern PropertyRNA* BlenderPyNodeTree_outputs; -extern PropertyRNA* BlenderPyDepsgraphUpdate_updates; -extern FunctionRNA* BlenderPyDepsgraphUpdate_id_type_updated; - bool ready() { return g_context != nullptr; @@ -212,17 +209,11 @@ void setup(py::object bpy_context) if (match_prop("object_instances")) { BlenderPyContext_depsgraph_object_instances = prop; } - if (match_prop("updates")) { - BlenderPyDepsgraphUpdate_updates = prop; - } } each_func{ if (match_func("update")) { BlenderPyContext_depsgraph_update = func; } - if (match_func("id_type_updated")) { - BlenderPyDepsgraphUpdate_id_type_updated = func; - } } } else if (match_type("DepsgraphObjectInstance")) { From 78b183c5a907d1758188006fcf5cff7d5c54db1d Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Mon, 14 Mar 2022 15:27:06 +0000 Subject: [PATCH 28/67] Fix for compiation issues --- .../Include/MeshSyncClient/SettingsUtility.h | 4 ++-- Plugins~/Src/MeshSyncClient/SettingsUtility.cpp | 17 ++++++++--------- .../Src/MeshSyncClientBlender/msblenContext.cpp | 9 +++++---- .../Src/MeshSyncClientBlender/msblenContext.h | 2 +- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/SettingsUtility.h b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/SettingsUtility.h index cf305b5d..3e7dd420 100644 --- a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/SettingsUtility.h +++ b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/SettingsUtility.h @@ -1,7 +1,7 @@ #pragma once namespace ms { - struct OSceneCacheSettings; + struct SceneCacheOutputSettings; } namespace MeshSyncClient { @@ -13,7 +13,7 @@ class SettingsUtility { public: static void ApplyCacheToSyncSettings(const BaseCacheSettings& cacheSettings, BaseSyncSettings* syncSettings); - static ms::OSceneCacheSettings CreateOSceneCacheSettings(float sampleRate, const BaseCacheSettings& cacheSettings); + static ms::SceneCacheOutputSettings CreateOSceneCacheSettings(float sampleRate, const BaseCacheSettings& cacheSettings); }; diff --git a/Plugins~/Src/MeshSyncClient/SettingsUtility.cpp b/Plugins~/Src/MeshSyncClient/SettingsUtility.cpp index 55a1b01f..675c5274 100644 --- a/Plugins~/Src/MeshSyncClient/SettingsUtility.cpp +++ b/Plugins~/Src/MeshSyncClient/SettingsUtility.cpp @@ -1,7 +1,6 @@ #pragma once -#include "MeshSync/SceneCache/msSceneCacheSettings.h" //OSceneCacheSettings - +#include "MeshSync/SceneCache/msSceneCacheOutputSettings.h" //SceneCacheOuputSettings #include "MeshSyncClient/SettingsUtility.h" #include "MeshSyncClient/BaseCacheSettings.h" @@ -21,13 +20,13 @@ void SettingsUtility::ApplyCacheToSyncSettings(const BaseCacheSettings& cacheSet //---------------------------------------------------------------------------------------------------------------------- -ms::OSceneCacheSettings SettingsUtility::CreateOSceneCacheSettings(float sampleRate, const BaseCacheSettings& cacheSettings) { - ms::OSceneCacheSettings oscs; - oscs.sample_rate = sampleRate; - oscs.encoder_settings.zstd.compression_level = cacheSettings.zstd_compression_level; - oscs.flatten_hierarchy = cacheSettings.flatten_hierarchy; - oscs.strip_normals = cacheSettings.strip_normals; - oscs.strip_tangents = cacheSettings.strip_tangents; +ms::SceneCacheOutputSettings SettingsUtility::CreateOSceneCacheSettings(float sampleRate, const BaseCacheSettings& cacheSettings) { + ms::SceneCacheOutputSettings oscs; + oscs.exportSettings.sampleRate = sampleRate; + oscs.exportSettings.encoderSettings.zstd.compressionLevel = cacheSettings.zstd_compression_level; + oscs.exportSettings.flattenHierarchy = cacheSettings.flatten_hierarchy; + oscs.exportSettings.stripNormals = cacheSettings.strip_normals; + oscs.exportSettings.stripTangents = cacheSettings.strip_tangents; return oscs; } diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index fb14cf1a..34594a60 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -13,6 +13,7 @@ #include "BlenderUtility.h" //ApplyMeshUV #include "MeshSyncClient/SettingsUtility.h" #include "MeshSyncClient/SceneCacheUtility.h" +#include "MeshSync/SceneCache/msSceneCacheOutputSettings.h" #include "BlenderPyObjects/BlenderPyScene.h" //BlenderPyScene #include "BlenderPyObjects/BlenderPyNodeTree.h" @@ -1520,9 +1521,9 @@ bool msblenContext::ExportCache(const std::string& path, const BlenderCacheSetti m_settings.curves_as_mesh = cache_settings.curves_as_mesh; SettingsUtility::ApplyCacheToSyncSettings(cache_settings, &m_settings); - const ms::OSceneCacheSettings oscs = SettingsUtility::CreateOSceneCacheSettings(frameRate, cache_settings); + const ms::SceneCacheOutputSettings oscs = SettingsUtility::CreateOSceneCacheSettings(frameRate, cache_settings); const std::string destPath = SceneCacheUtility::BuildFilePath(path); - if (!m_cache_writer.open(destPath.c_str(), oscs)) { + if (!m_cache_writer.Open(destPath.c_str(), oscs)) { logInfo("MeshSync: Can't write scene cache to %s", destPath.c_str()); m_settings = settings_old; return false; @@ -1584,7 +1585,7 @@ bool msblenContext::ExportCache(const std::string& path, const BlenderCacheSetti logInfo("MeshSync: Finished writing scene cache to %s (%f) ms", destPath.c_str(), timer.elapsed()); m_settings = settings_old; - m_cache_writer.close(); + m_cache_writer.Close(); return true; } @@ -1635,7 +1636,7 @@ void msblenContext::WaitAndKickAsyncExport() sender->client_settings = m_settings.client_settings; } else if (ms::SceneCacheWriter* writer = dynamic_cast(exporter)) { - writer->time = m_anim_time; + writer->SetTime(m_anim_time); } ms::SceneExporter& t = *exporter; diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h index 3460cbd5..6419e808 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h @@ -8,7 +8,7 @@ #include "MeshSync/msClient.h" #include "MeshSync/SceneExporter.h" #include "MeshSync/AsyncSceneSender.h" -#include "MeshSync/SceneCache/SceneCacheWriter.h" +#include "MeshSync/SceneCache/msSceneCacheWriter.h" #include "MeshSync/MeshSyncMacros.h" #include "MeshSyncClient/msEntityManager.h" From 471366f26dbc6e91283d172a3ab2ee7ed4c89f9f Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Tue, 15 Mar 2022 14:50:39 +0000 Subject: [PATCH 29/67] Support for Blender 3.1 --- .../python/3.1.0/unity_mesh_sync.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Plugins~/Src/MeshSyncClientBlender/python/3.1.0/unity_mesh_sync.py b/Plugins~/Src/MeshSyncClientBlender/python/3.1.0/unity_mesh_sync.py index 7516f4ac..d2b3baee 100644 --- a/Plugins~/Src/MeshSyncClientBlender/python/3.1.0/unity_mesh_sync.py +++ b/Plugins~/Src/MeshSyncClientBlender/python/3.1.0/unity_mesh_sync.py @@ -300,6 +300,15 @@ def DestroyMeshSyncContext(): import atexit atexit.register(DestroyMeshSyncContext) + +@persistent +def on_depsgraph_update_post(scene): + graph = bpy.context.evaluated_depsgraph_get() + msb_context.setup(bpy.context) + msb_context.OnDepsgraphUpdatePost(graph) + +bpy.app.handlers.depsgraph_update_post.append(on_depsgraph_update_post) +bpy.app.handlers.load_post.append(on_depsgraph_update_post) # --------------------------------------------------------------------------------------------------------------------- From 8fb890f7cb6e748a314712f43eba836472edce49 Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Wed, 16 Mar 2022 13:09:55 +0000 Subject: [PATCH 30/67] Used Shared Vector instead of std::Vector for instacing info transforms --- .../Src/MeshSyncClientBlender/msblenContext.cpp | 14 +++++++------- Plugins~/Src/MeshSyncClientBlender/msblenContext.h | 4 ++-- .../MeshSyncClientBlender/msblenGeometryNodes.cpp | 12 ++++++------ .../MeshSyncClientBlender/msblenGeometryNodes.h | 4 ++-- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index 34594a60..420cb298 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -1724,18 +1724,18 @@ void msblenContext::doExtactMeshDataWithoutObject(ms::MeshPtr msMesh, Mesh* mesh msMesh->refine(); } -void msblenContext::exportInstances(std::string str, std::vector mat) { +void msblenContext::exportInstances(std::string str, SharedVector mat) { auto info = ms::InstanceInfo::create(); info->path = str; - info->transforms = mat; + info->transforms = std::move(mat); info->type = ms::InstanceInfo::ReferenceType::ENTITY_PATH; // If an object that is added has been marked for deletion // it will be removed from the deletion list - m_instances_manager.add(std::move(info)); + m_instances_manager.add(info); } -void msblenContext::exportInstancesWithMesh(Mesh* mesh, std::vector mat) +void msblenContext::exportInstancesWithMesh(Mesh* mesh, SharedVector mat) { auto msMesh = ms::Mesh::create(); @@ -1744,12 +1744,12 @@ void msblenContext::exportInstancesWithMesh(Mesh* mesh, std::vectortype = ms::InstanceInfo::ReferenceType::MESH_PATH; info->path = msMesh->path; - info->transforms = mat; + info->transforms = std::move(mat); // If an object that is added has been marked for deletion // it will be removed from the deletion list - m_instances_manager.add(std::move(info)); - m_instances_manager.add(std::move(msMesh)); + m_instances_manager.add(info); + m_instances_manager.add(msMesh); } #endif diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h index 6419e808..56d1d082 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h @@ -178,8 +178,8 @@ class msblenContext { #if BLENDER_VERSION >= 300 void doExtactMeshDataWithoutObject(ms::MeshPtr, Mesh*); - void exportInstances(std::string, std::vector); - void exportInstancesWithMesh(Mesh* mesh, std::vector); + void exportInstances(std::string, SharedVector); + void exportInstancesWithMesh(Mesh* mesh, SharedVector); #endif private: diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp index 6231a076..a09d5802 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp @@ -127,10 +127,10 @@ namespace blender { } void GeometryNodesUtils::foreach_instance( - std::function)> pathHandler, - std::function)> meshHandler) { - map> pathMap; - map> meshMap; + std::function)> pathHandler, + std::function)> meshHandler) { + map> pathMap; + map> meshMap; foreach_instance([&](string name, float4x4 matrix) { pathMap[name].push_back(matrix); }, [&](Mesh* mesh, float4x4 matrix) { @@ -138,10 +138,10 @@ namespace blender { }); for (auto& entry : pathMap) { - pathHandler(entry.first, entry.second); + pathHandler(entry.first, std::move(entry.second)); } for (auto& entry : meshMap) { - meshHandler(entry.first, entry.second); + meshHandler(entry.first, std::move(entry.second)); } } diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h index 3ce6ed6a..0401f0ce 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h @@ -33,8 +33,8 @@ namespace blender { std::function meshHandler); static void foreach_instance( - std::function)> pathHandler, - std::function)> meshHandler); + std::function)> pathHandler, + std::function)> meshHandler); void setInstancesDirty(bool dirty); bool getInstancesDirty(); From 68cad81e772f9e5d481344550d63cac989d6494a Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Tue, 22 Mar 2022 16:56:47 +0000 Subject: [PATCH 31/67] Geometry Nodes: Refactored how objects are accessed so objects outside the scene can be used. Refactored export callbacks for reusing exportation code for geometry node object inputs --- .../Include/MeshSyncClient/msEntityManager.h | 3 +- .../MeshSyncClient/msInstancesManager.h | 13 +- .../MeshSyncClient/msTransformManager.h | 12 ++ .../Src/MeshSyncClient/msInstancesManager.cpp | 37 +++-- .../MeshSyncClientBlender/msblenContext.cpp | 154 +++++++----------- .../Src/MeshSyncClientBlender/msblenContext.h | 25 +-- .../msblenGeometryNodes.cpp | 63 +++---- .../msblenGeometryNodes.h | 8 +- 8 files changed, 141 insertions(+), 174 deletions(-) create mode 100644 Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msTransformManager.h diff --git a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msEntityManager.h b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msEntityManager.h index e0e57d45..7f9a57a7 100644 --- a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msEntityManager.h +++ b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msEntityManager.h @@ -1,5 +1,6 @@ #pragma once #include "MeshSync/MeshSync.h" //msDeclClassPtr +#include "msTransformManager.h" msDeclStructPtr(Identifier) msDeclClassPtr(Transform) @@ -7,7 +8,7 @@ msDeclClassPtr(Transform) #ifndef msRuntime namespace ms { -class EntityManager +class EntityManager : public TransformManager { public: EntityManager(); diff --git a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h index ebba8edb..338d854e 100644 --- a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h +++ b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h @@ -4,6 +4,7 @@ #include "MeshSync/SceneGraph/msIdentifier.h" #include #include +#include "msTransformManager.h" #ifndef msRuntime @@ -11,7 +12,7 @@ msDeclClassPtr(InstanceInfo) namespace ms { - class InstancesManager + class InstancesManager : public TransformManager { public: std::vector getDirtyMeshes(); @@ -23,22 +24,28 @@ namespace ms { void add(TransformPtr mesh); void clear(); void deleteAll(); + void touch(const std::string& path) { ; } void setAlwaysMarkDirty(bool alwaysDirty); private: + struct Record { bool dirtyInstances = false; bool dirtyMesh = false; - InstanceInfoPtr instances; - TransformPtr mesh; + InstanceInfoPtr instances = nullptr; + TransformPtr mesh = nullptr; }; std::map m_records; std::vector m_deleted_instanceInfo; std::vector m_deleted_meshes; bool m_always_mark_dirty; + + std::mutex m_mutex; + + Record& lockAndGet(const std::string& path); }; diff --git a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msTransformManager.h b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msTransformManager.h new file mode 100644 index 00000000..632ab7e0 --- /dev/null +++ b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msTransformManager.h @@ -0,0 +1,12 @@ +#pragma once + +#include "pch.h" +#include "MeshSync/MeshSync.h" + +namespace ms{ + class TransformManager { + public: + virtual void add(TransformPtr transform) = 0; + virtual void touch(const std::string& path) = 0; + }; +} \ No newline at end of file diff --git a/Plugins~/Src/MeshSyncClient/msInstancesManager.cpp b/Plugins~/Src/MeshSyncClient/msInstancesManager.cpp index fedb05ed..db96464f 100644 --- a/Plugins~/Src/MeshSyncClient/msInstancesManager.cpp +++ b/Plugins~/Src/MeshSyncClient/msInstancesManager.cpp @@ -49,14 +49,8 @@ namespace ms { } void InstancesManager::add(TransformPtr mesh) { - - auto path = mesh->path; - auto it = std::find_if(m_deleted_meshes.begin(), m_deleted_meshes.end(), [&path](Identifier& v) { return v.name == path; }); - if (it != m_deleted_meshes.end()) { - m_deleted_meshes.erase(it); - } - auto& rec = m_records[path]; + auto& rec = lockAndGet(mesh->path); if (m_always_mark_dirty || rec.mesh == nullptr || rec.mesh->hash() != mesh->hash()) { rec.dirtyMesh = true; @@ -65,16 +59,11 @@ namespace ms { rec.mesh = mesh; } + + void InstancesManager::add(InstanceInfoPtr info) { - auto path = info->path; - - auto it = std::find_if(m_deleted_instanceInfo.begin(), m_deleted_instanceInfo.end(), [&path](Identifier& v) { return v.name == path; }); - if (it != m_deleted_instanceInfo.end()) { - m_deleted_instanceInfo.erase(it); - } - - auto& rec = m_records[path]; + auto& rec = lockAndGet(info->path); //TODO implement hash for InstanceInfo and check if (m_always_mark_dirty || rec.instances == nullptr) { @@ -103,4 +92,22 @@ namespace ms { void InstancesManager::setAlwaysMarkDirty(bool alwaysDirty) { m_always_mark_dirty = alwaysDirty; } + + InstancesManager::Record& InstancesManager::lockAndGet(const std::string& path) + { + std::unique_lock lock(m_mutex); + if (!m_deleted_meshes.empty()) { + auto it = std::find_if(m_deleted_meshes.begin(), m_deleted_meshes.end(), [&path](Identifier& v) { return v.name == path; }); + if (it != m_deleted_meshes.end()) + m_deleted_meshes.erase(it); + } + + if (!m_deleted_instanceInfo.empty()) { + auto it = std::find_if(m_deleted_instanceInfo.begin(), m_deleted_instanceInfo.end(), [&path](Identifier& v) { return v.name == path; }); + if (it != m_deleted_instanceInfo.end()) + m_deleted_instanceInfo.erase(it); + } + + return m_records[path]; + } } diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index 64f6cfe8..80967891 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -394,22 +394,21 @@ void msblenContext::extractLightData(const Object *src, } -ms::TransformPtr msblenContext::exportObject(const Object *obj, bool parent, bool tip) -{ +ms::TransformPtr msblenContext::exportObject(const Object* obj, bool parent,ms::TransformManager& manager, bool tip) { if (!obj) return nullptr; - msblenContext::ObjectRecord& rec = touchRecord(obj); + msblenContext::ObjectRecord& rec = touchRecord(manager, obj); if (rec.dst) return rec.dst; // already exported auto handle_parent = [&]() { if (parent) - exportObject(obj->parent, parent, false); + exportObject(obj->parent, parent, manager, false); }; auto handle_transform = [&]() { handle_parent(); - rec.dst = exportTransform(obj); + rec.dst = exportTransform(obj, manager); }; switch (obj->type) { @@ -417,7 +416,7 @@ ms::TransformPtr msblenContext::exportObject(const Object *obj, bool parent, boo { if (!tip || (!m_settings.BakeModifiers && m_settings.sync_bones)) { handle_parent(); - rec.dst = exportArmature(obj); + rec.dst = exportArmature(obj, manager); } else if (!tip && parent) handle_transform(); @@ -426,12 +425,12 @@ ms::TransformPtr msblenContext::exportObject(const Object *obj, bool parent, boo case OB_MESH: { if (!m_settings.BakeModifiers && m_settings.sync_bones) { - if (auto *arm_mod = (const ArmatureModifierData*)FindModifier(obj, eModifierType_Armature)) - exportObject(arm_mod->object, parent); + if (auto* arm_mod = (const ArmatureModifierData*)FindModifier(obj, eModifierType_Armature)) + exportObject(arm_mod->object, parent, manager); } if (m_settings.sync_meshes || (!m_settings.BakeModifiers && m_settings.sync_blendshapes)) { handle_parent(); - rec.dst = exportMesh(obj); + rec.dst = exportMesh(obj, manager); } else if (!tip && parent) handle_transform(); @@ -444,7 +443,7 @@ ms::TransformPtr msblenContext::exportObject(const Object *obj, bool parent, boo { if (m_settings.sync_meshes && m_settings.curves_as_mesh) { handle_parent(); - rec.dst = exportMesh(obj); + rec.dst = exportMesh(obj, manager); } else if (!tip && parent) handle_transform(); @@ -454,7 +453,7 @@ ms::TransformPtr msblenContext::exportObject(const Object *obj, bool parent, boo { if (m_settings.sync_cameras) { handle_parent(); - rec.dst = exportCamera(obj); + rec.dst = exportCamera(obj, manager); } else if (!tip && parent) handle_transform(); @@ -464,7 +463,7 @@ ms::TransformPtr msblenContext::exportObject(const Object *obj, bool parent, boo { if (m_settings.sync_lights) { handle_parent(); - rec.dst = exportLight(obj); + rec.dst = exportLight(obj, manager); } else if (!tip && parent) handle_transform(); @@ -474,7 +473,7 @@ ms::TransformPtr msblenContext::exportObject(const Object *obj, bool parent, boo { if (get_instance_collection(obj) || (!tip && parent)) { handle_parent(); - rec.dst = exportTransform(obj); + rec.dst = exportTransform(obj, manager); } break; } @@ -486,51 +485,57 @@ ms::TransformPtr msblenContext::exportObject(const Object *obj, bool parent, boo ctx.group_host = obj; ctx.dst = rec.dst; - exportDupliGroup(obj, ctx); + exportDupliGroup(obj, ctx, manager); } } return rec.dst; } -ms::TransformPtr msblenContext::exportTransform(const Object *src) +ms::TransformPtr msblenContext::exportObject(const Object *obj, bool parent, bool tip) +{ + return exportObject(obj, parent, m_entity_manager, tip); +} + +ms::TransformPtr msblenContext::exportTransform(const Object *src, ms::TransformManager& manager) { std::shared_ptr ret = ms::Transform::create(); ms::Transform& dst = *ret; dst.path = get_path(src); extractTransformData(src, dst); - m_entity_manager.add(ret); + manager.add(ret); + return ret; } -ms::TransformPtr msblenContext::exportPose(const Object *armature, bPoseChannel *src) +ms::TransformPtr msblenContext::exportPose(const Object *armature, bPoseChannel *src, ms::TransformManager& manager) { std::shared_ptr ret = ms::Transform::create(); ms::Transform& dst = *ret; dst.path = get_path(armature, src->bone); extractTransformData(src, dst.position, dst.rotation, dst.scale); - m_entity_manager.add(ret); + manager.add(ret); return ret; } -ms::TransformPtr msblenContext::exportArmature(const Object *src) +ms::TransformPtr msblenContext::exportArmature(const Object *src, ms::TransformManager& manager) { std::shared_ptr ret = ms::Transform::create(); ms::Transform& dst = *ret; dst.path = get_path(src); extractTransformData(src, dst); - m_entity_manager.add(ret); + manager.add(ret); for (struct bPoseChannel* pose : bl::list_range((bPoseChannel*)src->pose->chanbase.first)) { struct Bone* bone = pose->bone; std::map>::mapped_type& dst = m_bones[bone]; - dst = exportPose(src, pose); + dst = exportPose(src, pose, manager); } return ret; } -ms::TransformPtr msblenContext::exportReference(Object *src, const DupliGroupContext& ctx) +ms::TransformPtr msblenContext::exportReference(Object *src, const DupliGroupContext& ctx, ms::TransformManager& manager) { - msblenContext::ObjectRecord& rec = touchRecord(src); + msblenContext::ObjectRecord& rec = touchRecord(manager, src); if (!rec.dst) return nullptr; @@ -555,14 +560,14 @@ ms::TransformPtr msblenContext::exportReference(Object *src, const DupliGroupCon (ms::Transform&)dst_mesh = (ms::Transform&)src_mesh; assign_base_params(); - auto do_merge = [this, dst, &dst_mesh, &src_mesh]() { + auto do_merge = [this, dst, &dst_mesh, &src_mesh, &manager]() { dst_mesh.merge(src_mesh); if (m_settings.ExportSceneCache) dst_mesh.detach(); dst_mesh.refine_settings = src_mesh.refine_settings; dst_mesh.refine_settings.local2world = dst_mesh.world_matrix; dst_mesh.refine_settings.flags.Set(ms::MESH_REFINE_FLAG_LOCAL2WORLD, true); - m_entity_manager.add(dst); + manager.add(dst); }; if (m_settings.multithreaded) // deferred to execute after extracting src mesh data is completed @@ -574,17 +579,17 @@ ms::TransformPtr msblenContext::exportReference(Object *src, const DupliGroupCon dst = ms::Transform::create(); assign_base_params(); dst->reference = local_path; - m_entity_manager.add(dst); + manager.add(dst); } } else { dst = std::static_pointer_cast(rec.dst->clone()); assign_base_params(); - m_entity_manager.add(dst); + manager.add(dst); } each_child(src, [&](Object *child) { - exportReference(child, ctx); + exportReference(child, ctx, manager); }); if (get_instance_collection(src)) { @@ -592,12 +597,12 @@ ms::TransformPtr msblenContext::exportReference(Object *src, const DupliGroupCon ctx2.group_host = src; ctx2.dst = dst; - exportDupliGroup(src, ctx2); + exportDupliGroup(src, ctx2, manager); } return dst; } -ms::TransformPtr msblenContext::exportDupliGroup(const Object *src, const DupliGroupContext& ctx) +ms::TransformPtr msblenContext::exportDupliGroup(const Object *src, const DupliGroupContext& ctx, ms::TransformManager& manager) { Collection* group = get_instance_collection(src); if (!group) @@ -613,7 +618,7 @@ ms::TransformPtr msblenContext::exportDupliGroup(const Object *src, const DupliG const mu::tvec3 offset_pos = -get_instance_offset(group); dst->position = m_settings.BakeTransform ? mu::float3::zero() : offset_pos; dst->world_matrix = mu::translate(offset_pos) * ctx.dst->world_matrix; - m_entity_manager.add(dst); + manager.add(dst); DupliGroupContext ctx2; ctx2.group_host = src; @@ -625,35 +630,35 @@ ms::TransformPtr msblenContext::exportDupliGroup(const Object *src, const DupliG const bool non_lib = obj->id.lib == nullptr; t->visibility = { true, non_lib, non_lib }; } - exportReference(obj, ctx2); + exportReference(obj, ctx2, manager); } return dst; } -ms::CameraPtr msblenContext::exportCamera(const Object *src) +ms::CameraPtr msblenContext::exportCamera(const Object *src, ms::TransformManager& manager) { std::shared_ptr ret = ms::Camera::create(); ms::Camera& dst = *ret; dst.path = get_path(src); extractTransformData(src, dst); extractCameraData(src, dst.is_ortho, dst.near_plane, dst.far_plane, dst.fov, dst.focal_length, dst.sensor_size, dst.lens_shift); - m_entity_manager.add(ret); + manager.add(ret); return ret; } -ms::LightPtr msblenContext::exportLight(const Object *src) +ms::LightPtr msblenContext::exportLight(const Object *src, ms::TransformManager& manager) { std::shared_ptr ret = ms::Light::create(); ms::Light& dst = *ret; dst.path = get_path(src); extractTransformData(src, dst); extractLightData(src, dst.light_type, dst.shadow_type, dst.color, dst.intensity, dst.range, dst.spot_angle); - m_entity_manager.add(ret); + manager.add(ret); return ret; } -ms::MeshPtr msblenContext::exportMesh(const Object *src) +ms::MeshPtr msblenContext::exportMesh(const Object *src, ms::TransformManager& manager) { // ignore particles if (//FindModifier(src, eModifierType_ParticleSystem) || @@ -713,10 +718,10 @@ ms::MeshPtr msblenContext::exportMesh(const Object *src) } if (data) { - auto task = [this, ret, src, data]() { + auto task = [this, ret, src, data, &manager]() { auto& dst = *ret; doExtractMeshData(dst, src, data, dst.world_matrix); - m_entity_manager.add(ret); + manager.add(ret); }; if (m_settings.multithreaded) @@ -1105,7 +1110,11 @@ ms::TransformPtr msblenContext::findBone(Object *armature, Bone *bone) return it != m_bones.end() ? it->second : nullptr; } -msblenContext::ObjectRecord& msblenContext::touchRecord(const Object *obj, const std::string& base_path, bool children) +msblenContext::ObjectRecord& msblenContext::touchRecord(const Object* obj, const std::string& base_path, bool children) { + return touchRecord(m_entity_manager, obj, base_path, children); +} + +msblenContext::ObjectRecord& msblenContext::touchRecord(ms::TransformManager& manager, const Object *obj, const std::string& base_path, bool children) { std::map::mapped_type& rec = m_obj_records[obj]; if (rec.touched && base_path.empty()) @@ -1119,32 +1128,32 @@ msblenContext::ObjectRecord& msblenContext::touchRecord(const Object *obj, const rec.path = local_path; } std::string path = base_path + local_path; - m_entity_manager.touch(path); + manager.touch(path); // trace bones if (is_armature(obj)) { blender::blist_range poses = bl::list_range((bPoseChannel*)obj->pose->chanbase.first); for (struct bPoseChannel* pose : poses) { m_obj_records[pose->bone].touched = true; - m_entity_manager.touch(base_path + get_path(obj, pose->bone)); + manager.touch(base_path + get_path(obj, pose->bone)); } } // care children if (children) { each_child(obj, [&](Object *child) { - touchRecord(child, base_path, true); + touchRecord(manager, child, base_path, true); }); } // trace dupli group if (Collection* group = get_instance_collection(obj)) { const std::string group_path = path + '/' + (group->id.name + 2); - m_entity_manager.touch(group_path); + manager.touch(group_path); auto gobjects = bl::list_range((CollectionObject*)group->gobject.first); for (auto go : gobjects) - touchRecord(go->ob, group_path, true); + touchRecord(manager, go->ob, group_path, true); } return rec; } @@ -1440,8 +1449,7 @@ bool msblenContext::sendObjects(MeshSyncClient::ObjectScope scope, bool dirty_al m_instances_manager.setAlwaysMarkDirty(true); auto instancesHandler = std::bind(&msblenContext::exportInstances, this, std::placeholders::_1, std::placeholders::_2); - auto instancesWithMeshHandler = std::bind(&msblenContext::exportInstancesWithMesh, this, std::placeholders::_1, std::placeholders::_2); - blender::GeometryNodesUtils::foreach_instance(instancesHandler, instancesWithMeshHandler); + blender::GeometryNodesUtils::foreach_instance(instancesHandler); m_geometryNodeUtils.setInstancesDirty(false); } @@ -1663,6 +1671,7 @@ void msblenContext::WaitAndKickAsyncExport() ms::ScaleConverter cv(scale_factor); for (std::vector>::value_type& obj : t.transforms) { cv.convert(*obj); } for (std::vector>::value_type& obj : t.geometries) { cv.convert(*obj); } + for (std::vector>::value_type& obj : t.instanceMeshes) { cv.convert(*obj); } for (std::vector>::value_type& obj : t.animations) { cv.convert(*obj); } } }; @@ -1694,41 +1703,13 @@ void msblenContext::onDepsgraphUpdatedPost(Depsgraph* graph) /// Geometry Nodes Blender Context Functionality /// #if BLENDER_VERSION >= 300 -void msblenContext::doExtactMeshDataWithoutObject(ms::MeshPtr msMesh, Mesh* mesh) -{ - BlenderSyncSettings meshExtractionSettings; - meshExtractionSettings.sync_meshes = true; - meshExtractionSettings.sync_normals = true; - meshExtractionSettings.sync_uvs = true; - meshExtractionSettings.sync_colors = true; - meshExtractionSettings.sync_bones = false; - - auto path = std::string(mesh->id.name); - path += std::to_string(mesh->id.session_uuid); - - - doExtractNonEditMeshData(*(msMesh), nullptr, mesh, meshExtractionSettings); - - if (msMesh->normals.empty()) - msMesh->refine_settings.flags.Set(ms::MESH_REFINE_FLAG_GEN_NORMALS, true); - if (msMesh->tangents.empty()) - msMesh->refine_settings.flags.Set(ms::MESH_REFINE_FLAG_GEN_TANGENTS, true); - msMesh->path = path; - msMesh->world_matrix = mu::float4x4::identity(); - msMesh->local_matrix = mu::float4x4::identity(); - msMesh->visibility.active = false; +void msblenContext::exportInstances(Object* object, SharedVector mat) { - msMesh->refine_settings.local2world = m_geometryNodeUtils.blenderToUnityWorldMatrixMesh(); - msMesh->refine_settings.flags.Set(ms::MeshRefineFlagsBit::MESH_REFINE_FLAG_LOCAL2WORLD, true); - msMesh->refine_settings.flags.Set(ms::MeshRefineFlagsBit::MESH_REFINE_FLAG_FLIP_FACES, true); + exportObject(object, false, m_instances_manager); - msMesh->refine(); -} - -void msblenContext::exportInstances(std::string str, SharedVector mat) { auto info = ms::InstanceInfo::create(); - info->path = str; + info->path = get_path(object); info->transforms = std::move(mat); info->type = ms::InstanceInfo::ReferenceType::ENTITY_PATH; @@ -1736,22 +1717,5 @@ void msblenContext::exportInstances(std::string str, SharedVector // it will be removed from the deletion list m_instances_manager.add(info); } - -void msblenContext::exportInstancesWithMesh(Mesh* mesh, SharedVector mat) -{ - auto msMesh = ms::Mesh::create(); - - doExtactMeshDataWithoutObject(msMesh, mesh); - - auto info = ms::InstanceInfo::create(); - info->type = ms::InstanceInfo::ReferenceType::MESH_PATH; - info->path = msMesh->path; - info->transforms = std::move(mat); - - // If an object that is added has been marked for deletion - // it will be removed from the deletion list - m_instances_manager.add(info); - m_instances_manager.add(msMesh); -} #endif diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h index 56d1d082..ab8ab4a4 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h @@ -22,10 +22,13 @@ #include "msblenGeometryNodes.h" #include "MeshSyncClient/msInstancesManager.h" +#include "MeshSyncClient/msTransformManager.h" #if BLENDER_VERSION >= 300 #include #endif +#include +#include class msblenContext; @@ -130,14 +133,15 @@ class msblenContext { ms::TransformPtr exportObject(const Object *obj, bool parent, bool tip = true); - ms::TransformPtr exportTransform(const Object *obj); - ms::TransformPtr exportPose(const Object *armature, bPoseChannel *obj); - ms::TransformPtr exportArmature(const Object *obj); - ms::TransformPtr exportReference(Object *obj, const DupliGroupContext& ctx); - ms::TransformPtr exportDupliGroup(const Object *obj, const DupliGroupContext& ctx); - ms::CameraPtr exportCamera(const Object *obj); - ms::LightPtr exportLight(const Object *obj); - ms::MeshPtr exportMesh(const Object *obj); + ms::TransformPtr exportObject(const Object* obj, bool parent, ms::TransformManager& manager, bool tip = true); + ms::TransformPtr exportTransform(const Object *obj, ms::TransformManager& manager); + ms::TransformPtr exportPose(const Object *armature, bPoseChannel *obj, ms::TransformManager& manager); + ms::TransformPtr exportArmature(const Object *obj, ms::TransformManager& manager); + ms::TransformPtr exportReference(Object *obj, const DupliGroupContext& ctx, ms::TransformManager& manager); + ms::TransformPtr exportDupliGroup(const Object *obj, const DupliGroupContext& ctx, ms::TransformManager& manager); + ms::CameraPtr exportCamera(const Object *obj, ms::TransformManager& manager); + ms::LightPtr exportLight(const Object *obj, ms::TransformManager& manager); + ms::MeshPtr exportMesh(const Object *obj, ms::TransformManager& manager); mu::float4x4 getWorldMatrix(const Object *obj); mu::float4x4 getLocalMatrix(const Object *obj); @@ -164,6 +168,7 @@ class msblenContext { ms::TransformPtr findBone(Object *armature, Bone *bone); ObjectRecord& touchRecord(const Object *obj, const std::string& base_path = "", bool children = false); + ObjectRecord& touchRecord(ms::TransformManager& manager, const Object* obj, const std::string& base_path = "", bool children = false); void eraseStaleObjects(); void exportAnimation(Object *obj, bool force, const std::string& base_path = ""); @@ -177,9 +182,7 @@ class msblenContext { void WaitAndKickAsyncExport(); #if BLENDER_VERSION >= 300 - void doExtactMeshDataWithoutObject(ms::MeshPtr, Mesh*); - void exportInstances(std::string, SharedVector); - void exportInstancesWithMesh(Mesh* mesh, SharedVector); + void exportInstances(Object* object, SharedVector); #endif private: diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp index a09d5802..70f0d5b4 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp @@ -5,6 +5,7 @@ #include "BlenderPyObjects/BlenderPyNodeTree.h" #include "BlenderPyObjects/BlenderPyScene.h" #include +#include using namespace std; @@ -53,26 +54,10 @@ namespace blender { } - void GeometryNodesUtils::foreach_instance( - std::function pathHandler, - std::function meshHandler) + void GeometryNodesUtils::foreach_instance(std::function handler) { auto blContext = blender::BlenderPyContext::get(); - // Build a map between data and the objects they belong to - auto scene = blContext.scene(); - auto mscene = BlenderPyScene(scene); - - map dataToObject; - - mscene.each_objects([&](Object* obj) { - if (obj == nullptr || obj->data == nullptr) - return; - auto data_id = (ID*)obj->data; - dataToObject[data_id->name] = obj; - }); - - // BlenderPyContext is an interface between depsgraph operations and anything that interacts with it @@ -83,6 +68,8 @@ namespace blender { blContext.object_instances_begin(&it, depsgraph); + + for (; it.valid; blContext.object_instances_next(&it)) { // Get the instance as a Pointer RNA. auto instance = blContext.object_instances_get(&it); @@ -101,47 +88,37 @@ namespace blender { auto object = blContext.object_get(instance); - if (object->type != OB_MESH) + if (object->type != OB_MESH) { continue; - - auto data_id = (ID*)object->data; - auto hierarchyObject = dataToObject[data_id->name]; + } auto world_matrix = float4x4(); blContext.world_matrix_get(&instance, &world_matrix); auto unityMatrix = blenderToUnityWorldMatrix(world_matrix); - if (hierarchyObject == nullptr) { - auto mesh = (Mesh*)object->data; - meshHandler(move(mesh),move(unityMatrix)); - } - else { - auto path = get_path(hierarchyObject); - pathHandler(move(path), move(unityMatrix)); - } + handler(&object->id, move(unityMatrix)); } // Cleanup resources blContext.object_instances_end(&it); } - void GeometryNodesUtils::foreach_instance( - std::function)> pathHandler, - std::function)> meshHandler) { - map> pathMap; - map> meshMap; - foreach_instance([&](string name, float4x4 matrix) { - pathMap[name].push_back(matrix); - }, [&](Mesh* mesh, float4x4 matrix) { - meshMap[mesh].push_back(matrix); + void GeometryNodesUtils::foreach_instance(function)> handler) { + + map> transformsMap; + foreach_instance([&](ID* id, float4x4 matrix) { + transformsMap[id->name].push_back(matrix); }); - for (auto& entry : pathMap) { - pathHandler(entry.first, std::move(entry.second)); - } - for (auto& entry : meshMap) { - meshHandler(entry.first, std::move(entry.second)); + auto ctx = blender::BlenderPyContext::get(); + + auto objects = ctx.data()->objects; + LISTBASE_FOREACH(Object*, obj, &objects){ + auto result = transformsMap.find(obj->id.name); + if (result != transformsMap.end()) { + handler(obj, std::move(result->second)); + } } } diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h index 0401f0ce..c5a9bf12 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h @@ -28,13 +28,9 @@ namespace blender { /// of the instance in the Unity3D Coordinate system /// /// - static void foreach_instance( - std::function pathHandler, - std::function meshHandler); + static void foreach_instance(std::function transformHandler); - static void foreach_instance( - std::function)> pathHandler, - std::function)> meshHandler); + static void foreach_instance(std::function)> transformHandler); void setInstancesDirty(bool dirty); bool getInstancesDirty(); From 8a9f42288ebbce5746f8c140c86cfbe20b9e41ad Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Tue, 22 Mar 2022 17:00:13 +0000 Subject: [PATCH 32/67] Removed Object Instance ReferenceType from geometry nodes instances --- Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index 80967891..067d09eb 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -1711,10 +1711,7 @@ void msblenContext::exportInstances(Object* object, SharedVector m auto info = ms::InstanceInfo::create(); info->path = get_path(object); info->transforms = std::move(mat); - info->type = ms::InstanceInfo::ReferenceType::ENTITY_PATH; - // If an object that is added has been marked for deletion - // it will be removed from the deletion list m_instances_manager.add(info); } #endif From ebc9b2a49f472ba2edb1c8d0794ed8e6a58f9d6b Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Wed, 23 Mar 2022 17:14:38 +0000 Subject: [PATCH 33/67] Refactor: created a class that encapsulates the msblenContext state of bones, pending list and the transform manager. State objects are passed as arguments to export function for reusing export code with instances manager --- .../MeshSyncClient/msInstancesManager.h | 14 +- .../MeshSyncClient/msTransformManager.h | 25 ++ .../Src/MeshSyncClient/msInstancesManager.cpp | 54 ++-- .../MeshSyncClientBlender/msblenContext.cpp | 265 ++++++++---------- .../Src/MeshSyncClientBlender/msblenContext.h | 75 ++--- .../msblenContextState.cpp | 80 ++++++ .../msblenContextState.h | 47 ++++ 7 files changed, 323 insertions(+), 237 deletions(-) create mode 100644 Plugins~/Src/MeshSyncClientBlender/msblenContextState.cpp create mode 100644 Plugins~/Src/MeshSyncClientBlender/msblenContextState.h diff --git a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h index 338d854e..540f5ceb 100644 --- a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h +++ b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h @@ -17,14 +17,14 @@ namespace ms { public: std::vector getDirtyMeshes(); std::vector getDirtyInstances(); - std::vector& getDeletedInstanceInfos(); - std::vector& getDeletedMeshes(); + std::vector& getDeleted(); void clearDirtyFlags(); void add(InstanceInfoPtr instanceInfo); void add(TransformPtr mesh); void clear(); - void deleteAll(); - void touch(const std::string& path) { ; } + void touch(const std::string& path); + + void eraseStaleEntities(); void setAlwaysMarkDirty(bool alwaysDirty); @@ -35,12 +35,12 @@ namespace ms { bool dirtyInstances = false; bool dirtyMesh = false; InstanceInfoPtr instances = nullptr; - TransformPtr mesh = nullptr; + TransformPtr entity = nullptr; + bool updated = false; }; std::map m_records; - std::vector m_deleted_instanceInfo; - std::vector m_deleted_meshes; + std::vector m_deleted; bool m_always_mark_dirty; std::mutex m_mutex; diff --git a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msTransformManager.h b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msTransformManager.h index 632ab7e0..92c38943 100644 --- a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msTransformManager.h +++ b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msTransformManager.h @@ -8,5 +8,30 @@ namespace ms{ public: virtual void add(TransformPtr transform) = 0; virtual void touch(const std::string& path) = 0; + virtual void eraseStaleEntities() = 0; + virtual void clear() = 0; + virtual void setAlwaysMarkDirty(bool flag) = 0; + + TransformManager() {} + ~TransformManager() {} + + TransformManager& operator=(const TransformManager& v) + { + return *this; + } + + + TransformManager(TransformManager&& v) + { + *this = std::move(v); + } + + TransformManager& operator=(TransformManager&& v) + { + + return *this; + } + + TransformManager(const TransformManager& v){ *this = v; } }; } \ No newline at end of file diff --git a/Plugins~/Src/MeshSyncClient/msInstancesManager.cpp b/Plugins~/Src/MeshSyncClient/msInstancesManager.cpp index db96464f..9b1c2ff1 100644 --- a/Plugins~/Src/MeshSyncClient/msInstancesManager.cpp +++ b/Plugins~/Src/MeshSyncClient/msInstancesManager.cpp @@ -10,7 +10,7 @@ namespace ms { for (auto& p : m_records) { Record& r = p.second; if (r.dirtyMesh) { - ret.push_back(r.mesh); + ret.push_back(r.entity); } } return ret; @@ -27,13 +27,8 @@ namespace ms { return ret; } - vector& InstancesManager::getDeletedInstanceInfos() - { - return m_deleted_instanceInfo; - } - - vector& InstancesManager::getDeletedMeshes() { - return m_deleted_meshes; + vector& InstancesManager::getDeleted() { + return m_deleted; } void InstancesManager::clearDirtyFlags() @@ -42,21 +37,22 @@ namespace ms { Record& r = p.second; r.dirtyInstances = false; r.dirtyMesh = false; + r.updated = false; } - m_deleted_instanceInfo.clear(); - m_deleted_meshes.clear(); + m_deleted.clear(); } void InstancesManager::add(TransformPtr mesh) { auto& rec = lockAndGet(mesh->path); - if (m_always_mark_dirty || rec.mesh == nullptr || rec.mesh->hash() != mesh->hash()) { + if (m_always_mark_dirty || rec.entity == nullptr || rec.entity->hash() != mesh->hash()) { rec.dirtyMesh = true; } - rec.mesh = mesh; + rec.updated = true; + rec.entity = mesh; } @@ -76,16 +72,24 @@ namespace ms { void InstancesManager::clear() { m_records.clear(); - m_deleted_instanceInfo.clear(); } - void InstancesManager::deleteAll() + void InstancesManager::touch(const std::string& path) + { + auto it = m_records.find(path); + if (it != m_records.end()) + it->second.updated = true; + } + + void InstancesManager::eraseStaleEntities() { - for (auto& record : m_records) { - m_deleted_instanceInfo.push_back(record.second.instances->getIdentifier()); - if (record.second.mesh != nullptr) { - m_deleted_meshes.push_back(record.second.mesh->getIdentifier()); + for (auto it = m_records.begin(); it != m_records.end(); ) { + if (!it->second.updated) { + m_deleted.push_back(it->second.entity->getIdentifier()); + m_records.erase(it++); } + else + ++it; } } @@ -96,16 +100,10 @@ namespace ms { InstancesManager::Record& InstancesManager::lockAndGet(const std::string& path) { std::unique_lock lock(m_mutex); - if (!m_deleted_meshes.empty()) { - auto it = std::find_if(m_deleted_meshes.begin(), m_deleted_meshes.end(), [&path](Identifier& v) { return v.name == path; }); - if (it != m_deleted_meshes.end()) - m_deleted_meshes.erase(it); - } - - if (!m_deleted_instanceInfo.empty()) { - auto it = std::find_if(m_deleted_instanceInfo.begin(), m_deleted_instanceInfo.end(), [&path](Identifier& v) { return v.name == path; }); - if (it != m_deleted_instanceInfo.end()) - m_deleted_instanceInfo.erase(it); + if (!m_deleted.empty()) { + auto it = std::find_if(m_deleted.begin(), m_deleted.end(), [&path](Identifier& v) { return v.name == path; }); + if (it != m_deleted.end()) + m_deleted.erase(it); } return m_records[path]; diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index 067d09eb..ac910269 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -60,35 +60,44 @@ void msblenContext::NodeRecord::recordAnimation(msblenContext *_this) const { } -void msblenContext::ObjectRecord::clearState() -{ - touched = renamed = false; - dst = nullptr; -} //---------------------------------------------------------------------------------------------------------------------- -msblenContext& msblenContext::getInstance() { - static msblenContext s_instance; - return s_instance; +static msblenContext* s_instance = nullptr; + +msblenContext& msblenContext::getInstance() +{ + if (s_instance == nullptr) { + s_instance = new msblenContext(); + } + + return *s_instance; } void msblenContext::Destroy() { m_texture_manager.clear(); m_material_manager.clear(); - m_entity_manager.clear(); - m_instances_manager.clear(); + + m_entities_state->clear(); + m_instances_state->clear(); + + delete s_instance; } msblenContext::msblenContext() { + m_entities_state = new msblenContextState(m_entity_manager); + m_instances_state = new msblenContextState(m_instances_manager); + m_settings.scene_settings.handedness = ms::Handedness::RightZUp; } msblenContext::~msblenContext() { + delete m_entities_state; + delete m_instances_state; // no wait() because it can cause deadlock... } @@ -393,22 +402,26 @@ void msblenContext::extractLightData(const Object *src, stype = (data->mode & 1) ? ms::Light::ShadowType::Soft : ms::Light::ShadowType::None; } +ms::TransformPtr msblenContext::exportObject( + msblenContextState& state, + const Object* obj, + bool parent, + bool tip) { -ms::TransformPtr msblenContext::exportObject(const Object* obj, bool parent,ms::TransformManager& manager, bool tip) { if (!obj) return nullptr; - msblenContext::ObjectRecord& rec = touchRecord(manager, obj); + msblenContextState::ObjectRecord& rec = state.touchRecord(obj); if (rec.dst) return rec.dst; // already exported auto handle_parent = [&]() { if (parent) - exportObject(obj->parent, parent, manager, false); + exportObject(state, obj->parent, parent, false); }; auto handle_transform = [&]() { handle_parent(); - rec.dst = exportTransform(obj, manager); + rec.dst = exportTransform(state, obj); }; switch (obj->type) { @@ -416,7 +429,7 @@ ms::TransformPtr msblenContext::exportObject(const Object* obj, bool parent,ms:: { if (!tip || (!m_settings.BakeModifiers && m_settings.sync_bones)) { handle_parent(); - rec.dst = exportArmature(obj, manager); + rec.dst = exportArmature(state, obj); } else if (!tip && parent) handle_transform(); @@ -426,11 +439,11 @@ ms::TransformPtr msblenContext::exportObject(const Object* obj, bool parent,ms:: { if (!m_settings.BakeModifiers && m_settings.sync_bones) { if (auto* arm_mod = (const ArmatureModifierData*)FindModifier(obj, eModifierType_Armature)) - exportObject(arm_mod->object, parent, manager); + exportObject(state, arm_mod->object, parent); } if (m_settings.sync_meshes || (!m_settings.BakeModifiers && m_settings.sync_blendshapes)) { handle_parent(); - rec.dst = exportMesh(obj, manager); + rec.dst = exportMesh(state, obj); } else if (!tip && parent) handle_transform(); @@ -443,7 +456,7 @@ ms::TransformPtr msblenContext::exportObject(const Object* obj, bool parent,ms:: { if (m_settings.sync_meshes && m_settings.curves_as_mesh) { handle_parent(); - rec.dst = exportMesh(obj, manager); + rec.dst = exportMesh(state, obj); } else if (!tip && parent) handle_transform(); @@ -453,7 +466,7 @@ ms::TransformPtr msblenContext::exportObject(const Object* obj, bool parent,ms:: { if (m_settings.sync_cameras) { handle_parent(); - rec.dst = exportCamera(obj, manager); + rec.dst = exportCamera(state, obj); } else if (!tip && parent) handle_transform(); @@ -463,7 +476,7 @@ ms::TransformPtr msblenContext::exportObject(const Object* obj, bool parent,ms:: { if (m_settings.sync_lights) { handle_parent(); - rec.dst = exportLight(obj, manager); + rec.dst = exportLight(state, obj); } else if (!tip && parent) handle_transform(); @@ -473,7 +486,7 @@ ms::TransformPtr msblenContext::exportObject(const Object* obj, bool parent,ms:: { if (get_instance_collection(obj) || (!tip && parent)) { handle_parent(); - rec.dst = exportTransform(obj, manager); + rec.dst = exportTransform(state, obj); } break; } @@ -485,57 +498,52 @@ ms::TransformPtr msblenContext::exportObject(const Object* obj, bool parent,ms:: ctx.group_host = obj; ctx.dst = rec.dst; - exportDupliGroup(obj, ctx, manager); + exportDupliGroup(state, obj, ctx); } } return rec.dst; } -ms::TransformPtr msblenContext::exportObject(const Object *obj, bool parent, bool tip) -{ - return exportObject(obj, parent, m_entity_manager, tip); -} - -ms::TransformPtr msblenContext::exportTransform(const Object *src, ms::TransformManager& manager) +ms::TransformPtr msblenContext::exportTransform(msblenContextState& state, const Object *src) { std::shared_ptr ret = ms::Transform::create(); ms::Transform& dst = *ret; dst.path = get_path(src); extractTransformData(src, dst); - manager.add(ret); + state.manager.add(ret); return ret; } -ms::TransformPtr msblenContext::exportPose(const Object *armature, bPoseChannel *src, ms::TransformManager& manager) +ms::TransformPtr msblenContext::exportPose(msblenContextState& state, const Object *armature, bPoseChannel *src) { std::shared_ptr ret = ms::Transform::create(); ms::Transform& dst = *ret; dst.path = get_path(armature, src->bone); extractTransformData(src, dst.position, dst.rotation, dst.scale); - manager.add(ret); + state.manager.add(ret); return ret; } -ms::TransformPtr msblenContext::exportArmature(const Object *src, ms::TransformManager& manager) +ms::TransformPtr msblenContext::exportArmature(msblenContextState& state, const Object *src) { std::shared_ptr ret = ms::Transform::create(); ms::Transform& dst = *ret; dst.path = get_path(src); extractTransformData(src, dst); - manager.add(ret); + state.manager.add(ret); for (struct bPoseChannel* pose : bl::list_range((bPoseChannel*)src->pose->chanbase.first)) { struct Bone* bone = pose->bone; - std::map>::mapped_type& dst = m_bones[bone]; - dst = exportPose(src, pose, manager); + std::map>::mapped_type& dst = state.bones[bone]; + dst = exportPose(state, src, pose); } return ret; } -ms::TransformPtr msblenContext::exportReference(Object *src, const DupliGroupContext& ctx, ms::TransformManager& manager) +ms::TransformPtr msblenContext::exportReference(msblenContextState& state, Object *src, const DupliGroupContext& ctx) { - msblenContext::ObjectRecord& rec = touchRecord(manager, src); + auto& rec = state.touchRecord(src); if (!rec.dst) return nullptr; @@ -560,6 +568,7 @@ ms::TransformPtr msblenContext::exportReference(Object *src, const DupliGroupCon (ms::Transform&)dst_mesh = (ms::Transform&)src_mesh; assign_base_params(); + auto& manager = state.manager; auto do_merge = [this, dst, &dst_mesh, &src_mesh, &manager]() { dst_mesh.merge(src_mesh); if (m_settings.ExportSceneCache) @@ -579,17 +588,17 @@ ms::TransformPtr msblenContext::exportReference(Object *src, const DupliGroupCon dst = ms::Transform::create(); assign_base_params(); dst->reference = local_path; - manager.add(dst); + state.manager.add(dst); } } else { dst = std::static_pointer_cast(rec.dst->clone()); assign_base_params(); - manager.add(dst); + state.manager.add(dst); } each_child(src, [&](Object *child) { - exportReference(child, ctx, manager); + exportReference(state, child, ctx); }); if (get_instance_collection(src)) { @@ -597,12 +606,12 @@ ms::TransformPtr msblenContext::exportReference(Object *src, const DupliGroupCon ctx2.group_host = src; ctx2.dst = dst; - exportDupliGroup(src, ctx2, manager); + exportDupliGroup(state, src, ctx2); } return dst; } -ms::TransformPtr msblenContext::exportDupliGroup(const Object *src, const DupliGroupContext& ctx, ms::TransformManager& manager) +ms::TransformPtr msblenContext::exportDupliGroup(msblenContextState& state, const Object *src, const DupliGroupContext& ctx) { Collection* group = get_instance_collection(src); if (!group) @@ -618,7 +627,7 @@ ms::TransformPtr msblenContext::exportDupliGroup(const Object *src, const DupliG const mu::tvec3 offset_pos = -get_instance_offset(group); dst->position = m_settings.BakeTransform ? mu::float3::zero() : offset_pos; dst->world_matrix = mu::translate(offset_pos) * ctx.dst->world_matrix; - manager.add(dst); + state.manager.add(dst); DupliGroupContext ctx2; ctx2.group_host = src; @@ -626,39 +635,39 @@ ms::TransformPtr msblenContext::exportDupliGroup(const Object *src, const DupliG auto gobjects = bl::list_range((CollectionObject*)group->gobject.first); for (auto go : gobjects) { auto obj = go->ob; - if (auto t = exportObject(obj, true, false)) { + if (auto t = exportObject(state, obj, true, false)) { const bool non_lib = obj->id.lib == nullptr; t->visibility = { true, non_lib, non_lib }; } - exportReference(obj, ctx2, manager); + exportReference(state, obj, ctx2); } return dst; } -ms::CameraPtr msblenContext::exportCamera(const Object *src, ms::TransformManager& manager) +ms::CameraPtr msblenContext::exportCamera(msblenContextState& state, const Object *src) { std::shared_ptr ret = ms::Camera::create(); ms::Camera& dst = *ret; dst.path = get_path(src); extractTransformData(src, dst); extractCameraData(src, dst.is_ortho, dst.near_plane, dst.far_plane, dst.fov, dst.focal_length, dst.sensor_size, dst.lens_shift); - manager.add(ret); + state.manager.add(ret); return ret; } -ms::LightPtr msblenContext::exportLight(const Object *src, ms::TransformManager& manager) +ms::LightPtr msblenContext::exportLight(msblenContextState& state, const Object *src) { std::shared_ptr ret = ms::Light::create(); ms::Light& dst = *ret; dst.path = get_path(src); extractTransformData(src, dst); extractLightData(src, dst.light_type, dst.shadow_type, dst.color, dst.intensity, dst.range, dst.spot_angle); - manager.add(ret); + state.manager.add(ret); return ret; } -ms::MeshPtr msblenContext::exportMesh(const Object *src, ms::TransformManager& manager) +ms::MeshPtr msblenContext::exportMesh(msblenContextState& state, const Object *src) { // ignore particles if (//FindModifier(src, eModifierType_ParticleSystem) || @@ -678,7 +687,7 @@ ms::MeshPtr msblenContext::exportMesh(const Object *src, ms::TransformManager& m struct BMesh* bm = edit_mesh->bm; if (bm->elem_table_dirty) { // mesh is editing and dirty. just add to pending list - m_pending.insert(src); + state.pending.insert(src); return nullptr; } } @@ -718,10 +727,10 @@ ms::MeshPtr msblenContext::exportMesh(const Object *src, ms::TransformManager& m } if (data) { - auto task = [this, ret, src, data, &manager]() { + auto task = [this, ret, src, data, &state]() { auto& dst = *ret; - doExtractMeshData(dst, src, data, dst.world_matrix); - manager.add(ret); + doExtractMeshData(state, dst, src, data, dst.world_matrix); + state.manager.add(ret); }; if (m_settings.multithreaded) @@ -732,7 +741,7 @@ ms::MeshPtr msblenContext::exportMesh(const Object *src, ms::TransformManager& m return ret; } -void msblenContext::doExtractMeshData(ms::Mesh& dst, const Object *obj, Mesh *data, mu::float4x4 world) +void msblenContext::doExtractMeshData(msblenContextState& state, ms::Mesh& dst, const Object *obj, Mesh *data, mu::float4x4 world) { if (m_settings.sync_meshes) { bl::BObject bobj(obj); @@ -742,10 +751,10 @@ void msblenContext::doExtractMeshData(ms::Mesh& dst, const Object *obj, Mesh *da // on edit mode, editing is applied to EditMesh and base Mesh is intact. so get data from EditMesh on edit mode. // todo: Blender 2.8 displays transparent final mesh on edit mode. extract data from it. if (is_editing) { - doExtractEditMeshData(dst, obj, data); + doExtractEditMeshData(state, dst, obj, data); } else { - doExtractNonEditMeshData(dst, obj, data); + doExtractNonEditMeshData(state, dst, obj, data); } if (!m_settings.BakeModifiers&& !is_editing) { @@ -769,7 +778,7 @@ void msblenContext::doExtractMeshData(ms::Mesh& dst, const Object *obj, Mesh *da } else { if (!m_settings.BakeModifiers&& m_settings.sync_blendshapes) { - doExtractBlendshapeWeights(dst, obj, data); + doExtractBlendshapeWeights(state, dst, obj, data); } } @@ -781,7 +790,7 @@ void msblenContext::doExtractMeshData(ms::Mesh& dst, const Object *obj, Mesh *da dst.refine_settings.flags.Set(ms::MESH_REFINE_FLAG_MAKE_DOUBLE_SIDED, m_settings.make_double_sided); } -void msblenContext::doExtractBlendshapeWeights(ms::Mesh& dst, const Object *obj, Mesh *data) +void msblenContext::doExtractBlendshapeWeights(msblenContextState& state, ms::Mesh& dst, const Object *obj, Mesh *data) { struct Mesh& mesh = *data; if (!m_settings.BakeModifiers) { @@ -803,11 +812,11 @@ void msblenContext::doExtractBlendshapeWeights(ms::Mesh& dst, const Object *obj, } -void msblenContext::doExtractNonEditMeshData(ms::Mesh& dst, const Object* obj, Mesh* data) { - doExtractNonEditMeshData(dst, obj, data, m_settings); +void msblenContext::doExtractNonEditMeshData(msblenContextState& state, ms::Mesh& dst, const Object* obj, Mesh* data) { + doExtractNonEditMeshData(state, dst, obj, data, m_settings); } -void msblenContext::doExtractNonEditMeshData(ms::Mesh& dst, const Object *obj, Mesh *data, BlenderSyncSettings& settings) +void msblenContext::doExtractNonEditMeshData(msblenContextState& state, ms::Mesh& dst, const Object *obj, Mesh *data, BlenderSyncSettings& settings) { bl::BObject bobj(obj); bl::BMesh bmesh(data); @@ -912,7 +921,7 @@ void msblenContext::doExtractNonEditMeshData(ms::Mesh& dst, const Object *obj, M bool found = false; Bone* bone = find_bone(arm_obj, g->name); if (bone) { - ms::TransformPtr trans = findBone(arm_obj, bone); + ms::TransformPtr trans = findBone(state, arm_obj, bone); if (trans) { found = true; ms::BoneDataPtr b = dst.addBone(trans->path); @@ -1016,7 +1025,7 @@ void msblenContext::doExtractNonEditMeshData(ms::Mesh& dst, const Object *obj, M #endif } -void msblenContext::doExtractEditMeshData(ms::Mesh& dst, const Object *obj, Mesh *data) +void msblenContext::doExtractEditMeshData(msblenContextState& state, ms::Mesh& dst, const Object *obj, Mesh *data) { bl::BObject bobj(obj); bl::BMesh bmesh(data); @@ -1103,71 +1112,10 @@ void msblenContext::doExtractEditMeshData(ms::Mesh& dst, const Object *obj, Mesh } } - -ms::TransformPtr msblenContext::findBone(Object *armature, Bone *bone) +ms::TransformPtr msblenContext::findBone(msblenContextState& state, Object *armature, Bone *bone) { - std::map>::iterator it = m_bones.find(bone); - return it != m_bones.end() ? it->second : nullptr; -} - -msblenContext::ObjectRecord& msblenContext::touchRecord(const Object* obj, const std::string& base_path, bool children) { - return touchRecord(m_entity_manager, obj, base_path, children); -} - -msblenContext::ObjectRecord& msblenContext::touchRecord(ms::TransformManager& manager, const Object *obj, const std::string& base_path, bool children) -{ - std::map::mapped_type& rec = m_obj_records[obj]; - if (rec.touched && base_path.empty()) - return rec; // already touched - - rec.touched = true; - - std::string local_path = get_path(obj); - if (local_path != rec.path) { - rec.renamed = true; - rec.path = local_path; - } - std::string path = base_path + local_path; - manager.touch(path); - - // trace bones - if (is_armature(obj)) { - blender::blist_range poses = bl::list_range((bPoseChannel*)obj->pose->chanbase.first); - for (struct bPoseChannel* pose : poses) { - m_obj_records[pose->bone].touched = true; - manager.touch(base_path + get_path(obj, pose->bone)); - } - } - - // care children - if (children) { - each_child(obj, [&](Object *child) { - touchRecord(manager, child, base_path, true); - }); - } - - // trace dupli group - if (Collection* group = get_instance_collection(obj)) { - const std::string group_path = path + '/' + (group->id.name + 2); - manager.touch(group_path); - - auto gobjects = bl::list_range((CollectionObject*)group->gobject.first); - for (auto go : gobjects) - touchRecord(manager, go->ob, group_path, true); - } - return rec; -} - - -void msblenContext::eraseStaleObjects() -{ - for (auto i = m_obj_records.begin(); i != m_obj_records.end(); /**/) { - if (!i->second.touched) - m_obj_records.erase(i++); - else - ++i; - } - m_entity_manager.eraseStaleEntities(); + std::map>::iterator it = state.bones.find(bone); + return it != state.bones.end() ? it->second : nullptr; } @@ -1413,7 +1361,7 @@ bool msblenContext::sendObjects(MeshSyncClient::ObjectScope scope, bool dirty_al m_entity_manager.setAlwaysMarkDirty(dirty_all); m_material_manager.setAlwaysMarkDirty(dirty_all); m_texture_manager.setAlwaysMarkDirty(false); // false because too heavy - m_instances_manager.setAlwaysMarkDirty(dirty_all); + m_instances_state->manager.setAlwaysMarkDirty(dirty_all); if (m_settings.sync_meshes) RegisterSceneMaterials(); @@ -1427,34 +1375,37 @@ bool msblenContext::sendObjects(MeshSyncClient::ObjectScope scope, bool dirty_al scene.each_objects([this](Object *obj) { bl::BlenderPyID bid = bl::BlenderPyID(obj); if (bid.is_updated() || bid.is_updated_data()) - exportObject(obj, false); + exportObject(*m_entities_state, obj, false); else - touchRecord(obj); // this cannot be covered by getNodes() + m_entities_state->touchRecord(obj); // this cannot be covered by getNodes() }); - eraseStaleObjects(); } else { for(std::vector::value_type obj : getNodes(scope)) - exportObject(obj, true); - eraseStaleObjects(); + exportObject(*m_entities_state, obj, true); } #if BLENDER_VERSION >= 300 if (m_geometryNodeUtils.getInstancesDirty() || dirty_all) { - // Assume everything needs to be deleted - m_instances_manager.deleteAll(); - // Assume everything is now dirty - m_instances_manager.setAlwaysMarkDirty(true); + m_instances_state->manager.setAlwaysMarkDirty(true); auto instancesHandler = std::bind(&msblenContext::exportInstances, this, std::placeholders::_1, std::placeholders::_2); blender::GeometryNodesUtils::foreach_instance(instancesHandler); m_geometryNodeUtils.setInstancesDirty(false); + + m_asyncTasksController.Wait(); + + m_instances_state->eraseStaleObjects(); } +#else + m_asyncTasksController.Wait(); #endif + m_entities_state->eraseStaleObjects(); + WaitAndKickAsyncExport(); return true; } @@ -1603,7 +1554,7 @@ bool msblenContext::ExportCache(const std::string& path, const BlenderCacheSetti void msblenContext::DoExportSceneCache(const std::vector& nodes) { for (const std::vector::value_type& n : nodes) - exportObject(n, true); + exportObject(*m_entities_state, n, true); m_texture_manager.clearDirtyFlags(); WaitAndKickAsyncExport(); @@ -1612,14 +1563,21 @@ void msblenContext::DoExportSceneCache(const std::vector& nodes) //---------------------------------------------------------------------------------------------------------------------- void msblenContext::flushPendingList() { - if (!m_pending.empty() && !m_sender.isExporting()) { - for (auto p : m_pending) - exportObject(p, false); - m_pending.clear(); + flushPendingList(*m_entities_state); + flushPendingList(*m_instances_state); +} + +void msblenContext::flushPendingList(msblenContextState& state) { + if (!state.pending.empty() && !m_sender.isExporting()) { + for (auto p : state.pending) + exportObject(state, p, false); + state.pending.clear(); + WaitAndKickAsyncExport(); } } + void msblenContext::WaitAndKickAsyncExport() { m_asyncTasksController.Wait(); @@ -1633,9 +1591,10 @@ void msblenContext::WaitAndKickAsyncExport() m_meshes_to_clear.clear(); } - for (std::map::value_type& kvp : m_obj_records) - kvp.second.clearState(); - m_bones.clear(); + m_entities_state->clearRecordsState(); + m_instances_state->clearRecordsState(); + + m_entities_state->bones.clear(); using Exporter = ms::SceneExporter; Exporter *exporter = m_settings.ExportSceneCache ? (Exporter*)&m_cache_writer : (Exporter*)&m_sender; @@ -1658,14 +1617,14 @@ void msblenContext::WaitAndKickAsyncExport() t.materials = m_material_manager.getDirtyMaterials(); t.transforms = m_entity_manager.getDirtyTransforms(); t.geometries = m_entity_manager.getDirtyGeometries(); - t.instanceInfos = m_instances_manager.getDirtyInstances(); - t.instanceMeshes = m_instances_manager.getDirtyMeshes(); + t.instanceInfos = m_instances_state->GetManager().getDirtyInstances(); + t.instanceMeshes = m_instances_state->GetManager().getDirtyMeshes(); t.animations = m_animations; t.deleted_materials = m_material_manager.getDeleted(); t.deleted_entities = m_entity_manager.getDeleted(); - t.deleted_instanceInfos = m_instances_manager.getDeletedInstanceInfos(); - t.deleted_instanceMeshes = m_instances_manager.getDeletedMeshes(); + + t.deleted_instances = m_instances_state->GetManager().getDeleted(); if (scale_factor != 1.0f) { ms::ScaleConverter cv(scale_factor); @@ -1681,7 +1640,7 @@ void msblenContext::WaitAndKickAsyncExport() m_material_manager.clearDirtyFlags(); m_entity_manager.clearDirtyFlags(); m_animations.clear(); - m_instances_manager.clearDirtyFlags(); + m_instances_state->GetManager().clearDirtyFlags(); }; exporter->kick(); @@ -1706,13 +1665,13 @@ void msblenContext::onDepsgraphUpdatedPost(Depsgraph* graph) void msblenContext::exportInstances(Object* object, SharedVector mat) { - exportObject(object, false, m_instances_manager); + exportObject(*m_instances_state, object, false); auto info = ms::InstanceInfo::create(); info->path = get_path(object); info->transforms = std::move(mat); - m_instances_manager.add(info); + m_instances_state->GetManager().add(info); } #endif diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h index ab8ab4a4..0a921cb0 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h @@ -27,13 +27,17 @@ #if BLENDER_VERSION >= 300 #include #endif +#include "../MeshSyncClientBlender/msblenContextState.h" #include -#include class msblenContext; class msblenContext { public: + + msblenContext(); + ~msblenContext(); + static msblenContext& getInstance(); void Destroy(); @@ -56,6 +60,7 @@ class msblenContext { bool ExportCache(const std::string& path, const BlenderCacheSettings& cache_settings); void flushPendingList(); + void flushPendingList(msblenContextState& state); void onDepsgraphUpdatedPost(Depsgraph* graph); @@ -79,27 +84,7 @@ class msblenContext { void recordAnimation(msblenContext *_this) const; }; - // note: - // ObjectRecord and Blender's Object is *NOT* 1 on 1 because there is 'dupli group' in Blender. - // dupli group is a collection of nodes that will be instanced. - // so, only the path is unique. Object maybe shared by multiple ObjectRecord. - struct ObjectRecord { - MS_CLASS_DEFAULT_NOCOPY_NOASSIGN(ObjectRecord); - //std::vector branches; // todo - - std::string path; - std::string name; - Object *host = nullptr; // parent of dupli group - Object *obj = nullptr; - Bone *bone = nullptr; - - ms::TransformPtr dst; - - bool touched = false; - bool renamed = false; - void clearState(); - }; struct AnimationRecord { MS_CLASS_DEFAULT_NOCOPY_NOASSIGN(AnimationRecord); @@ -119,9 +104,6 @@ class msblenContext { ms::TransformPtr dst; }; - msblenContext(); - ~msblenContext(); - static std::vector getNodes(MeshSyncClient::ObjectScope scope); int exportTexture(const std::string & path, ms::TextureType type); @@ -131,17 +113,15 @@ class msblenContext { void RegisterObjectMaterials(const std::vector objects); void RegisterMaterial(Material* mat, const uint32_t matIndex); - - ms::TransformPtr exportObject(const Object *obj, bool parent, bool tip = true); - ms::TransformPtr exportObject(const Object* obj, bool parent, ms::TransformManager& manager, bool tip = true); - ms::TransformPtr exportTransform(const Object *obj, ms::TransformManager& manager); - ms::TransformPtr exportPose(const Object *armature, bPoseChannel *obj, ms::TransformManager& manager); - ms::TransformPtr exportArmature(const Object *obj, ms::TransformManager& manager); - ms::TransformPtr exportReference(Object *obj, const DupliGroupContext& ctx, ms::TransformManager& manager); - ms::TransformPtr exportDupliGroup(const Object *obj, const DupliGroupContext& ctx, ms::TransformManager& manager); - ms::CameraPtr exportCamera(const Object *obj, ms::TransformManager& manager); - ms::LightPtr exportLight(const Object *obj, ms::TransformManager& manager); - ms::MeshPtr exportMesh(const Object *obj, ms::TransformManager& manager); + ms::TransformPtr exportObject(msblenContextState& state, const Object* obj, bool parent, bool tip = true); + ms::TransformPtr exportTransform(msblenContextState& state, const Object *obj); + ms::TransformPtr exportPose(msblenContextState& state, const Object *armature, bPoseChannel *obj); + ms::TransformPtr exportArmature(msblenContextState& state, const Object *obj); + ms::TransformPtr exportReference(msblenContextState& state, Object *obj, const DupliGroupContext& ctx); + ms::TransformPtr exportDupliGroup(msblenContextState& state, const Object *obj, const DupliGroupContext& ctx); + ms::CameraPtr exportCamera(msblenContextState& state, const Object *obj); + ms::LightPtr exportLight(msblenContextState& state, const Object *obj); + ms::MeshPtr exportMesh(msblenContextState& state, const Object *obj); mu::float4x4 getWorldMatrix(const Object *obj); mu::float4x4 getLocalMatrix(const Object *obj); @@ -158,19 +138,16 @@ class msblenContext { void extractLightData(const Object *src, ms::Light::LightType& ltype, ms::Light::ShadowType& stype, mu::float4& color, float& intensity, float& range, float& spot_angle); - void doExtractMeshData(ms::Mesh& dst, const Object *obj, Mesh *data, mu::float4x4 world); - void doExtractBlendshapeWeights(ms::Mesh& dst, const Object *obj, Mesh *data); - void doExtractNonEditMeshData(ms::Mesh& dst, const Object *obj, Mesh *data); - void doExtractNonEditMeshData(ms::Mesh& dst,const Object* obj, Mesh* data, BlenderSyncSettings& settings); - void doExtractEditMeshData(ms::Mesh& dst, const Object *obj, Mesh *data); - + void doExtractMeshData(msblenContextState& state, ms::Mesh& dst, const Object *obj, Mesh *data, mu::float4x4 world); + void doExtractBlendshapeWeights(msblenContextState& state, ms::Mesh& dst, const Object *obj, Mesh *data); + void doExtractNonEditMeshData(msblenContextState& state, ms::Mesh& dst, const Object *obj, Mesh *data); + void doExtractNonEditMeshData(msblenContextState& state, ms::Mesh& dst,const Object* obj, Mesh* data, BlenderSyncSettings& settings); + void doExtractEditMeshData(msblenContextState& state, ms::Mesh& dst, const Object *obj, Mesh *data); - ms::TransformPtr findBone(Object *armature, Bone *bone); - ObjectRecord& touchRecord(const Object *obj, const std::string& base_path = "", bool children = false); - ObjectRecord& touchRecord(ms::TransformManager& manager, const Object* obj, const std::string& base_path = "", bool children = false); - void eraseStaleObjects(); + ms::TransformPtr findBone(msblenContextState& state, Object* armature, Bone* bone); + void exportAnimation(Object *obj, bool force, const std::string& base_path = ""); void extractTransformAnimationData(ms::TransformAnimation& dst, void *obj); void extractPoseAnimationData(ms::TransformAnimation& dst, void *obj); @@ -187,11 +164,11 @@ class msblenContext { private: + msblenContextState* m_entities_state = nullptr; + msblenContextState* m_instances_state = nullptr; + BlenderSyncSettings m_settings; BlenderCacheSettings m_cache_settings; - std::set m_pending; - std::map m_bones; - std::map m_obj_records; // key can be object or bone MeshSyncClient::AsyncTasksController m_asyncTasksController; @@ -204,8 +181,8 @@ class msblenContext { ms::EntityManager m_entity_manager; ms::AsyncSceneSender m_sender; ms::SceneCacheWriter m_cache_writer; - ms::InstancesManager m_instances_manager; + #if BLENDER_VERSION >= 300 blender::GeometryNodesUtils m_geometryNodeUtils; #endif diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContextState.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContextState.cpp new file mode 100644 index 00000000..bdded8de --- /dev/null +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContextState.cpp @@ -0,0 +1,80 @@ +#include "msblenContextState.h" +#include + +void msblenContextState::ObjectRecord::clearState() +{ + touched = renamed = false; + dst = nullptr; +} + +void msblenContextState::eraseObjectRecords() +{ + for (auto i = records.begin(); i != records.end(); /**/) { + if (!i->second.touched) + records.erase(i++); + else + ++i; + } +} + +void msblenContextState::eraseStaleObjects() +{ + eraseObjectRecords(); + manager.eraseStaleEntities(); +} + +void msblenContextState::clear() { + manager.clear(); +} + +void msblenContextState::clearRecordsState() { + for (std::map::value_type& kvp : records) + kvp.second.clearState(); +} + +msblenContextState::ObjectRecord& msblenContextState::touchRecord( + const Object* obj, + const std::string& base_path, + bool children) +{ + auto& rec = records[obj]; + if (rec.touched && base_path.empty()) + return rec; // already touched + + rec.touched = true; + + std::string local_path = get_path(obj); + if (local_path != rec.path) { + rec.renamed = true; + rec.path = local_path; + } + std::string path = base_path + local_path; + manager.touch(path); + + // trace bones + if (is_armature(obj)) { + blender::blist_range poses = blender::list_range((bPoseChannel*)obj->pose->chanbase.first); + for (struct bPoseChannel* pose : poses) { + records[pose->bone].touched = true; + manager.touch(base_path + get_path(obj, pose->bone)); + } + } + + // care children + if (children) { + each_child(obj, [&](Object* child) { + touchRecord(child, base_path, true); + }); + } + + // trace dupli group + if (Collection* group = get_instance_collection(obj)) { + const std::string group_path = path + '/' + (group->id.name + 2); + manager.touch(group_path); + + auto gobjects = blender::list_range((CollectionObject*)group->gobject.first); + for (auto go : gobjects) + touchRecord(go->ob, group_path, true); + } + return rec; +} diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContextState.h b/Plugins~/Src/MeshSyncClientBlender/msblenContextState.h new file mode 100644 index 00000000..5490c862 --- /dev/null +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContextState.h @@ -0,0 +1,47 @@ +#include +#include "MeshSync/MeshSyncMacros.h" + +class msblenContextState { +public: + // note: +// ObjectRecord and Blender's Object is *NOT* 1 on 1 because there is 'dupli group' in Blender. +// dupli group is a collection of nodes that will be instanced. +// so, only the path is unique. Object maybe shared by multiple ObjectRecord. + struct ObjectRecord { + MS_CLASS_DEFAULT_NOCOPY_NOASSIGN(ObjectRecord); + //std::vector branches; // todo + + std::string path; + std::string name; + Object* host = nullptr; // parent of dupli group + Object* obj = nullptr; + Bone* bone = nullptr; + + ms::TransformPtr dst; + + bool touched = false; + bool renamed = false; + + void clearState(); + }; + + msblenContextState(ms::TransformManager& manager) : manager(manager) + { + }; + + std::set pending; + std::map records; + std::map bones; + + ms::TransformManager& manager; + + template + T& GetManager() { return (T&)manager; } + + void msblenContextState::eraseObjectRecords(); + void msblenContextState::eraseStaleObjects(); + void clear(); + void clearRecordsState(); + + msblenContextState::ObjectRecord& msblenContextState::touchRecord(const Object* obj, const std::string& base_path = "", bool children = false); +}; From 8b8b301de6f27029dd9600a14bdc4da83e1aedc3 Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Thu, 24 Mar 2022 11:42:36 +0000 Subject: [PATCH 34/67] Geometry Nodes: Fix for associating objects through data id instead of object id --- .../MeshSyncClientBlender/msblenGeometryNodes.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp index 70f0d5b4..9ec7bf86 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp @@ -97,7 +97,8 @@ namespace blender { auto unityMatrix = blenderToUnityWorldMatrix(world_matrix); - handler(&object->id, move(unityMatrix)); + auto id = (ID*)object->data; + handler(id, move(unityMatrix)); } // Cleanup resources @@ -107,15 +108,23 @@ namespace blender { void GeometryNodesUtils::foreach_instance(function)> handler) { map> transformsMap; + foreach_instance([&](ID* id, float4x4 matrix) { - transformsMap[id->name].push_back(matrix); + auto& rec = transformsMap[id->name]; + rec.push_back(matrix); }); auto ctx = blender::BlenderPyContext::get(); auto objects = ctx.data()->objects; LISTBASE_FOREACH(Object*, obj, &objects){ - auto result = transformsMap.find(obj->id.name); + + if (obj->data == nullptr) + continue; + + auto id = (ID*)obj->data; + + auto result = transformsMap.find(id->name); if (result != transformsMap.end()) { handler(obj, std::move(result->second)); } From ded7658d4e224906f6e11372ab37633e3718abae Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Thu, 24 Mar 2022 16:57:24 +0000 Subject: [PATCH 35/67] Geometry Nodes: WIP refactor on accessing instances data --- .../msblenGeometryNodes.cpp | 29 ++++++++++++------- .../msblenGeometryNodes.h | 8 ++++- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp index 9ec7bf86..a29256f4 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp @@ -54,7 +54,7 @@ namespace blender { } - void GeometryNodesUtils::foreach_instance(std::function handler) + void GeometryNodesUtils::foreach_instance(std::function handler) { auto blContext = blender::BlenderPyContext::get(); @@ -97,8 +97,7 @@ namespace blender { auto unityMatrix = blenderToUnityWorldMatrix(world_matrix); - auto id = (ID*)object->data; - handler(id, move(unityMatrix)); + handler(object, move(unityMatrix)); } // Cleanup resources @@ -107,11 +106,13 @@ namespace blender { void GeometryNodesUtils::foreach_instance(function)> handler) { - map> transformsMap; + map records; - foreach_instance([&](ID* id, float4x4 matrix) { - auto& rec = transformsMap[id->name]; - rec.push_back(matrix); + foreach_instance([&](Object* obj, float4x4 matrix) { + auto id = (ID*)obj->data; + auto& rec = records[id->name]; + rec.obj = obj; + rec.matrices.push_back(matrix); }); auto ctx = blender::BlenderPyContext::get(); @@ -124,11 +125,19 @@ namespace blender { auto id = (ID*)obj->data; - auto result = transformsMap.find(id->name); - if (result != transformsMap.end()) { - handler(obj, std::move(result->second)); + auto rec = records.find(id->name); + if (rec != records.end()) { + handler(obj, std::move(rec->second.matrices)); + rec->second.handled = true; } } + + for(auto& rec : records) { + if (rec.second.handled) + continue; + + // handler(rec.second.obj, std::move(rec.second.matrices)); + } } void GeometryNodesUtils::setInstancesDirty(bool dirty) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h index c5a9bf12..935db7c5 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h @@ -28,7 +28,7 @@ namespace blender { /// of the instance in the Unity3D Coordinate system /// /// - static void foreach_instance(std::function transformHandler); + static void foreach_instance(std::function transformHandler); static void foreach_instance(std::function)> transformHandler); @@ -37,6 +37,12 @@ namespace blender { private: bool m_instances_dirty; + + struct Record { + Object* obj = nullptr; + SharedVector matrices; + bool handled = false; + }; }; #endif } From 22fed3f1a8c942d226c68fbb9b4ba0c8c1ec2ac9 Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Fri, 25 Mar 2022 15:03:01 +0000 Subject: [PATCH 36/67] Geometry Nodes: support for passing the path of parent for instances --- .../MeshSyncClientBlender/msblenContext.cpp | 16 ++++++------- .../Src/MeshSyncClientBlender/msblenContext.h | 2 +- .../msblenGeometryNodes.cpp | 14 +++++------ .../msblenGeometryNodes.h | 24 ++++++++++++++----- 4 files changed, 34 insertions(+), 22 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index ac910269..d9984898 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -1391,8 +1391,9 @@ bool msblenContext::sendObjects(MeshSyncClient::ObjectScope scope, bool dirty_al // Assume everything is now dirty m_instances_state->manager.setAlwaysMarkDirty(true); - auto instancesHandler = std::bind(&msblenContext::exportInstances, this, std::placeholders::_1, std::placeholders::_2); - blender::GeometryNodesUtils::foreach_instance(instancesHandler); + auto instancesHandler = + std::bind(&msblenContext::exportInstances, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); + blender::GeometryNodesUtils::foreach_instanced_object(instancesHandler); m_geometryNodeUtils.setInstancesDirty(false); @@ -1400,10 +1401,8 @@ bool msblenContext::sendObjects(MeshSyncClient::ObjectScope scope, bool dirty_al m_instances_state->eraseStaleObjects(); } -#else - m_asyncTasksController.Wait(); #endif - + m_asyncTasksController.Wait(); m_entities_state->eraseStaleObjects(); WaitAndKickAsyncExport(); @@ -1663,12 +1662,13 @@ void msblenContext::onDepsgraphUpdatedPost(Depsgraph* graph) /// Geometry Nodes Blender Context Functionality /// #if BLENDER_VERSION >= 300 -void msblenContext::exportInstances(Object* object, SharedVector mat) { +void msblenContext::exportInstances(Object* instancedObject, Object* parent, SharedVector mat) { - exportObject(*m_instances_state, object, false); + exportObject(*m_instances_state, instancedObject, false); auto info = ms::InstanceInfo::create(); - info->path = get_path(object); + info->path = get_path(instancedObject); + info->parent_path = get_path(parent); info->transforms = std::move(mat); m_instances_state->GetManager().add(info); diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h index 0a921cb0..2edb74a0 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h @@ -159,7 +159,7 @@ class msblenContext { void WaitAndKickAsyncExport(); #if BLENDER_VERSION >= 300 - void exportInstances(Object* object, SharedVector); + void exportInstances(Object* object, Object* parent, SharedVector); #endif private: diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp index a29256f4..12bf715b 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp @@ -54,7 +54,7 @@ namespace blender { } - void GeometryNodesUtils::foreach_instance(std::function handler) + void GeometryNodesUtils::foreach_instance(std::function handler) { auto blContext = blender::BlenderPyContext::get(); @@ -68,8 +68,6 @@ namespace blender { blContext.object_instances_begin(&it, depsgraph); - - for (; it.valid; blContext.object_instances_next(&it)) { // Get the instance as a Pointer RNA. auto instance = blContext.object_instances_get(&it); @@ -96,22 +94,24 @@ namespace blender { blContext.world_matrix_get(&instance, &world_matrix); auto unityMatrix = blenderToUnityWorldMatrix(world_matrix); + auto parent = blContext.instance_parent_get(&instance); - handler(object, move(unityMatrix)); + handler(object, parent, move(unityMatrix)); } // Cleanup resources blContext.object_instances_end(&it); } - void GeometryNodesUtils::foreach_instance(function)> handler) { + void GeometryNodesUtils::foreach_instanced_object(function)> handler) { map records; - foreach_instance([&](Object* obj, float4x4 matrix) { + foreach_instance([&](Object* obj, Object* parent, float4x4 matrix) { auto id = (ID*)obj->data; auto& rec = records[id->name]; rec.obj = obj; + rec.parent = parent; rec.matrices.push_back(matrix); }); @@ -127,7 +127,7 @@ namespace blender { auto rec = records.find(id->name); if (rec != records.end()) { - handler(obj, std::move(rec->second.matrices)); + handler(obj, rec->second.parent, std::move(rec->second.matrices)); rec->second.handled = true; } } diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h index 935db7c5..d177eb6b 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h @@ -23,14 +23,25 @@ namespace blender { static mu::float4x4 blenderToUnityWorldMatrixMesh(); /// - /// Will invoke f for every instance. The first argument of f is the name - /// of the mesh that is being instantiated and the second argumenet is the world matrix - /// of the instance in the Unity3D Coordinate system + /// Invokes the handler function for each instance. /// - /// - static void foreach_instance(std::function transformHandler); + /// + /// The handling function: + /// instancedObject is the object that is being instanced. + /// transform is the transform of the instance + /// + static void foreach_instance(std::function handler); - static void foreach_instance(std::function)> transformHandler); + /// + /// Invokes the handler function for each instanced object. + /// + /// + /// The handling function: + /// instancedObject is the object that is being instanced. + /// parent is the object that has the geometry node modifier. + /// transforms is the collection of transforms for the instanced object. + /// + static void foreach_instanced_object(std::function)> handler); void setInstancesDirty(bool dirty); bool getInstancesDirty(); @@ -40,6 +51,7 @@ namespace blender { struct Record { Object* obj = nullptr; + Object* parent = nullptr; SharedVector matrices; bool handled = false; }; From 412f5ff7b9c103baf36f0e3529b23b686a535b83 Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Mon, 28 Mar 2022 21:58:23 +0100 Subject: [PATCH 37/67] Geometry Nodes: Better support for exporting objects that are not part of the file --- .../BlenderPyObjects/BlenderPyContext.cpp | 2 +- .../MeshSyncClientBlender/msblenContext.cpp | 266 ++++++++++-------- .../Src/MeshSyncClientBlender/msblenContext.h | 62 ++-- .../msblenContextDefaultPathProvider.cpp | 11 + .../msblenContextDefaultPathProvider.h | 13 + .../msblenContextIntermediatePathProvider.cpp | 38 +++ .../msblenContextIntermediatePathProvider.h | 8 + .../msblenContextPathProvider.h | 9 + .../msblenContextState.cpp | 11 +- .../msblenContextState.h | 8 +- .../msblenGeometryNodes.cpp | 55 ++-- .../msblenGeometryNodes.h | 14 +- .../Src/MeshSyncClientBlender/msblenUtils.cpp | 195 ++++++------- .../Src/MeshSyncClientBlender/msblenUtils.h | 178 ++++++------ 14 files changed, 509 insertions(+), 361 deletions(-) create mode 100644 Plugins~/Src/MeshSyncClientBlender/msblenContextDefaultPathProvider.cpp create mode 100644 Plugins~/Src/MeshSyncClientBlender/msblenContextDefaultPathProvider.h create mode 100644 Plugins~/Src/MeshSyncClientBlender/msblenContextIntermediatePathProvider.cpp create mode 100644 Plugins~/Src/MeshSyncClientBlender/msblenContextIntermediatePathProvider.h create mode 100644 Plugins~/Src/MeshSyncClientBlender/msblenContextPathProvider.h diff --git a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp index ed76df6a..2c7c8afb 100644 --- a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp @@ -92,7 +92,7 @@ bool BlenderPyContext::object_instances_is_instance(PointerRNA object) { void BlenderPyContext::world_matrix_get(PointerRNA* instance, mu::float4x4* result) { auto floatProp = (FloatPropertyRNA*)BlenderPyContext_depsgraph_world_matrix; - floatProp->getarray(instance, &(result->m[0][0])); // Sean Dillon - TODO: is the matrix object memory guaranteed to be aligned? + floatProp->getarray(instance, &(result->m[0][0])); } Object* BlenderPyContext::instance_parent_get(PointerRNA* instance) { diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index d9984898..b7507504 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -34,6 +34,8 @@ namespace bl = blender; +using namespace msblenUtils; + static const mu::float4x4 g_arm_to_world = mu::float4x4{ 1, 0, 0, 0, 0, 0,-1, 0, @@ -304,7 +306,7 @@ static void extract_bone_trs(const mu::float4x4& mat, mu::float3& t, mu::quatf& s = mu::swap_yz(s); } -void msblenContext::extractTransformData(const Object *obj, +void msblenContext::extractTransformData(BlenderSyncSettings& settings, const Object *obj, mu::float3& t, mu::quatf& r, mu::float3& s, ms::VisibilityFlags& vis, mu::float4x4 *dst_world, mu::float4x4 *dst_local) { @@ -317,7 +319,7 @@ void msblenContext::extractTransformData(const Object *obj, if (dst_local) *dst_local = local; - if (m_settings.BakeTransform) { + if (settings.BakeTransform) { if (is_camera(obj) || is_light(obj)) { mu::extract_trs(world, t, r, s); } @@ -332,14 +334,14 @@ void msblenContext::extractTransformData(const Object *obj, } } -void msblenContext::extractTransformData(const Object *src, ms::Transform& dst) +void msblenContext::extractTransformData(BlenderSyncSettings& settings, const Object *src, ms::Transform& dst) { - extractTransformData(src, dst.position, dst.rotation, dst.scale, dst.visibility, &dst.world_matrix, &dst.local_matrix); + extractTransformData(settings, src, dst.position, dst.rotation, dst.scale, dst.visibility, &dst.world_matrix, &dst.local_matrix); } -void msblenContext::extractTransformData(const bPoseChannel *src, mu::float3& t, mu::quatf& r, mu::float3& s) +void msblenContext::extractTransformData(BlenderSyncSettings& settings, const bPoseChannel *src, mu::float3& t, mu::quatf& r, mu::float3& s) { - if (m_settings.BakeTransform) { + if (settings.BakeTransform) { t = mu::float3::zero(); r = mu::quatf::identity(); s = mu::float3::one(); @@ -404,6 +406,8 @@ void msblenContext::extractLightData(const Object *src, ms::TransformPtr msblenContext::exportObject( msblenContextState& state, + msblenContextPathProvider& paths, + BlenderSyncSettings& settings, const Object* obj, bool parent, bool tip) { @@ -411,25 +415,25 @@ ms::TransformPtr msblenContext::exportObject( if (!obj) return nullptr; - msblenContextState::ObjectRecord& rec = state.touchRecord(obj); + msblenContextState::ObjectRecord& rec = state.touchRecord(paths, obj); if (rec.dst) return rec.dst; // already exported auto handle_parent = [&]() { if (parent) - exportObject(state, obj->parent, parent, false); + exportObject(state, paths, settings, obj->parent, parent, false); }; auto handle_transform = [&]() { handle_parent(); - rec.dst = exportTransform(state, obj); + rec.dst = exportTransform(state, paths, settings, obj); }; switch (obj->type) { case OB_ARMATURE: { - if (!tip || (!m_settings.BakeModifiers && m_settings.sync_bones)) { + if (!tip || (!settings.BakeModifiers && settings.sync_bones)) { handle_parent(); - rec.dst = exportArmature(state, obj); + rec.dst = exportArmature(state, paths, settings, obj); } else if (!tip && parent) handle_transform(); @@ -437,13 +441,13 @@ ms::TransformPtr msblenContext::exportObject( } case OB_MESH: { - if (!m_settings.BakeModifiers && m_settings.sync_bones) { + if (!settings.BakeModifiers && settings.sync_bones) { if (auto* arm_mod = (const ArmatureModifierData*)FindModifier(obj, eModifierType_Armature)) - exportObject(state, arm_mod->object, parent); + exportObject(state, paths, settings, arm_mod->object, parent); } - if (m_settings.sync_meshes || (!m_settings.BakeModifiers && m_settings.sync_blendshapes)) { + if (settings.sync_meshes || (!settings.BakeModifiers && settings.sync_blendshapes)) { handle_parent(); - rec.dst = exportMesh(state, obj); + rec.dst = exportMesh(state,paths, settings, obj); } else if (!tip && parent) handle_transform(); @@ -454,9 +458,9 @@ ms::TransformPtr msblenContext::exportObject( case OB_SURF: // case OB_MBALL: // these can be converted to mesh { - if (m_settings.sync_meshes && m_settings.curves_as_mesh) { + if (settings.sync_meshes && settings.curves_as_mesh) { handle_parent(); - rec.dst = exportMesh(state, obj); + rec.dst = exportMesh(state, paths, settings, obj); } else if (!tip && parent) handle_transform(); @@ -464,9 +468,9 @@ ms::TransformPtr msblenContext::exportObject( } case OB_CAMERA: { - if (m_settings.sync_cameras) { + if (settings.sync_cameras) { handle_parent(); - rec.dst = exportCamera(state, obj); + rec.dst = exportCamera(state, paths, settings, obj); } else if (!tip && parent) handle_transform(); @@ -474,9 +478,9 @@ ms::TransformPtr msblenContext::exportObject( } case OB_LAMP: { - if (m_settings.sync_lights) { + if (settings.sync_lights) { handle_parent(); - rec.dst = exportLight(state, obj); + rec.dst = exportLight(state, paths, settings, obj); } else if (!tip && parent) handle_transform(); @@ -486,7 +490,7 @@ ms::TransformPtr msblenContext::exportObject( { if (get_instance_collection(obj) || (!tip && parent)) { handle_parent(); - rec.dst = exportTransform(state, obj); + rec.dst = exportTransform(state, paths, settings, obj); } break; } @@ -498,61 +502,62 @@ ms::TransformPtr msblenContext::exportObject( ctx.group_host = obj; ctx.dst = rec.dst; - exportDupliGroup(state, obj, ctx); + exportDupliGroup(state, paths, settings, obj, ctx); } } return rec.dst; } -ms::TransformPtr msblenContext::exportTransform(msblenContextState& state, const Object *src) +ms::TransformPtr msblenContext::exportTransform(msblenContextState& state, msblenContextPathProvider& paths, BlenderSyncSettings& settings, const Object *src) { std::shared_ptr ret = ms::Transform::create(); ms::Transform& dst = *ret; - dst.path = get_path(src); - extractTransformData(src, dst); + dst.path = paths.get_path(src); + extractTransformData(settings, src, dst); state.manager.add(ret); return ret; } -ms::TransformPtr msblenContext::exportPose(msblenContextState& state, const Object *armature, bPoseChannel *src) +ms::TransformPtr msblenContext::exportPose(msblenContextState& state, msblenContextPathProvider& paths, BlenderSyncSettings& settings, const Object *armature, bPoseChannel *src) { std::shared_ptr ret = ms::Transform::create(); ms::Transform& dst = *ret; - dst.path = get_path(armature, src->bone); - extractTransformData(src, dst.position, dst.rotation, dst.scale); + + dst.path = paths.get_path(armature, src->bone); + extractTransformData(settings, src, dst.position, dst.rotation, dst.scale); state.manager.add(ret); return ret; } -ms::TransformPtr msblenContext::exportArmature(msblenContextState& state, const Object *src) +ms::TransformPtr msblenContext::exportArmature(msblenContextState& state, msblenContextPathProvider& paths, BlenderSyncSettings& settings, const Object *src) { std::shared_ptr ret = ms::Transform::create(); ms::Transform& dst = *ret; - dst.path = get_path(src); - extractTransformData(src, dst); + dst.path = paths.get_path(src); + extractTransformData(settings, src, dst); state.manager.add(ret); for (struct bPoseChannel* pose : bl::list_range((bPoseChannel*)src->pose->chanbase.first)) { struct Bone* bone = pose->bone; std::map>::mapped_type& dst = state.bones[bone]; - dst = exportPose(state, src, pose); + dst = exportPose(state, paths, settings, src, pose); } return ret; } -ms::TransformPtr msblenContext::exportReference(msblenContextState& state, Object *src, const DupliGroupContext& ctx) +ms::TransformPtr msblenContext::exportReference(msblenContextState& state, msblenContextPathProvider& paths, BlenderSyncSettings& settings, Object *src, const DupliGroupContext& ctx) { - auto& rec = state.touchRecord(src); + auto& rec = state.touchRecord(paths, src); if (!rec.dst) return nullptr; - const std::string local_path = get_path(src); + const std::string local_path = paths.get_path(src); std::string path = ctx.dst->path + local_path; ms::TransformPtr dst; auto assign_base_params = [&]() { - extractTransformData(src, *dst); + extractTransformData(settings, src, *dst); dst->path = path; // todo: dst->visibility = {}; @@ -560,7 +565,7 @@ ms::TransformPtr msblenContext::exportReference(msblenContextState& state, Objec }; if (is_mesh(src)) { - if (m_settings.BakeTransform) { + if (settings.BakeTransform) { dst = ms::Mesh::create(); ms::Mesh& dst_mesh = static_cast(*dst); ms::Mesh& src_mesh = static_cast(*rec.dst); @@ -569,16 +574,16 @@ ms::TransformPtr msblenContext::exportReference(msblenContextState& state, Objec assign_base_params(); auto& manager = state.manager; - auto do_merge = [this, dst, &dst_mesh, &src_mesh, &manager]() { + auto do_merge = [this, dst, &dst_mesh, &src_mesh, &manager,&settings]() { dst_mesh.merge(src_mesh); - if (m_settings.ExportSceneCache) + if (settings.ExportSceneCache) dst_mesh.detach(); dst_mesh.refine_settings = src_mesh.refine_settings; dst_mesh.refine_settings.local2world = dst_mesh.world_matrix; dst_mesh.refine_settings.flags.Set(ms::MESH_REFINE_FLAG_LOCAL2WORLD, true); manager.add(dst); }; - if (m_settings.multithreaded) + if (settings.multithreaded) // deferred to execute after extracting src mesh data is completed m_asyncTasksController.AddTask(std::launch::deferred, do_merge); else @@ -598,7 +603,7 @@ ms::TransformPtr msblenContext::exportReference(msblenContextState& state, Objec } each_child(src, [&](Object *child) { - exportReference(state, child, ctx); + exportReference(state, paths, settings, child, ctx); }); if (get_instance_collection(src)) { @@ -606,12 +611,12 @@ ms::TransformPtr msblenContext::exportReference(msblenContextState& state, Objec ctx2.group_host = src; ctx2.dst = dst; - exportDupliGroup(state, src, ctx2); + exportDupliGroup(state, paths, settings, src, ctx2); } return dst; } -ms::TransformPtr msblenContext::exportDupliGroup(msblenContextState& state, const Object *src, const DupliGroupContext& ctx) +ms::TransformPtr msblenContext::exportDupliGroup(msblenContextState& state, msblenContextPathProvider& paths, BlenderSyncSettings& settings, const Object *src, const DupliGroupContext& ctx) { Collection* group = get_instance_collection(src); if (!group) @@ -625,7 +630,7 @@ ms::TransformPtr msblenContext::exportDupliGroup(msblenContextState& state, cons dst->visibility = { true, visible_in_render(ctx.group_host), visible_in_viewport(ctx.group_host) }; const mu::tvec3 offset_pos = -get_instance_offset(group); - dst->position = m_settings.BakeTransform ? mu::float3::zero() : offset_pos; + dst->position = settings.BakeTransform ? mu::float3::zero() : offset_pos; dst->world_matrix = mu::translate(offset_pos) * ctx.dst->world_matrix; state.manager.add(dst); @@ -635,39 +640,39 @@ ms::TransformPtr msblenContext::exportDupliGroup(msblenContextState& state, cons auto gobjects = bl::list_range((CollectionObject*)group->gobject.first); for (auto go : gobjects) { auto obj = go->ob; - if (auto t = exportObject(state, obj, true, false)) { + if (auto t = exportObject(state, paths, settings, obj, true, false)) { const bool non_lib = obj->id.lib == nullptr; t->visibility = { true, non_lib, non_lib }; } - exportReference(state, obj, ctx2); + exportReference(state, paths, settings, obj, ctx2); } return dst; } -ms::CameraPtr msblenContext::exportCamera(msblenContextState& state, const Object *src) +ms::CameraPtr msblenContext::exportCamera(msblenContextState& state, msblenContextPathProvider& paths, BlenderSyncSettings& settings, const Object *src) { std::shared_ptr ret = ms::Camera::create(); ms::Camera& dst = *ret; - dst.path = get_path(src); - extractTransformData(src, dst); + dst.path = paths.get_path(src); + extractTransformData(settings, src, dst); extractCameraData(src, dst.is_ortho, dst.near_plane, dst.far_plane, dst.fov, dst.focal_length, dst.sensor_size, dst.lens_shift); state.manager.add(ret); return ret; } -ms::LightPtr msblenContext::exportLight(msblenContextState& state, const Object *src) +ms::LightPtr msblenContext::exportLight(msblenContextState& state, msblenContextPathProvider& paths, BlenderSyncSettings& settings, const Object *src) { std::shared_ptr ret = ms::Light::create(); ms::Light& dst = *ret; - dst.path = get_path(src); - extractTransformData(src, dst); + dst.path = paths.get_path(src); + extractTransformData(settings, src, dst); extractLightData(src, dst.light_type, dst.shadow_type, dst.color, dst.intensity, dst.range, dst.spot_angle); state.manager.add(ret); return ret; } -ms::MeshPtr msblenContext::exportMesh(msblenContextState& state, const Object *src) +ms::MeshPtr msblenContext::exportMesh(msblenContextState& state, msblenContextPathProvider& paths, BlenderSyncSettings& settings, const Object *src) { // ignore particles if (//FindModifier(src, eModifierType_ParticleSystem) || @@ -680,7 +685,7 @@ ms::MeshPtr msblenContext::exportMesh(msblenContextState& state, const Object *s data = (Mesh*)src->data; bool is_editing = false; - if (m_settings.sync_meshes && data) { + if (settings.sync_meshes && data) { // check if mesh is dirty if (BMEditMesh* edit_mesh = get_edit_mesh(data)) { is_editing = true; @@ -695,18 +700,18 @@ ms::MeshPtr msblenContext::exportMesh(msblenContextState& state, const Object *s std::shared_ptr ret = ms::Mesh::create(); ms::Mesh& dst = *ret; - dst.path = get_path(src); + dst.path = paths.get_path(src); // transform - extractTransformData(src, dst); + extractTransformData(settings, src, dst); - if (m_settings.sync_meshes) { + if (settings.sync_meshes) { const bool need_convert = - (!is_editing && m_settings.BakeModifiers ) || !is_mesh(src); + (!is_editing && settings.BakeModifiers ) || !is_mesh(src); if (need_convert) { - if (m_settings.BakeModifiers) { + if (settings.BakeModifiers) { auto blContext = bl::BlenderPyContext::get(); Depsgraph* depsgraph = blContext.evaluated_depsgraph_get(); bobj = (Object*)bl::BlenderPyID(bobj).evaluated_get(depsgraph); @@ -719,7 +724,7 @@ ms::MeshPtr msblenContext::exportMesh(msblenContextState& state, const Object *s // calculate per index normals // note: when bake_modifiers is enabled, it is done for baked meshes - if (data && m_settings.sync_normals && m_settings.calc_per_index_normals) { + if (data && settings.sync_normals && settings.calc_per_index_normals) { // calc_normals_split() seems can't be multi-threaded. it will cause unpredictable crash... // todo: calculate normals by myself to be multi-threaded bl::BMesh(data).calc_normals_split(); @@ -727,13 +732,13 @@ ms::MeshPtr msblenContext::exportMesh(msblenContextState& state, const Object *s } if (data) { - auto task = [this, ret, src, data, &state]() { + auto task = [this, ret, src, data, &state, &settings]() { auto& dst = *ret; - doExtractMeshData(state, dst, src, data, dst.world_matrix); + doExtractMeshData(state, settings, dst, src, data, dst.world_matrix); state.manager.add(ret); }; - if (m_settings.multithreaded) + if (settings.multithreaded) m_asyncTasksController.AddTask(std::launch::async, task); else task(); @@ -741,9 +746,9 @@ ms::MeshPtr msblenContext::exportMesh(msblenContextState& state, const Object *s return ret; } -void msblenContext::doExtractMeshData(msblenContextState& state, ms::Mesh& dst, const Object *obj, Mesh *data, mu::float4x4 world) +void msblenContext::doExtractMeshData(msblenContextState& state, BlenderSyncSettings& settings, ms::Mesh& dst, const Object *obj, Mesh *data, mu::float4x4 world) { - if (m_settings.sync_meshes) { + if (settings.sync_meshes) { bl::BObject bobj(obj); bl::BMesh bmesh(data); const bool is_editing = get_edit_mesh(bmesh.ptr()) != nullptr; @@ -751,13 +756,13 @@ void msblenContext::doExtractMeshData(msblenContextState& state, ms::Mesh& dst, // on edit mode, editing is applied to EditMesh and base Mesh is intact. so get data from EditMesh on edit mode. // todo: Blender 2.8 displays transparent final mesh on edit mode. extract data from it. if (is_editing) { - doExtractEditMeshData(state, dst, obj, data); + doExtractEditMeshData(state, settings, dst, obj, data); } else { - doExtractNonEditMeshData(state, dst, obj, data); + doExtractNonEditMeshData(state, settings, dst, obj, data); } - if (!m_settings.BakeModifiers&& !is_editing) { + if (!settings.BakeModifiers&& !is_editing) { // mirror if (const MirrorModifierData* mirror = (const MirrorModifierData*)FindModifier(obj, eModifierType_Mirror)) { if (mirror->flag & MOD_MIR_AXIS_X) dst.refine_settings.flags.Set(ms::MESH_REFINE_FLAG_MIRROR_X, true); @@ -771,14 +776,14 @@ void msblenContext::doExtractMeshData(msblenContextState& state, ms::Mesh& dst, } } } - if (m_settings.BakeTransform) { + if (settings.BakeTransform) { dst.refine_settings.local2world = world; dst.refine_settings.flags.Set(ms::MESH_REFINE_FLAG_LOCAL2WORLD, true); } } else { - if (!m_settings.BakeModifiers&& m_settings.sync_blendshapes) { - doExtractBlendshapeWeights(state, dst, obj, data); + if (!settings.BakeModifiers&& settings.sync_blendshapes) { + doExtractBlendshapeWeights(state, settings, dst, obj, data); } } @@ -787,15 +792,15 @@ void msblenContext::doExtractMeshData(msblenContextState& state, ms::Mesh& dst, if (dst.tangents.empty()) dst.refine_settings.flags.Set(ms::MESH_REFINE_FLAG_GEN_TANGENTS, true); dst.refine_settings.flags.Set(ms::MESH_REFINE_FLAG_FLIP_FACES, true); - dst.refine_settings.flags.Set(ms::MESH_REFINE_FLAG_MAKE_DOUBLE_SIDED, m_settings.make_double_sided); + dst.refine_settings.flags.Set(ms::MESH_REFINE_FLAG_MAKE_DOUBLE_SIDED, settings.make_double_sided); } -void msblenContext::doExtractBlendshapeWeights(msblenContextState& state, ms::Mesh& dst, const Object *obj, Mesh *data) +void msblenContext::doExtractBlendshapeWeights(msblenContextState& state, BlenderSyncSettings& settings, ms::Mesh& dst, const Object *obj, Mesh *data) { struct Mesh& mesh = *data; - if (!m_settings.BakeModifiers) { + if (!settings.BakeModifiers) { // blend shapes - if (m_settings.sync_blendshapes && mesh.key) { + if (settings.sync_blendshapes && mesh.key) { RawVector basis; int bi = 0; each_key(&mesh, [&](const KeyBlock *kb) { @@ -811,12 +816,7 @@ void msblenContext::doExtractBlendshapeWeights(msblenContextState& state, ms::Me } } - -void msblenContext::doExtractNonEditMeshData(msblenContextState& state, ms::Mesh& dst, const Object* obj, Mesh* data) { - doExtractNonEditMeshData(state, dst, obj, data, m_settings); -} - -void msblenContext::doExtractNonEditMeshData(msblenContextState& state, ms::Mesh& dst, const Object *obj, Mesh *data, BlenderSyncSettings& settings) +void msblenContext::doExtractNonEditMeshData(msblenContextState& state, BlenderSyncSettings& settings, ms::Mesh& dst, const Object *obj, Mesh *data) { bl::BObject bobj(obj); bl::BMesh bmesh(data); @@ -1025,7 +1025,7 @@ void msblenContext::doExtractNonEditMeshData(msblenContextState& state, ms::Mesh #endif } -void msblenContext::doExtractEditMeshData(msblenContextState& state, ms::Mesh& dst, const Object *obj, Mesh *data) +void msblenContext::doExtractEditMeshData(msblenContextState& state, BlenderSyncSettings& settings, ms::Mesh& dst, const Object *obj, Mesh *data) { bl::BObject bobj(obj); bl::BMesh bmesh(data); @@ -1075,7 +1075,7 @@ void msblenContext::doExtractEditMeshData(msblenContextState& state, ms::Mesh& d } // normals - if (m_settings.sync_normals) { + if (settings.sync_normals) { #if 0 // per-vertex dst.normals.resize_discard(num_vertices); @@ -1093,7 +1093,7 @@ void msblenContext::doExtractEditMeshData(msblenContextState& state, ms::Mesh& d } // uv - if (m_settings.sync_uvs) { + if (settings.sync_uvs) { //const int offset = emesh.uv_data_offset(); //if (offset != -1) { // dst.m_uv[0].resize_discard(num_indices); @@ -1119,12 +1119,12 @@ ms::TransformPtr msblenContext::findBone(msblenContextState& state, Object *arma } -void msblenContext::exportAnimation(Object *obj, bool force, const std::string& base_path) +void msblenContext::exportAnimation(msblenContextPathProvider& paths, BlenderSyncSettings& settings, Object *obj, bool force, const std::string& base_path) { if (!obj) return; - std::string path = base_path + get_path(obj); + std::string path = base_path + paths.get_path(obj); if (m_anim_records.find(path) != m_anim_records.end()) return; @@ -1133,12 +1133,13 @@ void msblenContext::exportAnimation(Object *obj, bool force, const std::string& AnimationRecord::extractor_t extractor = nullptr; Collection* group = get_instance_collection(obj); - auto add_animation = [this, &clip](const std::string& path, void *obj, ms::TransformAnimationPtr dst, AnimationRecord::extractor_t extractor) { + auto add_animation = [this, &clip](BlenderSyncSettings& settings, const std::string& path, void *obj, ms::TransformAnimationPtr dst, AnimationRecord::extractor_t extractor) { dst->path = path; std::map, AnimationRecord>::mapped_type& rec = m_anim_records[path]; rec.extractor = extractor; rec.obj = obj; rec.dst = dst; + rec.settings = settings; clip->addAnimation(dst); }; @@ -1146,35 +1147,35 @@ void msblenContext::exportAnimation(Object *obj, bool force, const std::string& case OB_CAMERA: { // camera - exportAnimation(obj->parent, true, base_path); - add_animation(path, obj, ms::CameraAnimation::create(), &msblenContext::extractCameraAnimationData); + exportAnimation(paths, settings, obj->parent, true, base_path); + add_animation(settings, path, obj, ms::CameraAnimation::create(), &msblenContext::extractCameraAnimationData); break; } case OB_LAMP: { // lights - exportAnimation(obj->parent, true, base_path); - add_animation(path, obj, ms::LightAnimation::create(), &msblenContext::extractLightAnimationData); + exportAnimation(paths, settings, obj->parent, true, base_path); + add_animation(settings, path, obj, ms::LightAnimation::create(), &msblenContext::extractLightAnimationData); break; } case OB_MESH: { // meshes - exportAnimation(obj->parent, true, base_path); - add_animation(path, obj, ms::MeshAnimation::create(), &msblenContext::extractMeshAnimationData); + exportAnimation(paths, settings, obj->parent, true, base_path); + add_animation(settings, path, obj, ms::MeshAnimation::create(), &msblenContext::extractMeshAnimationData); break; } default: if (force || obj->type == OB_ARMATURE || group) { - exportAnimation(obj->parent, true, base_path); - add_animation(path, obj, ms::TransformAnimation::create(), &msblenContext::extractTransformAnimationData); + exportAnimation(paths, settings, obj->parent, true, base_path); + add_animation(settings, path, obj, ms::TransformAnimation::create(), &msblenContext::extractTransformAnimationData); - if (obj->type == OB_ARMATURE && (!m_settings.BakeModifiers && m_settings.sync_bones)) { + if (obj->type == OB_ARMATURE && (!settings.BakeModifiers && settings.sync_bones)) { // bones blender::blist_range poses = bl::list_range((bPoseChannel*)obj->pose->chanbase.first); for (struct bPoseChannel* pose : poses) { auto pose_path = base_path + get_path(obj, pose->bone); - add_animation(pose_path, pose, ms::TransformAnimation::create(), &msblenContext::extractPoseAnimationData); + add_animation(settings, pose_path, pose, ms::TransformAnimation::create(), &msblenContext::extractPoseAnimationData); } } break; @@ -1191,12 +1192,12 @@ void msblenContext::exportAnimation(Object *obj, bool force, const std::string& auto gobjects = bl::list_range((CollectionObject*)group->gobject.first); for (auto go : gobjects) { - exportAnimation(go->ob, false, group_path); + exportAnimation(paths, settings, go->ob, false, group_path); } } } -void msblenContext::extractTransformAnimationData(ms::TransformAnimation& dst_, void *obj) +void msblenContext::extractTransformAnimationData(BlenderSyncSettings& settings, ms::TransformAnimation& dst_, void *obj) { ms::TransformAnimation& dst = (ms::TransformAnimation&)dst_; @@ -1204,7 +1205,7 @@ void msblenContext::extractTransformAnimationData(ms::TransformAnimation& dst_, mu::quatf rot; mu::float3 scale; ms::VisibilityFlags vis; - extractTransformData((Object*)obj, pos, rot, scale, vis); + extractTransformData(settings, (Object*)obj, pos, rot, scale, vis); float t = m_anim_time; dst.translation.push_back({ t, pos }); @@ -1213,14 +1214,14 @@ void msblenContext::extractTransformAnimationData(ms::TransformAnimation& dst_, dst.visible.push_back({ t, (int)vis.visible_in_render }); } -void msblenContext::extractPoseAnimationData(ms::TransformAnimation& dst_, void *obj) +void msblenContext::extractPoseAnimationData(BlenderSyncSettings& settings, ms::TransformAnimation& dst_, void *obj) { ms::TransformAnimation& dst = (ms::TransformAnimation&)dst_; mu::float3 t; mu::quatf r; mu::float3 s; - extractTransformData((bPoseChannel*)obj, t, r, s); + extractTransformData(settings, (bPoseChannel*)obj, t, r, s); const float time = m_anim_time; dst.translation.push_back({ time, t }); @@ -1228,9 +1229,9 @@ void msblenContext::extractPoseAnimationData(ms::TransformAnimation& dst_, void dst.scale.push_back({ time, s }); } -void msblenContext::extractCameraAnimationData(ms::TransformAnimation& dst_, void *obj) +void msblenContext::extractCameraAnimationData(BlenderSyncSettings& settings, ms::TransformAnimation& dst_, void *obj) { - extractTransformAnimationData(dst_, obj); + extractTransformAnimationData(settings, dst_, obj); ms::CameraAnimation& dst = (ms::CameraAnimation&)dst_; @@ -1248,9 +1249,9 @@ void msblenContext::extractCameraAnimationData(ms::TransformAnimation& dst_, voi dst.lens_shift.push_back({ t , lens_shift }); } -void msblenContext::extractLightAnimationData(ms::TransformAnimation& dst_, void *obj) +void msblenContext::extractLightAnimationData(BlenderSyncSettings& settings, ms::TransformAnimation& dst_, void *obj) { - extractTransformAnimationData(dst_, obj); + extractTransformAnimationData(settings, dst_, obj); ms::LightAnimation& dst = (ms::LightAnimation&)dst_; @@ -1269,9 +1270,9 @@ void msblenContext::extractLightAnimationData(ms::TransformAnimation& dst_, void } } -void msblenContext::extractMeshAnimationData(ms::TransformAnimation & dst_, void * obj) +void msblenContext::extractMeshAnimationData(BlenderSyncSettings& settings, ms::TransformAnimation & dst_, void * obj) { - extractTransformAnimationData(dst_, obj); + extractTransformAnimationData(settings, dst_, obj); ms::MeshAnimation& dst = (ms::MeshAnimation&)dst_; float t = m_anim_time; @@ -1375,14 +1376,14 @@ bool msblenContext::sendObjects(MeshSyncClient::ObjectScope scope, bool dirty_al scene.each_objects([this](Object *obj) { bl::BlenderPyID bid = bl::BlenderPyID(obj); if (bid.is_updated() || bid.is_updated_data()) - exportObject(*m_entities_state, obj, false); + exportObject(*m_entities_state, m_default_paths, m_settings, obj, false); else - m_entities_state->touchRecord(obj); // this cannot be covered by getNodes() + m_entities_state->touchRecord(m_default_paths, obj); // this cannot be covered by getNodes() }); } else { for(std::vector::value_type obj : getNodes(scope)) - exportObject(*m_entities_state, obj, true); + exportObject(*m_entities_state, m_default_paths, m_settings, obj, true); } #if BLENDER_VERSION >= 300 @@ -1392,8 +1393,9 @@ bool msblenContext::sendObjects(MeshSyncClient::ObjectScope scope, bool dirty_al m_instances_state->manager.setAlwaysMarkDirty(true); auto instancesHandler = - std::bind(&msblenContext::exportInstances, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); - blender::GeometryNodesUtils::foreach_instanced_object(instancesHandler); + std::bind(&msblenContext::exportInstances, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4); + + m_geometryNodeUtils.foreach_instanced_object(instancesHandler); m_geometryNodeUtils.setInstancesDirty(false); @@ -1429,7 +1431,7 @@ bool msblenContext::sendAnimations(MeshSyncClient::ObjectScope scope) // list target objects for (std::vector::value_type obj : getNodes(scope)) - exportAnimation(obj, false); + exportAnimation(m_default_paths, m_settings, obj, false); // advance frame and record animations { @@ -1553,7 +1555,7 @@ bool msblenContext::ExportCache(const std::string& path, const BlenderCacheSetti void msblenContext::DoExportSceneCache(const std::vector& nodes) { for (const std::vector::value_type& n : nodes) - exportObject(*m_entities_state, n, true); + exportObject(*m_entities_state, m_default_paths,m_settings, n, true); m_texture_manager.clearDirtyFlags(); WaitAndKickAsyncExport(); @@ -1562,14 +1564,14 @@ void msblenContext::DoExportSceneCache(const std::vector& nodes) //---------------------------------------------------------------------------------------------------------------------- void msblenContext::flushPendingList() { - flushPendingList(*m_entities_state); - flushPendingList(*m_instances_state); + flushPendingList(*m_entities_state, m_default_paths, m_settings); + flushPendingList(*m_instances_state, m_default_paths, m_settings); } -void msblenContext::flushPendingList(msblenContextState& state) { +void msblenContext::flushPendingList(msblenContextState& state, msblenContextPathProvider& paths, BlenderSyncSettings& settings) { if (!state.pending.empty() && !m_sender.isExporting()) { for (auto p : state.pending) - exportObject(state, p, false); + exportObject(state, paths, settings, p, false); state.pending.clear(); WaitAndKickAsyncExport(); @@ -1640,6 +1642,8 @@ void msblenContext::WaitAndKickAsyncExport() m_entity_manager.clearDirtyFlags(); m_animations.clear(); m_instances_state->GetManager().clearDirtyFlags(); + + m_geometryNodeUtils.clear(); }; exporter->kick(); @@ -1662,16 +1666,28 @@ void msblenContext::onDepsgraphUpdatedPost(Depsgraph* graph) /// Geometry Nodes Blender Context Functionality /// #if BLENDER_VERSION >= 300 -void msblenContext::exportInstances(Object* instancedObject, Object* parent, SharedVector mat) { - - exportObject(*m_instances_state, instancedObject, false); +void msblenContext::doExportInstances(msblenContextState& state, msblenContextPathProvider& paths, BlenderSyncSettings& settings, Object* instancedObject, Object* parent, SharedVector mat) { + exportObject(state, paths, settings, instancedObject, false); auto info = ms::InstanceInfo::create(); - info->path = get_path(instancedObject); - info->parent_path = get_path(parent); + info->path = paths.get_path(instancedObject); + info->parent_path = m_default_paths.get_path(parent); // parent will always be part of the scene info->transforms = std::move(mat); m_instances_state->GetManager().add(info); } + +void msblenContext::exportInstances(Object* instancedObject, Object* parent, SharedVector mat, bool fromFile) { + auto settings = m_settings; + settings.BakeTransform = false; + if (fromFile) { + doExportInstances(*m_instances_state, m_default_paths, settings, instancedObject, parent, std::move(mat)); + } + else { + settings.BakeModifiers = false; + settings.multithreaded = false; + doExportInstances(*m_instances_state, m_intermediate_paths, settings, instancedObject, parent, std::move(mat)); + } +} #endif diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h index 2edb74a0..77e5cbb0 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h @@ -24,11 +24,15 @@ #include "MeshSyncClient/msInstancesManager.h" #include "MeshSyncClient/msTransformManager.h" + #if BLENDER_VERSION >= 300 #include #endif + #include "../MeshSyncClientBlender/msblenContextState.h" #include +#include +#include class msblenContext; @@ -60,7 +64,7 @@ class msblenContext { bool ExportCache(const std::string& path, const BlenderCacheSettings& cache_settings); void flushPendingList(); - void flushPendingList(msblenContextState& state); + void flushPendingList(msblenContextState& state, msblenContextPathProvider& paths, BlenderSyncSettings& settings); void onDepsgraphUpdatedPost(Depsgraph* graph); @@ -88,14 +92,15 @@ class msblenContext { struct AnimationRecord { MS_CLASS_DEFAULT_NOCOPY_NOASSIGN(AnimationRecord); - using extractor_t = void (msblenContext::*)(ms::TransformAnimation& dst, void *obj); + using extractor_t = void (msblenContext::*)(BlenderSyncSettings& settings, ms::TransformAnimation& dst, void *obj); void *obj = nullptr; ms::TransformAnimationPtr dst; extractor_t extractor = nullptr; + BlenderSyncSettings settings; void operator()(msblenContext *_this) { - (_this->*extractor)(*dst, obj); + (_this->*extractor)(settings, *dst, obj); } }; @@ -113,53 +118,53 @@ class msblenContext { void RegisterObjectMaterials(const std::vector objects); void RegisterMaterial(Material* mat, const uint32_t matIndex); - ms::TransformPtr exportObject(msblenContextState& state, const Object* obj, bool parent, bool tip = true); - ms::TransformPtr exportTransform(msblenContextState& state, const Object *obj); - ms::TransformPtr exportPose(msblenContextState& state, const Object *armature, bPoseChannel *obj); - ms::TransformPtr exportArmature(msblenContextState& state, const Object *obj); - ms::TransformPtr exportReference(msblenContextState& state, Object *obj, const DupliGroupContext& ctx); - ms::TransformPtr exportDupliGroup(msblenContextState& state, const Object *obj, const DupliGroupContext& ctx); - ms::CameraPtr exportCamera(msblenContextState& state, const Object *obj); - ms::LightPtr exportLight(msblenContextState& state, const Object *obj); - ms::MeshPtr exportMesh(msblenContextState& state, const Object *obj); + ms::TransformPtr exportObject(msblenContextState& state, msblenContextPathProvider& paths, BlenderSyncSettings& settings, const Object* obj, bool parent, bool tip = true); + ms::TransformPtr exportTransform(msblenContextState& state, msblenContextPathProvider& paths, BlenderSyncSettings& settings, const Object *obj); + ms::TransformPtr exportPose(msblenContextState& state, msblenContextPathProvider& paths, BlenderSyncSettings& settings, const Object *armature, bPoseChannel *obj); + ms::TransformPtr exportArmature(msblenContextState& state, msblenContextPathProvider& paths, BlenderSyncSettings& settings, const Object *obj); + ms::TransformPtr exportReference(msblenContextState& state, msblenContextPathProvider& paths, BlenderSyncSettings& settings, Object *obj, const DupliGroupContext& ctx); + ms::TransformPtr exportDupliGroup(msblenContextState& state, msblenContextPathProvider& paths, BlenderSyncSettings& settings, const Object *obj, const DupliGroupContext& ctx); + ms::CameraPtr exportCamera(msblenContextState& state, msblenContextPathProvider& paths, BlenderSyncSettings& settings, const Object *obj); + ms::LightPtr exportLight(msblenContextState& state, msblenContextPathProvider& paths, BlenderSyncSettings& settings, const Object *obj); + ms::MeshPtr exportMesh(msblenContextState& state, msblenContextPathProvider& paths, BlenderSyncSettings& settings, const Object *obj); mu::float4x4 getWorldMatrix(const Object *obj); mu::float4x4 getLocalMatrix(const Object *obj); mu::float4x4 getLocalMatrix(const Bone *bone); mu::float4x4 getLocalMatrix(const bPoseChannel *pose); - void extractTransformData(const Object *src, + void extractTransformData(BlenderSyncSettings& settings, const Object *src, mu::float3& t, mu::quatf& r, mu::float3& s, ms::VisibilityFlags& vis, mu::float4x4 *dst_world = nullptr, mu::float4x4 *dst_local = nullptr); - void extractTransformData(const Object *src, ms::Transform& dst); - void extractTransformData(const bPoseChannel *pose, mu::float3& t, mu::quatf& r, mu::float3& s); + void extractTransformData(BlenderSyncSettings& settings, const Object *src, ms::Transform& dst); + void extractTransformData(BlenderSyncSettings& settings, const bPoseChannel *pose, mu::float3& t, mu::quatf& r, mu::float3& s); void extractCameraData(const Object *src, bool& ortho, float& near_plane, float& far_plane, float& fov, float& focal_length, mu::float2& sensor_size, mu::float2& lens_shift); void extractLightData(const Object *src, ms::Light::LightType& ltype, ms::Light::ShadowType& stype, mu::float4& color, float& intensity, float& range, float& spot_angle); - void doExtractMeshData(msblenContextState& state, ms::Mesh& dst, const Object *obj, Mesh *data, mu::float4x4 world); - void doExtractBlendshapeWeights(msblenContextState& state, ms::Mesh& dst, const Object *obj, Mesh *data); - void doExtractNonEditMeshData(msblenContextState& state, ms::Mesh& dst, const Object *obj, Mesh *data); - void doExtractNonEditMeshData(msblenContextState& state, ms::Mesh& dst,const Object* obj, Mesh* data, BlenderSyncSettings& settings); - void doExtractEditMeshData(msblenContextState& state, ms::Mesh& dst, const Object *obj, Mesh *data); + void doExtractMeshData(msblenContextState& state, BlenderSyncSettings& settings, ms::Mesh& dst, const Object *obj, Mesh *data, mu::float4x4 world); + void doExtractBlendshapeWeights(msblenContextState& state, BlenderSyncSettings& settings, ms::Mesh& dst, const Object *obj, Mesh *data); + void doExtractNonEditMeshData(msblenContextState& state, BlenderSyncSettings& settings, ms::Mesh& dst, const Object *obj, Mesh *data); + void doExtractEditMeshData(msblenContextState& state, BlenderSyncSettings& settings, ms::Mesh& dst, const Object *obj, Mesh *data); ms::TransformPtr findBone(msblenContextState& state, Object* armature, Bone* bone); - void exportAnimation(Object *obj, bool force, const std::string& base_path = ""); - void extractTransformAnimationData(ms::TransformAnimation& dst, void *obj); - void extractPoseAnimationData(ms::TransformAnimation& dst, void *obj); - void extractCameraAnimationData(ms::TransformAnimation& dst, void *obj); - void extractLightAnimationData(ms::TransformAnimation& dst, void *obj); - void extractMeshAnimationData(ms::TransformAnimation& dst, void *obj); + void exportAnimation(msblenContextPathProvider& paths, BlenderSyncSettings& settings, Object *obj, bool force, const std::string& base_path = ""); + void extractTransformAnimationData(BlenderSyncSettings& settings, ms::TransformAnimation& dst, void *obj); + void extractPoseAnimationData(BlenderSyncSettings& settings, ms::TransformAnimation& dst, void *obj); + void extractCameraAnimationData(BlenderSyncSettings& settings, ms::TransformAnimation& dst, void *obj); + void extractLightAnimationData(BlenderSyncSettings& settings, ms::TransformAnimation& dst, void *obj); + void extractMeshAnimationData(BlenderSyncSettings& settings, ms::TransformAnimation& dst, void *obj); void DoExportSceneCache(const std::vector& nodes); void WaitAndKickAsyncExport(); #if BLENDER_VERSION >= 300 - void exportInstances(Object* object, Object* parent, SharedVector); + void exportInstances(Object* object, Object* parent, SharedVector, bool fromFile); + void doExportInstances(msblenContextState& state, msblenContextPathProvider& paths, BlenderSyncSettings& settings, Object* instancedObject, Object* parent, SharedVector mat); #endif private: @@ -167,6 +172,9 @@ class msblenContext { msblenContextState* m_entities_state = nullptr; msblenContextState* m_instances_state = nullptr; + msblenContextDefaultPathProvider m_default_paths; + msblenContextIntermediatePathProvider m_intermediate_paths; + BlenderSyncSettings m_settings; BlenderCacheSettings m_cache_settings; diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContextDefaultPathProvider.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContextDefaultPathProvider.cpp new file mode 100644 index 00000000..5b7edf8e --- /dev/null +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContextDefaultPathProvider.cpp @@ -0,0 +1,11 @@ +#include "msblenContextDefaultPathProvider.h" +#include "msblenUtils.h" + +std::string msblenContextDefaultPathProvider::get_path(const Object* obj) +{ + return msblenUtils::get_path(obj); +} +std::string msblenContextDefaultPathProvider::get_path(const Object* arm, const Bone* obj) { + return msblenUtils::get_path(arm, obj); +} + diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContextDefaultPathProvider.h b/Plugins~/Src/MeshSyncClientBlender/msblenContextDefaultPathProvider.h new file mode 100644 index 00000000..883914b6 --- /dev/null +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContextDefaultPathProvider.h @@ -0,0 +1,13 @@ +#pragma once +#include +#include +#include +#include + +class msblenContextDefaultPathProvider : public msblenContextPathProvider { +public: + std::string get_path(const Object* obj); + std::string get_path(const Object* arm, const Bone* obj); + + +}; \ No newline at end of file diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContextIntermediatePathProvider.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContextIntermediatePathProvider.cpp new file mode 100644 index 00000000..75239e36 --- /dev/null +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContextIntermediatePathProvider.cpp @@ -0,0 +1,38 @@ +#include "msblenContextIntermediatePathProvider.h" +#include "msblenUtils.h" +#include + + +std::string append_id(std::string path, const Object* obj) { + auto data = (ID*)obj->data; + path += "_" + std::to_string(data->session_uuid); + return path; +} + +std::string get_path_with_id(const Object* obj, const Bone* bone = nullptr) { + + std::string path; + if (bone) { + path = msblenUtils::get_path(obj, bone); + } + else { + path = msblenUtils::get_path(obj); + } + + auto data = (ID*)obj->data; + auto name = std::string(data->name); + + return append_id(path, obj); +} + +std::string msblenContextIntermediatePathProvider::get_path(const Object* obj) +{ + auto path = get_path_with_id(obj); + return path; +} + +std::string msblenContextIntermediatePathProvider::get_path(const Object* obj, const Bone* bone) +{ + auto path = get_path_with_id(obj, bone); + return path; +} diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContextIntermediatePathProvider.h b/Plugins~/Src/MeshSyncClientBlender/msblenContextIntermediatePathProvider.h new file mode 100644 index 00000000..d1de5afc --- /dev/null +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContextIntermediatePathProvider.h @@ -0,0 +1,8 @@ +#pragma once +#include + +class msblenContextIntermediatePathProvider: public msblenContextPathProvider { +public: + std::string get_path(const Object* obj); + std::string get_path(const Object* obj, const Bone* bone); +}; \ No newline at end of file diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContextPathProvider.h b/Plugins~/Src/MeshSyncClientBlender/msblenContextPathProvider.h new file mode 100644 index 00000000..2e8e7a6a --- /dev/null +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContextPathProvider.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +class msblenContextPathProvider { +public: + virtual std::string get_path(const Object* obj) = 0; + virtual std::string get_path(const Object* arm, const Bone* obj) = 0; +}; \ No newline at end of file diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContextState.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContextState.cpp index bdded8de..47bae4be 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContextState.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContextState.cpp @@ -1,6 +1,8 @@ #include "msblenContextState.h" #include +using namespace msblenUtils; + void msblenContextState::ObjectRecord::clearState() { touched = renamed = false; @@ -33,6 +35,7 @@ void msblenContextState::clearRecordsState() { } msblenContextState::ObjectRecord& msblenContextState::touchRecord( + msblenContextPathProvider& paths, const Object* obj, const std::string& base_path, bool children) @@ -43,7 +46,7 @@ msblenContextState::ObjectRecord& msblenContextState::touchRecord( rec.touched = true; - std::string local_path = get_path(obj); + std::string local_path = paths.get_path(obj); if (local_path != rec.path) { rec.renamed = true; rec.path = local_path; @@ -56,14 +59,14 @@ msblenContextState::ObjectRecord& msblenContextState::touchRecord( blender::blist_range poses = blender::list_range((bPoseChannel*)obj->pose->chanbase.first); for (struct bPoseChannel* pose : poses) { records[pose->bone].touched = true; - manager.touch(base_path + get_path(obj, pose->bone)); + manager.touch(base_path + paths.get_path(obj, pose->bone)); } } // care children if (children) { each_child(obj, [&](Object* child) { - touchRecord(child, base_path, true); + touchRecord(paths, child, base_path, true); }); } @@ -74,7 +77,7 @@ msblenContextState::ObjectRecord& msblenContextState::touchRecord( auto gobjects = blender::list_range((CollectionObject*)group->gobject.first); for (auto go : gobjects) - touchRecord(go->ob, group_path, true); + touchRecord(paths, go->ob, group_path, true); } return rec; } diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContextState.h b/Plugins~/Src/MeshSyncClientBlender/msblenContextState.h index 5490c862..cef454ab 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContextState.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContextState.h @@ -1,5 +1,7 @@ +#pragma once #include #include "MeshSync/MeshSyncMacros.h" +#include class msblenContextState { public: @@ -43,5 +45,9 @@ class msblenContextState { void clear(); void clearRecordsState(); - msblenContextState::ObjectRecord& msblenContextState::touchRecord(const Object* obj, const std::string& base_path = "", bool children = false); + msblenContextState::ObjectRecord& msblenContextState::touchRecord( + msblenContextPathProvider& path, + const Object* obj, + const std::string& base_path = "", + bool children = false); }; diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp index 12bf715b..9a0911f5 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp @@ -103,40 +103,57 @@ namespace blender { blContext.object_instances_end(&it); } - void GeometryNodesUtils::foreach_instanced_object(function)> handler) { - - map records; + void GeometryNodesUtils::foreach_instanced_object(function, bool)> handler) { + m_records.clear(); + m_records_by_name.clear(); + foreach_instance([&](Object* obj, Object* parent, float4x4 matrix) { auto id = (ID*)obj->data; - auto& rec = records[id->name]; - rec.obj = obj; - rec.parent = parent; + auto& rec = m_records[id->session_uuid]; + + if (!rec.updated) { + rec.parent = parent; + rec.object_copy = *obj; + rec.updated = true; + + m_records_by_name[obj->id.name] = &rec; + } + rec.matrices.push_back(matrix); }); + // Look for objects in the file auto ctx = blender::BlenderPyContext::get(); - auto objects = ctx.data()->objects; LISTBASE_FOREACH(Object*, obj, &objects){ if (obj->data == nullptr) continue; - auto id = (ID*)obj->data; + // Check if there is record with the same object name + auto rec = m_records_by_name.find(obj->id.name); + if (rec == m_records_by_name.end()) + continue; - auto rec = records.find(id->name); - if (rec != records.end()) { - handler(obj, rec->second.parent, std::move(rec->second.matrices)); - rec->second.handled = true; - } + // Check if the data names also match + auto recDataId = (ID*)rec->second->object_copy.data; + auto sceneDataId = (ID*)obj->data; + + if (strcmp(sceneDataId->name + 2, recDataId->name + 2) != 0) + continue; + + handler(obj, rec->second->parent, std::move(rec->second->matrices), true); + rec->second->handled = true; } - for(auto& rec : records) { + // Export objects that are not in the file + for(auto& rec : m_records) { if (rec.second.handled) continue; - - // handler(rec.second.obj, std::move(rec.second.matrices)); + + handler(&rec.second.object_copy, rec.second.parent, std::move(rec.second.matrices), false); + rec.second.handled= true; } } @@ -148,5 +165,11 @@ namespace blender { { return m_instances_dirty; } + + void blender::GeometryNodesUtils::clear() + { + m_records.clear(); + m_records_by_name.clear(); + } #endif } diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h index d177eb6b..8ce101cc 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h @@ -30,7 +30,7 @@ namespace blender { /// instancedObject is the object that is being instanced. /// transform is the transform of the instance /// - static void foreach_instance(std::function handler); + void foreach_instance(std::function handler); /// /// Invokes the handler function for each instanced object. @@ -41,21 +41,29 @@ namespace blender { /// parent is the object that has the geometry node modifier. /// transforms is the collection of transforms for the instanced object. /// - static void foreach_instanced_object(std::function)> handler); + void foreach_instanced_object(std::function, bool)> handler); void setInstancesDirty(bool dirty); bool getInstancesDirty(); + void clear(); + private: bool m_instances_dirty; struct Record { - Object* obj = nullptr; + Object object_copy; Object* parent = nullptr; SharedVector matrices; bool handled = false; + bool updated = false; }; + + std::map m_records; + std::map m_records_by_name; }; + + #endif } diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenUtils.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenUtils.cpp index 1e1a7d77..e95d6a16 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenUtils.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenUtils.cpp @@ -4,121 +4,124 @@ #include "msblenUtils.h" namespace bl = blender; - -std::string get_name(const Material *obj) -{ - std::string ret; - if (obj) { - ret.assign(obj->id.name + 2); - mu::SanitizeNodeName(ret); +namespace msblenUtils { + std::string get_name(const Material* obj) + { + std::string ret; + if (obj) { + ret.assign(obj->id.name + 2); + mu::SanitizeNodeName(ret); + } + return ret; } - return ret; -} -std::string get_name(const Object *obj) -{ - std::string ret; - if (obj) { - ret.assign(obj->id.name + 2); - mu::SanitizeNodeName(ret); + std::string get_name(const Object* obj) + { + std::string ret; + if (obj) { + ret.assign(obj->id.name + 2); + mu::SanitizeNodeName(ret); + } + return ret; } - return ret; -} -std::string get_name(const Bone *obj) -{ - std::string ret; - if (obj) { - ret.assign(obj->name); - mu::SanitizeNodeName(ret); + std::string get_name(const Bone* obj) + { + std::string ret; + if (obj) { + ret.assign(obj->name); + mu::SanitizeNodeName(ret); + } + return ret; } - return ret; -} -std::string get_path(const Object *obj) -{ - std::string ret; - if (obj->parent) { - if (obj->partype == PARBONE) { - if (auto bone = find_bone(obj->parent, obj->parsubstr)) { - ret += get_path(obj->parent, bone); + std::string get_path(const Object* obj) + { + std::string ret; + if (obj->parent) { + if (obj->partype == PARBONE) { + if (auto bone = find_bone(obj->parent, obj->parsubstr)) { + ret += get_path(obj->parent, bone); + } + } + else { + ret += get_path(obj->parent); } } - else { - ret += get_path(obj->parent); - } + ret += '/'; + ret += get_name(obj); + return ret; + } + std::string get_path(const Object* arm, const Bone* obj) + { + std::string ret; + if (obj->parent) + ret += get_path(arm, obj->parent); + else + ret += get_path(arm); + ret += '/'; + ret += get_name(obj); + return ret; } - ret += '/'; - ret += get_name(obj); - return ret; -} -std::string get_path(const Object *arm, const Bone *obj) -{ - std::string ret; - if (obj->parent) - ret += get_path(arm, obj->parent); - else - ret += get_path(arm); - ret += '/'; - ret += get_name(obj); - return ret; -} -bool visible_in_render(const Object *obj) -{ - return !bl::BObject(obj).hide_render(); -} -bool visible_in_viewport(const Object *obj) -{ - return !bl::BObject(obj).hide_viewport(); -} + bool visible_in_render(const Object* obj) + { + return !bl::BObject(obj).hide_render(); + } + bool visible_in_viewport(const Object* obj) + { + return !bl::BObject(obj).hide_viewport(); + } -const ModifierData* FindModifier(const Object *obj, ModifierType type) -{ - for (auto *it = (ModifierData*)obj->modifiers.first; it != nullptr; it = it->next) - if (it->type == type) - return it; - return nullptr;; -} + const ModifierData* FindModifier(const Object* obj, ModifierType type) + { + for (auto* it = (ModifierData*)obj->modifiers.first; it != nullptr; it = it->next) + if (it->type == type) + return it; + return nullptr;; + } -Bone* find_bone_recursive(Bone *bone, const char *name) -{ - if (strcmp(bone->name, name) == 0) { - return bone; + Bone* find_bone_recursive(Bone* bone, const char* name) + { + if (strcmp(bone->name, name) == 0) { + return bone; + } + else { + for (auto* child = (Bone*)bone->childbase.first; child != nullptr; child = child->next) { + auto* found = find_bone_recursive(child, name); + if (found) + return found; + } + } + return nullptr; } - else { - for (auto *child = (Bone*)bone->childbase.first; child != nullptr; child = child->next) { - auto *found = find_bone_recursive(child, name); + + Bone* find_bone(Object* obj, const char* name) + { + if (!obj) { return nullptr; } + auto* arm = (bArmature*)obj->data; + for (auto* bone = (Bone*)arm->bonebase.first; bone != nullptr; bone = bone->next) + { + auto found = find_bone_recursive(bone, name); if (found) return found; } + return nullptr; } - return nullptr; -} -Bone* find_bone(Object *obj, const char *name) -{ - if (!obj) { return nullptr; } - auto *arm = (bArmature*)obj->data; - for (auto *bone = (Bone*)arm->bonebase.first; bone != nullptr; bone = bone->next) + bPoseChannel* find_pose(Object* obj, const char* name) { - auto found = find_bone_recursive(bone, name); - if (found) - return found; + if (!obj || !obj->pose) { return nullptr; } + for (auto* it = (bPoseChannel*)obj->pose->chanbase.first; it != nullptr; it = it->next) + if (std::strcmp(it->name, name) == 0) + return it; + return nullptr; } - return nullptr; -} -bPoseChannel* find_pose(Object *obj, const char *name) -{ - if (!obj || !obj->pose) { return nullptr; } - for (auto *it = (bPoseChannel*)obj->pose->chanbase.first; it != nullptr; it = it->next) - if (std::strcmp(it->name, name) == 0) - return it; - return nullptr; -} + bool is_mesh(const Object* obj) { return obj->type == OB_MESH; } + bool is_camera(const Object* obj) { return obj->type == OB_CAMERA; } + bool is_light(const Object* obj) { return obj->type == OB_LAMP; } + bool is_armature(const Object* obj) { return obj->type == OB_ARMATURE; } -bool is_mesh(const Object *obj) { return obj->type == OB_MESH; } -bool is_camera(const Object *obj) { return obj->type == OB_CAMERA; } -bool is_light(const Object *obj) { return obj->type == OB_LAMP; } -bool is_armature(const Object *obj) { return obj->type == OB_ARMATURE; } + bool is_valid_pointer(void* ptr) { return ptr != nullptr && ptr != ((void*)-1); } +} diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenUtils.h b/Plugins~/Src/MeshSyncClientBlender/msblenUtils.h index 380b9060..9fbd0b9e 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenUtils.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenUtils.h @@ -4,108 +4,110 @@ #include "BlenderPyObjects/BlenderPyContext.h" -std::string get_name(const Material *obj); -std::string get_name(const Object *obj); -std::string get_name(const Bone *obj); -std::string get_path(const Object *obj); -std::string get_path(const Object *arm, const Bone *obj); -bool visible_in_render(const Object *obj); -bool visible_in_viewport(const Object *obj); -const ModifierData* FindModifier(const Object *obj, ModifierType type); -Bone* find_bone_recursive(Bone *bone, const char *name); -Bone* find_bone(Object *obj, const char *name); -bPoseChannel* find_pose(Object *obj, const char *name); - -bool is_mesh(const Object *obj); -bool is_camera(const Object *obj); -bool is_light(const Object *obj); -bool is_armature(const Object *obj); - -inline Collection* get_instance_collection(const Object *obj) { - return obj->instance_collection; -} +namespace msblenUtils { + std::string get_name(const Material* obj); + std::string get_name(const Object* obj); + std::string get_name(const Bone* obj); + std::string get_path(const Object* obj); + std::string get_path(const Object* arm, const Bone* obj); + bool visible_in_render(const Object* obj); + bool visible_in_viewport(const Object* obj); + const ModifierData* FindModifier(const Object* obj, ModifierType type); + Bone* find_bone_recursive(Bone* bone, const char* name); + Bone* find_bone(Object* obj, const char* name); + bPoseChannel* find_pose(Object* obj, const char* name); + + bool is_mesh(const Object* obj); + bool is_camera(const Object* obj); + bool is_light(const Object* obj); + bool is_armature(const Object* obj); + + inline Collection* get_instance_collection(const Object* obj) { + return obj->instance_collection; + } -inline const mu::float3& get_instance_offset(const Collection *col) { - return (mu::float3&)col->instance_offset; -} + inline const mu::float3& get_instance_offset(const Collection* col) { + return (mu::float3&)col->instance_offset; + } -inline BMEditMesh* get_edit_mesh(Mesh *mesh) { - return mesh->edit_mesh; -} + inline BMEditMesh* get_edit_mesh(Mesh* mesh) { + return mesh->edit_mesh; + } -// Body: [](const FCurve*) -> void -template -static inline void each_child(const Object *obj, const Body& body) -{ - // Object doesn't have children data. need to enumerate all objects and check its parent... - auto bpy_data = blender::BData(blender::BlenderPyContext::get().data()); - for (auto obj : bpy_data.objects()) { - if (obj->parent == obj) - body(obj); + // Body: [](const FCurve*) -> void + template + static inline void each_child(const Object* obj, const Body& body) + { + // Object doesn't have children data. need to enumerate all objects and check its parent... + auto bpy_data = blender::BData(blender::BlenderPyContext::get().data()); + for (auto obj : bpy_data.objects()) { + if (obj->parent == obj) + body(obj); + } } -} -// Body: [](const FCurve*) -> void -template -static inline void each_fcurve(Object *obj, const Body& body) -{ - if (!obj->adt || !obj->adt->action) return; - for (auto *curve = (FCurve*)obj->adt->action->curves.first; curve; curve = curve->next) { - body(curve); + // Body: [](const FCurve*) -> void + template + static inline void each_fcurve(Object* obj, const Body& body) + { + if (!obj->adt || !obj->adt->action) return; + for (auto* curve = (FCurve*)obj->adt->action->curves.first; curve; curve = curve->next) { + body(curve); + } } -} -// Body: [](const ModifierData*) -> void -template -inline void each_modifier(Object *obj, const Body& body) -{ - auto *it = (const ModifierData*)obj->modifiers.first; - auto *end = (const ModifierData*)obj->modifiers.last; - for (; it != end; it = it->next) - body(it); -} + // Body: [](const ModifierData*) -> void + template + inline void each_modifier(Object* obj, const Body& body) + { + auto* it = (const ModifierData*)obj->modifiers.first; + auto* end = (const ModifierData*)obj->modifiers.last; + for (; it != end; it = it->next) + body(it); + } -// Body: [](const bDeformGroup*) -> void -template -static inline void each_deform_group(const Object *obj, const Body& body) -{ - for (auto *it = (const bDeformGroup*)obj->defbase.first; it != nullptr; it = it->next) - body(it); -} + // Body: [](const bDeformGroup*) -> void + template + static inline void each_deform_group(const Object* obj, const Body& body) + { + for (auto* it = (const bDeformGroup*)obj->defbase.first; it != nullptr; it = it->next) + body(it); + } -// Body: [](const KeyBlock*) -> void -template -static inline void each_key(Mesh *obj, const Body& body) -{ - if (obj->key == nullptr || obj->key->block.first == nullptr) { return; } - for (auto *it = (const KeyBlock*)obj->key->block.first; it != nullptr; it = it->next) - body(it); -} + // Body: [](const KeyBlock*) -> void + template + static inline void each_key(Mesh* obj, const Body& body) + { + if (obj->key == nullptr || obj->key->block.first == nullptr) { return; } + for (auto* it = (const KeyBlock*)obj->key->block.first; it != nullptr; it = it->next) + body(it); + } -inline mu::float3 to_float3(const float(&v)[3]) -{ - return (mu::float3&)v; -} + inline mu::float3 to_float3(const float(&v)[3]) + { + return (mu::float3&)v; + } -inline mu::float3 to_float3(const short(&v)[3]) -{ - return mu::float3{ - v[0] * (1.0f / 32767.0f), - v[1] * (1.0f / 32767.0f), - v[2] * (1.0f / 32767.0f), - }; -} + inline mu::float3 to_float3(const short(&v)[3]) + { + return mu::float3{ + v[0] * (1.0f / 32767.0f), + v[1] * (1.0f / 32767.0f), + v[2] * (1.0f / 32767.0f), + }; + } -inline mu::float4 to_float4(const MLoopCol& c) -{ - return mu::float4{ - c.r * (1.0f / 255.0f), - c.g * (1.0f / 255.0f), - c.b * (1.0f / 255.0f), - c.a * (1.0f / 255.0f), - }; + inline mu::float4 to_float4(const MLoopCol& c) + { + return mu::float4{ + c.r * (1.0f / 255.0f), + c.g * (1.0f / 255.0f), + c.b * (1.0f / 255.0f), + c.a * (1.0f / 255.0f), + }; + } } From 21fab1ce7627c73fa89f9e5269d022601ffbbdab Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Wed, 30 Mar 2022 16:45:59 +0100 Subject: [PATCH 38/67] Geometry Nodes: avoid exporting objects that exist in the scene --- .../Src/MeshSyncClient/msInstancesManager.cpp | 3 +- .../MeshSyncClientBlender/msblenContext.cpp | 22 +++++++++- .../Src/MeshSyncClientBlender/msblenContext.h | 1 + .../msblenGeometryNodes.cpp | 42 +++++++++---------- .../msblenGeometryNodes.h | 10 +++-- 5 files changed, 49 insertions(+), 29 deletions(-) diff --git a/Plugins~/Src/MeshSyncClient/msInstancesManager.cpp b/Plugins~/Src/MeshSyncClient/msInstancesManager.cpp index 9b1c2ff1..ae12fef7 100644 --- a/Plugins~/Src/MeshSyncClient/msInstancesManager.cpp +++ b/Plugins~/Src/MeshSyncClient/msInstancesManager.cpp @@ -66,6 +66,7 @@ namespace ms { rec.dirtyInstances = true; } + rec.updated = true; rec.instances = info; } @@ -85,7 +86,7 @@ namespace ms { { for (auto it = m_records.begin(); it != m_records.end(); ) { if (!it->second.updated) { - m_deleted.push_back(it->second.entity->getIdentifier()); + m_deleted.push_back(it->second.instances->getIdentifier()); m_records.erase(it++); } else diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index b7507504..c5143e65 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -1373,6 +1373,7 @@ bool msblenContext::sendObjects(MeshSyncClient::ObjectScope scope, bool dirty_al return true; // nothing to send bl::BlenderPyScene scene = bl::BlenderPyScene(bl::BlenderPyContext::get().scene()); + scene.each_objects([this](Object *obj) { bl::BlenderPyID bid = bl::BlenderPyID(obj); if (bid.is_updated() || bid.is_updated_data()) @@ -1389,6 +1390,13 @@ bool msblenContext::sendObjects(MeshSyncClient::ObjectScope scope, bool dirty_al #if BLENDER_VERSION >= 300 if (m_geometryNodeUtils.getInstancesDirty() || dirty_all) { + bl::BlenderPyScene scene = bl::BlenderPyScene(bl::BlenderPyContext::get().scene()); + + scene.each_objects([this](Object* obj) + { + scene_objects.insert(obj->id.name); + }); + // Assume everything is now dirty m_instances_state->manager.setAlwaysMarkDirty(true); @@ -1399,6 +1407,8 @@ bool msblenContext::sendObjects(MeshSyncClient::ObjectScope scope, bool dirty_al m_geometryNodeUtils.setInstancesDirty(false); + scene_objects.clear(); + m_asyncTasksController.Wait(); m_instances_state->eraseStaleObjects(); @@ -1667,8 +1677,6 @@ void msblenContext::onDepsgraphUpdatedPost(Depsgraph* graph) #if BLENDER_VERSION >= 300 void msblenContext::doExportInstances(msblenContextState& state, msblenContextPathProvider& paths, BlenderSyncSettings& settings, Object* instancedObject, Object* parent, SharedVector mat) { - exportObject(state, paths, settings, instancedObject, false); - auto info = ms::InstanceInfo::create(); info->path = paths.get_path(instancedObject); info->parent_path = m_default_paths.get_path(parent); // parent will always be part of the scene @@ -1681,11 +1689,21 @@ void msblenContext::exportInstances(Object* instancedObject, Object* parent, Sha auto settings = m_settings; settings.BakeTransform = false; if (fromFile) { + + // Export the object from file only if its not part of the scene + auto scene_object = scene_objects.find(instancedObject->id.name); + if (scene_object == scene_objects.end()) { + exportObject(*m_instances_state, m_default_paths, settings, instancedObject, false); + } + doExportInstances(*m_instances_state, m_default_paths, settings, instancedObject, parent, std::move(mat)); } else { settings.BakeModifiers = false; settings.multithreaded = false; + + exportObject(*m_instances_state, m_intermediate_paths, settings, instancedObject, false); + doExportInstances(*m_instances_state, m_intermediate_paths, settings, instancedObject, parent, std::move(mat)); } } diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h index 77e5cbb0..63f47f91 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h @@ -174,6 +174,7 @@ class msblenContext { msblenContextDefaultPathProvider m_default_paths; msblenContextIntermediatePathProvider m_intermediate_paths; + std::unordered_set scene_objects; BlenderSyncSettings m_settings; BlenderCacheSettings m_cache_settings; diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp index 9a0911f5..435e5f8d 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp @@ -13,14 +13,8 @@ using namespace mu; namespace blender { -#if BLENDER_VERSION >= 300 - /// - /// Converts the world matrix from blender to Unity coordinate systems - /// - /// - /// - float4x4 GeometryNodesUtils::blenderToUnityWorldMatrix(float4x4& blenderMatrix) { - + GeometryNodesUtils::GeometryNodesUtils() + { auto rotation = rotate_x(-90 * DegToRad); auto rotation180 = rotate_z(180 * DegToRad); auto scale_z = float3::one(); @@ -29,31 +23,32 @@ namespace blender { auto scale_x = float3::one(); scale_x.x = -1; - auto result = + m_blender_to_unity_world = to_mat4x4(rotation) * - scale44(scale_x) * - blenderMatrix * + scale44(scale_x); + + m_blender_to_unity_local = to_mat4x4(rotation) * to_mat4x4(rotation180) * scale44(scale_z); - return result; - } - mu::float4x4 GeometryNodesUtils::blenderToUnityWorldMatrixMesh() - { - auto rotation = rotate_x(90.0f * DegToRad); - auto scale = float3::one(); - scale.x = -1; + } - auto result = - to_mat4x4(rotation)* - scale44(scale); +#if BLENDER_VERSION >= 300 + /// + /// Converts the world matrix from blender to Unity coordinate systems + /// + /// + /// + float4x4 GeometryNodesUtils::blenderToUnityWorldMatrix(float4x4& blenderMatrix) { - return result; + return + m_blender_to_unity_world * + blenderMatrix * + m_blender_to_unity_local;; } - void GeometryNodesUtils::foreach_instance(std::function handler) { @@ -109,6 +104,7 @@ namespace blender { m_records_by_name.clear(); foreach_instance([&](Object* obj, Object* parent, float4x4 matrix) { + // Critical path, must do as few things as possible auto id = (ID*)obj->data; auto& rec = m_records[id->session_uuid]; diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h index 8ce101cc..1e30d040 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h @@ -15,12 +15,13 @@ namespace blender { class GeometryNodesUtils { public: + + GeometryNodesUtils(); + /// /// /// Converts the world matrix from blender to Unity coordinate system /// /// - static mu::float4x4 blenderToUnityWorldMatrix(mu::float4x4& blenderMatrix); - - static mu::float4x4 blenderToUnityWorldMatrixMesh(); + mu::float4x4 blenderToUnityWorldMatrix(mu::float4x4& blenderMatrix); /// /// Invokes the handler function for each instance. @@ -51,6 +52,9 @@ namespace blender { private: bool m_instances_dirty; + mu::float4x4 m_blender_to_unity_local; + mu::float4x4 m_blender_to_unity_world; + struct Record { Object object_copy; Object* parent = nullptr; From 6a606cb0c3f1c308ec1bf5799601c41739a015e7 Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Wed, 30 Mar 2022 17:01:31 +0100 Subject: [PATCH 39/67] Geometry Nodes: use unordered map instead of map for instances records --- Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h index 1e30d040..0b3f95d5 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h @@ -63,8 +63,8 @@ namespace blender { bool updated = false; }; - std::map m_records; - std::map m_records_by_name; + std::unordered_map m_records; + std::unordered_map m_records_by_name; }; From 5fcc26bd01ee092a24a9c33ae165c5ac00be335e Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Thu, 31 Mar 2022 21:02:55 +0100 Subject: [PATCH 40/67] Geometry Nodes: send local transforms for instances instead of world transforms --- .../Src/MeshSyncClient/msInstancesManager.cpp | 8 +- .../MeshSyncClientBlender/msblenContext.cpp | 80 ++++++++++++++++--- .../Src/MeshSyncClientBlender/msblenContext.h | 15 +++- .../msblenContextIntermediatePathProvider.cpp | 8 +- .../msblenGeometryNodes.cpp | 6 +- 5 files changed, 91 insertions(+), 26 deletions(-) diff --git a/Plugins~/Src/MeshSyncClient/msInstancesManager.cpp b/Plugins~/Src/MeshSyncClient/msInstancesManager.cpp index ae12fef7..eae4ed69 100644 --- a/Plugins~/Src/MeshSyncClient/msInstancesManager.cpp +++ b/Plugins~/Src/MeshSyncClient/msInstancesManager.cpp @@ -43,16 +43,16 @@ namespace ms { m_deleted.clear(); } - void InstancesManager::add(TransformPtr mesh) { + void InstancesManager::add(TransformPtr entity) { - auto& rec = lockAndGet(mesh->path); + auto& rec = lockAndGet(entity->path); - if (m_always_mark_dirty || rec.entity == nullptr || rec.entity->hash() != mesh->hash()) { + if (m_always_mark_dirty || rec.entity == nullptr || rec.entity->hash() != entity->hash()) { rec.dirtyMesh = true; } rec.updated = true; - rec.entity = mesh; + rec.entity = entity; } diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index c5143e65..162248d4 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -1394,7 +1394,7 @@ bool msblenContext::sendObjects(MeshSyncClient::ObjectScope scope, bool dirty_al scene.each_objects([this](Object* obj) { - scene_objects.insert(obj->id.name); + scene_objects.insert(obj); }); // Assume everything is now dirty @@ -1676,36 +1676,90 @@ void msblenContext::onDepsgraphUpdatedPost(Depsgraph* graph) /// Geometry Nodes Blender Context Functionality /// #if BLENDER_VERSION >= 300 -void msblenContext::doExportInstances(msblenContextState& state, msblenContextPathProvider& paths, BlenderSyncSettings& settings, Object* instancedObject, Object* parent, SharedVector mat) { +ms::InstanceInfoPtr msblenContext::exportInstanceInfo( + msblenContextState& state, + msblenContextPathProvider& paths, + BlenderSyncSettings& settings, + Object* instancedObject, + Object* parent, + SharedVector mat) { + auto info = ms::InstanceInfo::create(); info->path = paths.get_path(instancedObject); info->parent_path = m_default_paths.get_path(parent); // parent will always be part of the scene + info->transforms = std::move(mat); m_instances_state->GetManager().add(info); + + return info; } void msblenContext::exportInstances(Object* instancedObject, Object* parent, SharedVector mat, bool fromFile) { - auto settings = m_settings; - settings.BakeTransform = false; + if (fromFile) { // Export the object from file only if its not part of the scene - auto scene_object = scene_objects.find(instancedObject->id.name); + auto scene_object = scene_objects.find(instancedObject); if (scene_object == scene_objects.end()) { - exportObject(*m_instances_state, m_default_paths, settings, instancedObject, false); + exportInstacesFromFile(instancedObject, parent, std::move(mat)); + } + else { + exportInstacesFromScene(instancedObject, parent, std::move(mat)); } - - doExportInstances(*m_instances_state, m_default_paths, settings, instancedObject, parent, std::move(mat)); } else { - settings.BakeModifiers = false; - settings.multithreaded = false; - - exportObject(*m_instances_state, m_intermediate_paths, settings, instancedObject, false); + exportInstancesFromTree(instancedObject, parent, std::move(mat)); + } +} +void msblenContext::exportInstacesFromFile(Object* instancedObject, Object* parent, SharedVector mat) +{ + auto settings = m_settings; + settings.BakeTransform = false; + + auto transform = exportObject(*m_instances_state, m_default_paths, settings, instancedObject, false); + transform.reset(); + + auto object_world_matrix = m_geometryNodeUtils.blenderToUnityWorldMatrix(getWorldMatrix(instancedObject)); + auto inverse = mu::invert(object_world_matrix); + + auto parent_world_matrix = m_geometryNodeUtils.blenderToUnityWorldMatrix(getWorldMatrix(parent)); + for (int i = 0; i < mat.size(); i++) { + mat[i] = parent_world_matrix * m_geometryNodeUtils.blenderToUnityWorldMatrix(mat[i]) * inverse; + } + + exportInstanceInfo(*m_instances_state, m_default_paths, settings, instancedObject, parent, std::move(mat)); +} +void msblenContext::exportInstacesFromScene(Object* instancedObject, Object* parent, SharedVector mat) +{ + auto settings = m_settings; + settings.BakeTransform = false; + + auto world_matrix = m_geometryNodeUtils.blenderToUnityWorldMatrix(getWorldMatrix(instancedObject)); + auto inverse = mu::invert(world_matrix); + for (int i = 0; i < mat.size(); i++) { + mat[i] = m_geometryNodeUtils.blenderToUnityWorldMatrix(mat[i]) * inverse; + } - doExportInstances(*m_instances_state, m_intermediate_paths, settings, instancedObject, parent, std::move(mat)); + exportInstanceInfo(*m_instances_state, m_default_paths, settings, instancedObject, parent, std::move(mat)); +} + +void msblenContext::exportInstancesFromTree(Object* instancedObject, Object* parent, SharedVector mat) +{ + auto settings = m_settings; + settings.BakeTransform = false; + settings.BakeModifiers = false; + settings.multithreaded = false; + + auto transform = exportObject(*m_instances_state, m_intermediate_paths, settings, instancedObject, false); + transform->reset(); + + auto world_matrix = m_geometryNodeUtils.blenderToUnityWorldMatrix(getWorldMatrix(parent)); + for (int i = 0; i < mat.size(); i++) { + mat[i] = world_matrix * m_geometryNodeUtils.blenderToUnityWorldMatrix(mat[i]); } + + exportInstanceInfo(*m_instances_state, m_intermediate_paths, settings, instancedObject, parent, std::move(mat)); } #endif diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h index 63f47f91..d622af03 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h @@ -164,7 +164,18 @@ class msblenContext { #if BLENDER_VERSION >= 300 void exportInstances(Object* object, Object* parent, SharedVector, bool fromFile); - void doExportInstances(msblenContextState& state, msblenContextPathProvider& paths, BlenderSyncSettings& settings, Object* instancedObject, Object* parent, SharedVector mat); + void exportInstacesFromFile(Object* object, Object* parent, SharedVector); + void exportInstacesFromScene(Object* object, Object* parent, SharedVector); + void exportInstancesFromTree(Object* object, Object* parent, SharedVector); + + ms::InstanceInfoPtr exportInstanceInfo( + msblenContextState& state, + msblenContextPathProvider& paths, + BlenderSyncSettings& settings, + Object* instancedObject, + Object* parent, + SharedVector mat); + #endif private: @@ -174,7 +185,7 @@ class msblenContext { msblenContextDefaultPathProvider m_default_paths; msblenContextIntermediatePathProvider m_intermediate_paths; - std::unordered_set scene_objects; + std::unordered_set scene_objects; BlenderSyncSettings m_settings; BlenderCacheSettings m_cache_settings; diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContextIntermediatePathProvider.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContextIntermediatePathProvider.cpp index 75239e36..eab50f68 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContextIntermediatePathProvider.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContextIntermediatePathProvider.cpp @@ -9,14 +9,14 @@ std::string append_id(std::string path, const Object* obj) { return path; } -std::string get_path_with_id(const Object* obj, const Bone* bone = nullptr) { +std::string get_name_with_id(const Object* obj, const Bone* bone = nullptr) { std::string path; if (bone) { path = msblenUtils::get_path(obj, bone); } else { - path = msblenUtils::get_path(obj); + path = "/" + msblenUtils::get_name(obj); } auto data = (ID*)obj->data; @@ -27,12 +27,12 @@ std::string get_path_with_id(const Object* obj, const Bone* bone = nullptr) { std::string msblenContextIntermediatePathProvider::get_path(const Object* obj) { - auto path = get_path_with_id(obj); + auto path = get_name_with_id(obj); return path; } std::string msblenContextIntermediatePathProvider::get_path(const Object* obj, const Bone* bone) { - auto path = get_path_with_id(obj, bone); + auto path = get_name_with_id(obj, bone); return path; } diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp index 435e5f8d..7e81eeee 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp @@ -46,9 +46,10 @@ namespace blender { return m_blender_to_unity_world * blenderMatrix * - m_blender_to_unity_local;; + m_blender_to_unity_local; } + void GeometryNodesUtils::foreach_instance(std::function handler) { @@ -88,10 +89,9 @@ namespace blender { auto world_matrix = float4x4(); blContext.world_matrix_get(&instance, &world_matrix); - auto unityMatrix = blenderToUnityWorldMatrix(world_matrix); auto parent = blContext.instance_parent_get(&instance); - handler(object, parent, move(unityMatrix)); + handler(object, parent, move(world_matrix)); } // Cleanup resources From a2389d45e5b4abf1d7d9bf7951181568287e219b Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Thu, 31 Mar 2022 21:32:10 +0100 Subject: [PATCH 41/67] Geometry Nodes: Simplification on local matrix calculcation --- .../Include/MeshSyncClient/msInstancesManager.h | 2 +- Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h index 540f5ceb..d8c9d8af 100644 --- a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h +++ b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h @@ -20,7 +20,7 @@ namespace ms { std::vector& getDeleted(); void clearDirtyFlags(); void add(InstanceInfoPtr instanceInfo); - void add(TransformPtr mesh); + void add(TransformPtr entity); void clear(); void touch(const std::string& path); diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index 162248d4..be5524d2 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -1718,14 +1718,12 @@ void msblenContext::exportInstacesFromFile(Object* instancedObject, Object* pare settings.BakeTransform = false; auto transform = exportObject(*m_instances_state, m_default_paths, settings, instancedObject, false); - transform.reset(); auto object_world_matrix = m_geometryNodeUtils.blenderToUnityWorldMatrix(getWorldMatrix(instancedObject)); auto inverse = mu::invert(object_world_matrix); - auto parent_world_matrix = m_geometryNodeUtils.blenderToUnityWorldMatrix(getWorldMatrix(parent)); for (int i = 0; i < mat.size(); i++) { - mat[i] = parent_world_matrix * m_geometryNodeUtils.blenderToUnityWorldMatrix(mat[i]) * inverse; + mat[i] = m_geometryNodeUtils.blenderToUnityWorldMatrix(mat[i]) * inverse; } exportInstanceInfo(*m_instances_state, m_default_paths, settings, instancedObject, parent, std::move(mat)); @@ -1754,9 +1752,8 @@ void msblenContext::exportInstancesFromTree(Object* instancedObject, Object* par auto transform = exportObject(*m_instances_state, m_intermediate_paths, settings, instancedObject, false); transform->reset(); - auto world_matrix = m_geometryNodeUtils.blenderToUnityWorldMatrix(getWorldMatrix(parent)); for (int i = 0; i < mat.size(); i++) { - mat[i] = world_matrix * m_geometryNodeUtils.blenderToUnityWorldMatrix(mat[i]); + mat[i] = m_geometryNodeUtils.blenderToUnityWorldMatrix(mat[i]); } exportInstanceInfo(*m_instances_state, m_intermediate_paths, settings, instancedObject, parent, std::move(mat)); From bc50d448b1628b581048314ead3c2c9ecc7246eb Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Thu, 31 Mar 2022 21:37:57 +0100 Subject: [PATCH 42/67] Geometry Nodes: simplification on matrix calculations --- Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index be5524d2..6a6b84af 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -1719,11 +1719,11 @@ void msblenContext::exportInstacesFromFile(Object* instancedObject, Object* pare auto transform = exportObject(*m_instances_state, m_default_paths, settings, instancedObject, false); - auto object_world_matrix = m_geometryNodeUtils.blenderToUnityWorldMatrix(getWorldMatrix(instancedObject)); + auto object_world_matrix = getWorldMatrix(instancedObject); auto inverse = mu::invert(object_world_matrix); for (int i = 0; i < mat.size(); i++) { - mat[i] = m_geometryNodeUtils.blenderToUnityWorldMatrix(mat[i]) * inverse; + mat[i] = m_geometryNodeUtils.blenderToUnityWorldMatrix( mat[i] * inverse); } exportInstanceInfo(*m_instances_state, m_default_paths, settings, instancedObject, parent, std::move(mat)); @@ -1733,10 +1733,10 @@ void msblenContext::exportInstacesFromScene(Object* instancedObject, Object* par auto settings = m_settings; settings.BakeTransform = false; - auto world_matrix = m_geometryNodeUtils.blenderToUnityWorldMatrix(getWorldMatrix(instancedObject)); + auto world_matrix = getWorldMatrix(instancedObject); auto inverse = mu::invert(world_matrix); for (int i = 0; i < mat.size(); i++) { - mat[i] = m_geometryNodeUtils.blenderToUnityWorldMatrix(mat[i]) * inverse; + mat[i] = m_geometryNodeUtils.blenderToUnityWorldMatrix(mat[i]* inverse); } exportInstanceInfo(*m_instances_state, m_default_paths, settings, instancedObject, parent, std::move(mat)); From 141fe5578f4f3ff6880db0345c86c772992c1dda Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Thu, 31 Mar 2022 22:18:05 +0100 Subject: [PATCH 43/67] Geometry Nodes: small refactor on using how the geonode utility lamdas are used --- .../MeshSyncClientBlender/msblenContext.cpp | 56 +++++++++---------- .../Src/MeshSyncClientBlender/msblenContext.h | 3 +- .../msblenGeometryNodes.cpp | 12 ++-- .../msblenGeometryNodes.h | 4 +- 4 files changed, 37 insertions(+), 38 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index 6a6b84af..0fdbc1c1 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -1390,30 +1390,14 @@ bool msblenContext::sendObjects(MeshSyncClient::ObjectScope scope, bool dirty_al #if BLENDER_VERSION >= 300 if (m_geometryNodeUtils.getInstancesDirty() || dirty_all) { - bl::BlenderPyScene scene = bl::BlenderPyScene(bl::BlenderPyContext::get().scene()); - - scene.each_objects([this](Object* obj) - { - scene_objects.insert(obj); - }); - - // Assume everything is now dirty - m_instances_state->manager.setAlwaysMarkDirty(true); - - auto instancesHandler = - std::bind(&msblenContext::exportInstances, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4); - - m_geometryNodeUtils.foreach_instanced_object(instancesHandler); - - m_geometryNodeUtils.setInstancesDirty(false); - - scene_objects.clear(); + exportInstances(); m_asyncTasksController.Wait(); m_instances_state->eraseStaleObjects(); } #endif + m_asyncTasksController.Wait(); m_entities_state->eraseStaleObjects(); @@ -1695,22 +1679,38 @@ ms::InstanceInfoPtr msblenContext::exportInstanceInfo( return info; } -void msblenContext::exportInstances(Object* instancedObject, Object* parent, SharedVector mat, bool fromFile) { +void msblenContext::exportInstances() { - if (fromFile) { + bl::BlenderPyScene scene = bl::BlenderPyScene(bl::BlenderPyContext::get().scene()); - // Export the object from file only if its not part of the scene - auto scene_object = scene_objects.find(instancedObject); + std::unordered_set scene_objects; + scene.each_objects([this, &scene_objects](Object* obj) + { + scene_objects.insert(obj); + }); + + // Assume everything is now dirty + m_instances_state->manager.setAlwaysMarkDirty(true); + + m_geometryNodeUtils.each_instanced_object([this, &scene_objects](Object* instanced, Object* parent, SharedVector matrices, bool fromFile){ + // If the instanced object is not present in the file + if (!fromFile) { + return exportInstancesFromTree(instanced, parent, std::move(matrices)); + } + + // check if the object has been already exported as part of the scene + auto scene_object = scene_objects.find(instanced); if (scene_object == scene_objects.end()) { - exportInstacesFromFile(instancedObject, parent, std::move(mat)); + return exportInstacesFromFile(instanced, parent, std::move(matrices)); } else { - exportInstacesFromScene(instancedObject, parent, std::move(mat)); + return exportInstacesFromScene(instanced, parent, std::move(matrices)); } - } - else { - exportInstancesFromTree(instancedObject, parent, std::move(mat)); - } + }); + + m_geometryNodeUtils.setInstancesDirty(false); + + scene_objects.clear(); } void msblenContext::exportInstacesFromFile(Object* instancedObject, Object* parent, SharedVector mat) { diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h index d622af03..6235615e 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h @@ -163,7 +163,7 @@ class msblenContext { void WaitAndKickAsyncExport(); #if BLENDER_VERSION >= 300 - void exportInstances(Object* object, Object* parent, SharedVector, bool fromFile); + void exportInstances(); void exportInstacesFromFile(Object* object, Object* parent, SharedVector); void exportInstacesFromScene(Object* object, Object* parent, SharedVector); void exportInstancesFromTree(Object* object, Object* parent, SharedVector); @@ -185,7 +185,6 @@ class msblenContext { msblenContextDefaultPathProvider m_default_paths; msblenContextIntermediatePathProvider m_intermediate_paths; - std::unordered_set scene_objects; BlenderSyncSettings m_settings; BlenderCacheSettings m_cache_settings; diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp index 7e81eeee..62c9e2b7 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp @@ -49,8 +49,8 @@ namespace blender { m_blender_to_unity_local; } - - void GeometryNodesUtils::foreach_instance(std::function handler) + + void GeometryNodesUtils::each_instance(std::function handler) { auto blContext = blender::BlenderPyContext::get(); @@ -91,19 +91,19 @@ namespace blender { auto parent = blContext.instance_parent_get(&instance); - handler(object, parent, move(world_matrix)); + handler(object, parent, world_matrix); } // Cleanup resources blContext.object_instances_end(&it); } - void GeometryNodesUtils::foreach_instanced_object(function, bool)> handler) { + void GeometryNodesUtils::each_instanced_object(function, bool)> handler) { m_records.clear(); m_records_by_name.clear(); - foreach_instance([&](Object* obj, Object* parent, float4x4 matrix) { + each_instance([&](Object* obj, Object* parent, float4x4 matrix) { // Critical path, must do as few things as possible auto id = (ID*)obj->data; auto& rec = m_records[id->session_uuid]; @@ -149,7 +149,7 @@ namespace blender { continue; handler(&rec.second.object_copy, rec.second.parent, std::move(rec.second.matrices), false); - rec.second.handled= true; + rec.second.handled = true; } } diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h index 0b3f95d5..793148be 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h @@ -31,7 +31,7 @@ namespace blender { /// instancedObject is the object that is being instanced. /// transform is the transform of the instance /// - void foreach_instance(std::function handler); + void each_instance(std::function handler); /// /// Invokes the handler function for each instanced object. @@ -42,7 +42,7 @@ namespace blender { /// parent is the object that has the geometry node modifier. /// transforms is the collection of transforms for the instanced object. /// - void foreach_instanced_object(std::function, bool)> handler); + void each_instanced_object(std::function, bool)> handler); void setInstancesDirty(bool dirty); bool getInstancesDirty(); From 9ff82ce424721dd819d0aebad61b50f7160507c6 Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Fri, 1 Apr 2022 12:42:45 +0100 Subject: [PATCH 44/67] Geometry Nodes: moved RNA interfacing to appropriate classes --- .../BlenderPyObjects/BlenderPyContext.cpp | 78 -------- .../BlenderPyObjects/BlenderPyContext.h | 12 -- .../BlenderPyObjects/BlenderPyDepsgraph.cpp | 39 ++++ .../BlenderPyObjects/BlenderPyDepsgraph.h | 21 +++ .../BlenderPyDepsgraphObjectInstance.cpp | 53 ++++++ .../BlenderPyDepsgraphObjectInstance.h | 22 +++ .../MeshSyncClientBlender/msblenBinder.cpp | 27 +-- .../MeshSyncClientBlender/msblenContext.cpp | 12 +- .../msblenContextState.h | 3 - .../msblenGeometryNodes.cpp | 172 +++++++++--------- .../msblenGeometryNodes.h | 63 +++---- 11 files changed, 267 insertions(+), 235 deletions(-) create mode 100644 Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyDepsgraph.cpp create mode 100644 Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyDepsgraph.h create mode 100644 Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyDepsgraphObjectInstance.cpp create mode 100644 Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyDepsgraphObjectInstance.h diff --git a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp index 2c7c8afb..09da62ec 100644 --- a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp @@ -11,14 +11,6 @@ PropertyRNA* BlenderPyContext_blend_data = nullptr; PropertyRNA* BlenderPyContext_scene = nullptr; FunctionRNA* BlenderPyContext_evaluated_depsgraph_get = nullptr; FunctionRNA* BlenderPyContext_depsgraph_update = nullptr; -PropertyRNA* BlenderPyContext_depsgraph_object_instances = nullptr; -PropertyRNA* BlenderPyContext_depsgraph_instance_object = nullptr; -PropertyRNA* BlenderPyContext_depsgraph_is_instance = nullptr; -PropertyRNA* BlenderPyContext_depsgraph_world_matrix = nullptr; -PropertyRNA* BlenderPyContext_depsgraph_parent = nullptr; -PropertyRNA* BlenderPyContext_depsgraph_object = nullptr; - - BlenderPyContext BlenderPyContext::get() { @@ -43,74 +35,4 @@ void BlenderPyContext::UpdateDepsgraph(Depsgraph* depsgraph) { call(g_context, depsgraph, BlenderPyContext_depsgraph_update); } -void BlenderPyContext::object_instances_begin(CollectionPropertyIterator* it, Depsgraph* depsgraph) { - - PointerRNA rna; - rna.data = depsgraph; - - CollectionPropertyRNA* cprop = (CollectionPropertyRNA*)BlenderPyContext_depsgraph_object_instances; - - cprop->begin(it, &rna); -} - -void BlenderPyContext::object_instances_end(CollectionPropertyIterator* it) { - - CollectionPropertyRNA* cprop = (CollectionPropertyRNA*)BlenderPyContext_depsgraph_object_instances; - cprop->end(it); -} - -void BlenderPyContext::object_instances_next(CollectionPropertyIterator * it){ - CollectionPropertyRNA* cprop = (CollectionPropertyRNA*)BlenderPyContext_depsgraph_object_instances; - cprop->next(it); -} - -PointerRNA BlenderPyContext::object_instances_get(CollectionPropertyIterator* it) { - - auto collectionProp = (CollectionPropertyRNA*)BlenderPyContext_depsgraph_object_instances; - return collectionProp->get(it); - -} - -Object* BlenderPyContext::instance_object_get(PointerRNA instance) { - auto objectInstanceProp = (PointerPropertyRNA*)BlenderPyContext_depsgraph_instance_object; - auto object = objectInstanceProp->get(&instance); - - if (object.type == nullptr || object.data == nullptr) { - return nullptr; - } - - return (Object*)object.data; -} - - - -bool BlenderPyContext::object_instances_is_instance(PointerRNA object) { - auto booleanProp = (BoolPropertyRNA*)BlenderPyContext_depsgraph_is_instance; - return booleanProp->get(&object); -} - -void BlenderPyContext::world_matrix_get(PointerRNA* instance, mu::float4x4* result) -{ - auto floatProp = (FloatPropertyRNA*)BlenderPyContext_depsgraph_world_matrix; - floatProp->getarray(instance, &(result->m[0][0])); -} - -Object* BlenderPyContext::instance_parent_get(PointerRNA* instance) { - auto pointerProp = (PointerPropertyRNA*)BlenderPyContext_depsgraph_parent; - auto parent = pointerProp->get(instance); - - return (Object*)parent.data; -} - -Object* BlenderPyContext::object_get(PointerRNA instance) { - auto objectInstanceProp = (PointerPropertyRNA*)BlenderPyContext_depsgraph_object; - auto object = objectInstanceProp->get(&instance); - - if (object.type == nullptr || object.data == nullptr) { - return nullptr; - } - - return (Object*)object.data; -} - } // namespace blender diff --git a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.h b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.h index a4623beb..0880c723 100644 --- a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.h +++ b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.h @@ -18,18 +18,6 @@ namespace blender Depsgraph* evaluated_depsgraph_get(); static void UpdateDepsgraph(Depsgraph* depsgraph); - - void object_instances_begin(CollectionPropertyIterator* it, Depsgraph* depsgrah); - void object_instances_end(CollectionPropertyIterator* it); - void object_instances_next(CollectionPropertyIterator* it); - PointerRNA object_instances_get(CollectionPropertyIterator* it); - - - Object* instance_object_get(PointerRNA instance); - bool object_instances_is_instance(PointerRNA instance); - void world_matrix_get(PointerRNA* instance, mu::float4x4* world_matrix); - Object* instance_parent_get(PointerRNA* instance); - Object* object_get(PointerRNA instance); }; } // namespace blender diff --git a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyDepsgraph.cpp b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyDepsgraph.cpp new file mode 100644 index 00000000..7389a152 --- /dev/null +++ b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyDepsgraph.cpp @@ -0,0 +1,39 @@ +#include " +#include + +namespace blender { + + PropertyRNA* BlenderPyDepsgraph_object_instances = nullptr; + + BlenderPyDepsgraph::BlenderPyDepsgraph(Depsgraph* depsgraph) + { + m_depsgraph = depsgraph; + } + + void BlenderPyDepsgraph::object_instances_begin(CollectionPropertyIterator* it) { + + PointerRNA rna; + rna.data = m_depsgraph; + + CollectionPropertyRNA* cprop = (CollectionPropertyRNA*)BlenderPyDepsgraph_object_instances; + + cprop->begin(it, &rna); + } + + void BlenderPyDepsgraph::object_instances_end(CollectionPropertyIterator* it) { + + CollectionPropertyRNA* cprop = (CollectionPropertyRNA*)BlenderPyDepsgraph_object_instances; + cprop->end(it); + } + + void BlenderPyDepsgraph::object_instances_next(CollectionPropertyIterator* it) { + CollectionPropertyRNA* cprop = (CollectionPropertyRNA*)BlenderPyDepsgraph_object_instances; + cprop->next(it); + } + + PointerRNA BlenderPyDepsgraph::object_instances_get(CollectionPropertyIterator* it) { + + auto collectionProp = (CollectionPropertyRNA*)BlenderPyDepsgraph_object_instances; + return collectionProp->get(it); + } +} \ No newline at end of file diff --git a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyDepsgraph.h b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyDepsgraph.h new file mode 100644 index 00000000..404c59be --- /dev/null +++ b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyDepsgraph.h @@ -0,0 +1,21 @@ +#pragma once +#include //bContext +#include "MeshUtils/muMath.h" + +namespace blender +{ + + class BlenderPyDepsgraph + { + public: + BlenderPyDepsgraph(Depsgraph* depsgraph); + void object_instances_begin(CollectionPropertyIterator* it); + void object_instances_end(CollectionPropertyIterator* it); + void object_instances_next(CollectionPropertyIterator* it); + PointerRNA object_instances_get(CollectionPropertyIterator* it); + + private: + Depsgraph* m_depsgraph; + }; + +} \ No newline at end of file diff --git a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyDepsgraphObjectInstance.cpp b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyDepsgraphObjectInstance.cpp new file mode 100644 index 00000000..f38abd86 --- /dev/null +++ b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyDepsgraphObjectInstance.cpp @@ -0,0 +1,53 @@ +#include "pch.h" +#include "BlenderPyCommon.h" +#include "BlenderPyObjects/BlenderPyDepsgraphObjectInstance.h" + +namespace blender { + + PropertyRNA* BlenderPyDepsgraphObjectInstance_instance_object = nullptr; + PropertyRNA* BlenderPyDepsgraphObjectInstance_is_instance = nullptr; + PropertyRNA* BlenderPyDepsgraphObjectInstance_world_matrix = nullptr; + PropertyRNA* BlenderPyDepsgraphObjectInstance_parent = nullptr; + PropertyRNA* BlenderPyDepsgraphObjectInstance_object = nullptr; + + Object* BlenderPyDepsgraphInstance::instance_object() { + auto objectInstanceProp = (PointerPropertyRNA*)BlenderPyDepsgraphObjectInstance_instance_object; + auto object = objectInstanceProp->get(&m_instance); + + if (object.type == nullptr || object.data == nullptr) { + return nullptr; + } + + return (Object*)object.data; + } + + bool BlenderPyDepsgraphInstance::is_instance() { + auto booleanProp = (BoolPropertyRNA*)BlenderPyDepsgraphObjectInstance_is_instance; + return booleanProp->get(&m_instance); + } + + void BlenderPyDepsgraphInstance::world_matrix(mu::float4x4* result) + { + auto floatProp = (FloatPropertyRNA*)BlenderPyDepsgraphObjectInstance_world_matrix; + floatProp->getarray(&m_instance, &(result->m[0][0])); + } + + Object* BlenderPyDepsgraphInstance::parent() { + auto pointerProp = (PointerPropertyRNA*)BlenderPyDepsgraphObjectInstance_parent; + auto parent = pointerProp->get(&m_instance); + + return (Object*)parent.data; + } + + Object* BlenderPyDepsgraphInstance::object() { + auto objectInstanceProp = (PointerPropertyRNA*)BlenderPyDepsgraphObjectInstance_object; + auto object = objectInstanceProp->get(&m_instance); + + if (object.type == nullptr || object.data == nullptr) { + return nullptr; + } + + return (Object*)object.data; + } + +} // namespace blender diff --git a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyDepsgraphObjectInstance.h b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyDepsgraphObjectInstance.h new file mode 100644 index 00000000..4a58b272 --- /dev/null +++ b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyDepsgraphObjectInstance.h @@ -0,0 +1,22 @@ +#pragma once + +#include //bContext +#include "MeshUtils/muMath.h" + +namespace blender +{ + class BlenderPyDepsgraphInstance + { + public: + BlenderPyDepsgraphInstance(PointerRNA& instance) : m_instance(instance) {} + + Object* instance_object(); + bool is_instance(); + void world_matrix(mu::float4x4* world_matrix); + Object* parent(); + Object* object(); + private: + PointerRNA& m_instance; + }; + +} // namespace blender diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp index 99735b7e..a6fa1e4e 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp @@ -5,6 +5,8 @@ #include "MeshUtils/muLog.h" +#include "BlenderPyObjects/BlenderPyDepsgraph.h" +#include "BlenderPyObjects/BlenderPyDepsgraphObjectInstance.h" #include "BlenderPyObjects/BlenderPyContext.h" #include "BlenderPyObjects/BlenderPyScene.h" #include "BlenderPyObjects/BlenderPyCommon.h" //call, etc @@ -63,14 +65,13 @@ extern PropertyRNA* BlenderPyContext_scene; extern FunctionRNA* BlenderPyContext_evaluated_depsgraph_get; extern FunctionRNA* BlenderPyContext_depsgraph_update; -extern PropertyRNA* BlenderPyContext_depsgraph_object_instances; +extern PropertyRNA* BlenderPyDepsgraphObjectInstance_instance_object; +extern PropertyRNA* BlenderPyDepsgraphObjectInstance_is_instance; +extern PropertyRNA* BlenderPyDepsgraphObjectInstance_world_matrix; +extern PropertyRNA* BlenderPyDepsgraphObjectInstance_parent; +extern PropertyRNA* BlenderPyDepsgraphObjectInstance_object; -extern PropertyRNA* BlenderPyContext_depsgraph_instance_object; -extern PropertyRNA* BlenderPyContext_depsgraph_is_instance; -extern PropertyRNA* BlenderPyContext_depsgraph_world_matrix; -extern PropertyRNA* BlenderPyContext_depsgraph_parent; - -extern PropertyRNA* BlenderPyContext_depsgraph_object; +extern PropertyRNA* BlenderPyDepsgraph_object_instances; extern PropertyRNA* BlenderPyNodeTree_inputs; extern PropertyRNA* BlenderPyNodeTree_nodes; @@ -207,7 +208,7 @@ void setup(py::object bpy_context) else if (match_type("Depsgraph")) { each_prop{ if (match_prop("object_instances")) { - BlenderPyContext_depsgraph_object_instances = prop; + BlenderPyDepsgraph_object_instances = prop; } } each_func{ @@ -219,20 +220,20 @@ void setup(py::object bpy_context) else if (match_type("DepsgraphObjectInstance")) { each_prop{ if (match_prop("instance_object")) { - BlenderPyContext_depsgraph_instance_object = prop; + BlenderPyDepsgraphObjectInstance_instance_object = prop; } if (match_prop("is_instance")) { - BlenderPyContext_depsgraph_is_instance = prop; + BlenderPyDepsgraphObjectInstance_is_instance = prop; } if (match_prop("matrix_world")) { - BlenderPyContext_depsgraph_world_matrix = prop; + BlenderPyDepsgraphObjectInstance_world_matrix = prop; } if (match_prop("parent")) { - BlenderPyContext_depsgraph_parent = prop; + BlenderPyDepsgraphObjectInstance_parent = prop; } if (match_prop("object")) { - BlenderPyContext_depsgraph_object = prop; + BlenderPyDepsgraphObjectInstance_object = prop; } } } diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index 0fdbc1c1..5568d7d6 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -1612,14 +1612,14 @@ void msblenContext::WaitAndKickAsyncExport() t.materials = m_material_manager.getDirtyMaterials(); t.transforms = m_entity_manager.getDirtyTransforms(); t.geometries = m_entity_manager.getDirtyGeometries(); - t.instanceInfos = m_instances_state->GetManager().getDirtyInstances(); - t.instanceMeshes = m_instances_state->GetManager().getDirtyMeshes(); + t.instanceInfos = m_instances_manager.getDirtyInstances(); + t.instanceMeshes = m_instances_manager.getDirtyMeshes(); t.animations = m_animations; t.deleted_materials = m_material_manager.getDeleted(); t.deleted_entities = m_entity_manager.getDeleted(); - t.deleted_instances = m_instances_state->GetManager().getDeleted(); + t.deleted_instances = m_instances_manager.getDeleted(); if (scale_factor != 1.0f) { ms::ScaleConverter cv(scale_factor); @@ -1635,9 +1635,7 @@ void msblenContext::WaitAndKickAsyncExport() m_material_manager.clearDirtyFlags(); m_entity_manager.clearDirtyFlags(); m_animations.clear(); - m_instances_state->GetManager().clearDirtyFlags(); - - m_geometryNodeUtils.clear(); + m_instances_manager.clearDirtyFlags(); }; exporter->kick(); @@ -1674,7 +1672,7 @@ ms::InstanceInfoPtr msblenContext::exportInstanceInfo( info->transforms = std::move(mat); - m_instances_state->GetManager().add(info); + m_instances_manager.add(info); return info; } diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContextState.h b/Plugins~/Src/MeshSyncClientBlender/msblenContextState.h index cef454ab..37509df2 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContextState.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContextState.h @@ -37,9 +37,6 @@ class msblenContextState { ms::TransformManager& manager; - template - T& GetManager() { return (T&)manager; } - void msblenContextState::eraseObjectRecords(); void msblenContextState::eraseStaleObjects(); void clear(); diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp index 62c9e2b7..aadd5715 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp @@ -1,8 +1,9 @@ #include "msblenGeometryNodes.h" #include #include +#include +#include #include -#include "BlenderPyObjects/BlenderPyNodeTree.h" #include "BlenderPyObjects/BlenderPyScene.h" #include #include @@ -31,8 +32,6 @@ namespace blender { to_mat4x4(rotation) * to_mat4x4(rotation180) * scale44(scale_z); - - } #if BLENDER_VERSION >= 300 @@ -49,123 +48,120 @@ namespace blender { m_blender_to_unity_local; } - - void GeometryNodesUtils::each_instance(std::function handler) + void GeometryNodesUtils::setInstancesDirty(bool dirty) + { + m_instances_dirty = dirty; + } + bool GeometryNodesUtils::getInstancesDirty() { + return m_instances_dirty; + } + + void GeometryNodesUtils::each_instanced_object(std::function, bool)> handler) { + + std::unordered_map m_records; + std::unordered_map m_records_by_name; + + each_instance([&](Object* obj, Object* parent, float4x4 matrix) + { + // Critical path, must do as few things as possible + auto id = (ID*)obj->data; + auto& rec = m_records[id->session_uuid]; + if (!rec.updated) + { + rec.parent = parent; + rec.object_copy = *obj; + rec.updated = true; + + m_records_by_name[obj->id.name] = &rec; + } + + rec.matrices.push_back(matrix); + }); + + // Look for objects in the file + auto ctx = blender::BlenderPyContext::get(); + auto objects = ctx.data()->objects; + LISTBASE_FOREACH(Object*, obj, &objects) { - auto blContext = blender::BlenderPyContext::get(); + if (obj->data == nullptr) + continue; + // Check if there is record with the same object name + auto rec = m_records_by_name.find(obj->id.name); + if (rec == m_records_by_name.end()) + continue; - // BlenderPyContext is an interface between depsgraph operations and anything that interacts with it - auto depsgraph = blContext.evaluated_depsgraph_get(); + // Check if the data names also match + auto recDataId = (ID*)rec->second->object_copy.data; + auto sceneDataId = (ID*)obj->data; + + if (strcmp(sceneDataId->name + 2, recDataId->name + 2) != 0) + continue; + + handler(obj, rec->second->parent, std::move(rec->second->matrices), true); + rec->second->handled = true; + + } + + // Export objects that are not in the file + for (auto& rec : m_records) { + if (rec.second.handled) + continue; + + + handler(&rec.second.object_copy, rec.second.parent, std::move(rec.second.matrices), false); + rec.second.handled = true; + } + + } + + void GeometryNodesUtils::each_instance(std::function handler) + { + auto blender_ctx = BlenderPyContext::get(); + auto depsgraph_ctx = blender_ctx.evaluated_depsgraph_get(); + + auto depsgraph = BlenderPyDepsgraph(depsgraph_ctx); + // Iterate over the object instances collection of depsgraph CollectionPropertyIterator it; - blContext.object_instances_begin(&it, depsgraph); + depsgraph.object_instances_begin(&it); + + for (; it.valid; depsgraph.object_instances_next(&it)) { - for (; it.valid; blContext.object_instances_next(&it)) { // Get the instance as a Pointer RNA. - auto instance = blContext.object_instances_get(&it); + auto instance_ctx = depsgraph.object_instances_get(&it); + auto instance = BlenderPyDepsgraphInstance(instance_ctx); // Get the object that the instance refers to - auto instance_object = blContext.instance_object_get(instance); - + auto instance_object = instance.instance_object(); // If the object is null, skip if (instance_object == nullptr) continue; // if the instance is not an instance, skip - if (!blContext.object_instances_is_instance(instance)) + if (!instance.is_instance()) continue; - auto object = blContext.object_get(instance); + auto object = instance.object(); if (object->type != OB_MESH) { continue; } auto world_matrix = float4x4(); - blContext.world_matrix_get(&instance, &world_matrix); + instance.world_matrix(&world_matrix); - auto parent = blContext.instance_parent_get(&instance); + auto parent = instance.parent(); handler(object, parent, world_matrix); } // Cleanup resources - blContext.object_instances_end(&it); - } - - void GeometryNodesUtils::each_instanced_object(function, bool)> handler) { - - m_records.clear(); - m_records_by_name.clear(); - - each_instance([&](Object* obj, Object* parent, float4x4 matrix) { - // Critical path, must do as few things as possible - auto id = (ID*)obj->data; - auto& rec = m_records[id->session_uuid]; - - if (!rec.updated) { - rec.parent = parent; - rec.object_copy = *obj; - rec.updated = true; - - m_records_by_name[obj->id.name] = &rec; - } - - rec.matrices.push_back(matrix); - }); - - // Look for objects in the file - auto ctx = blender::BlenderPyContext::get(); - auto objects = ctx.data()->objects; - LISTBASE_FOREACH(Object*, obj, &objects){ - - if (obj->data == nullptr) - continue; - - // Check if there is record with the same object name - auto rec = m_records_by_name.find(obj->id.name); - if (rec == m_records_by_name.end()) - continue; - - // Check if the data names also match - auto recDataId = (ID*)rec->second->object_copy.data; - auto sceneDataId = (ID*)obj->data; - - if (strcmp(sceneDataId->name + 2, recDataId->name + 2) != 0) - continue; - - handler(obj, rec->second->parent, std::move(rec->second->matrices), true); - rec->second->handled = true; - } - - // Export objects that are not in the file - for(auto& rec : m_records) { - if (rec.second.handled) - continue; - - handler(&rec.second.object_copy, rec.second.parent, std::move(rec.second.matrices), false); - rec.second.handled = true; - } - } - - void GeometryNodesUtils::setInstancesDirty(bool dirty) - { - m_instances_dirty = dirty; - } - bool GeometryNodesUtils::getInstancesDirty() - { - return m_instances_dirty; - } - - void blender::GeometryNodesUtils::clear() - { - m_records.clear(); - m_records_by_name.clear(); + depsgraph.object_instances_end(&it); } #endif } diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h index 793148be..5d9e1a7c 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h @@ -18,53 +18,48 @@ namespace blender { GeometryNodesUtils(); + /// + /// Invokes the handler function for each instance. + /// + /// + /// The handling function: + /// instancedObject is the object that is being instanced. + /// transform is the transform of the instance + /// + void each_instance(std::function handler); + + /// + /// Invokes the handler function for each instanced object. + /// + /// + /// The handling function: + /// instancedObject is the object that is being instanced. + /// parent is the object that has the geometry node modifier. + /// transforms is the collection of transforms for the instanced object. + /// + void each_instanced_object(std::function, bool)> handler); + /// /// /// Converts the world matrix from blender to Unity coordinate system /// /// mu::float4x4 blenderToUnityWorldMatrix(mu::float4x4& blenderMatrix); - /// - /// Invokes the handler function for each instance. - /// - /// - /// The handling function: - /// instancedObject is the object that is being instanced. - /// transform is the transform of the instance - /// - void each_instance(std::function handler); - - /// - /// Invokes the handler function for each instanced object. - /// - /// - /// The handling function: - /// instancedObject is the object that is being instanced. - /// parent is the object that has the geometry node modifier. - /// transforms is the collection of transforms for the instanced object. - /// - void each_instanced_object(std::function, bool)> handler); - void setInstancesDirty(bool dirty); bool getInstancesDirty(); - void clear(); - private: bool m_instances_dirty; mu::float4x4 m_blender_to_unity_local; mu::float4x4 m_blender_to_unity_world; - - struct Record { - Object object_copy; - Object* parent = nullptr; - SharedVector matrices; - bool handled = false; - bool updated = false; - }; - - std::unordered_map m_records; - std::unordered_map m_records_by_name; + + struct Record { + Object object_copy; + Object* parent = nullptr; + SharedVector matrices; + bool handled = false; + bool updated = false; + }; }; From dd382e7670ea76b94946787b0810439ba7bea05f Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Fri, 1 Apr 2022 13:30:11 +0100 Subject: [PATCH 45/67] Visibility: fix for collection visibility --- .../BlenderPyObjects/BlenderPyContext.cpp | 6 ++++ .../BlenderPyObjects/BlenderPyContext.h | 1 + .../MeshSyncClientBlender/msblenBinder.cpp | 2 ++ .../MeshSyncClientBlender/msblenContext.cpp | 9 +++--- .../Src/MeshSyncClientBlender/msblenUtils.cpp | 32 +++++++++++++++++++ .../Src/MeshSyncClientBlender/msblenUtils.h | 4 +++ 6 files changed, 49 insertions(+), 5 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp index 09da62ec..6ac08055 100644 --- a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp @@ -11,6 +11,7 @@ PropertyRNA* BlenderPyContext_blend_data = nullptr; PropertyRNA* BlenderPyContext_scene = nullptr; FunctionRNA* BlenderPyContext_evaluated_depsgraph_get = nullptr; FunctionRNA* BlenderPyContext_depsgraph_update = nullptr; +PropertyRNA* BlenderPyContext_viewlayer = nullptr; BlenderPyContext BlenderPyContext::get() { @@ -30,6 +31,11 @@ Depsgraph* BlenderPyContext::evaluated_depsgraph_get() return call(g_context, m_ptr, BlenderPyContext_evaluated_depsgraph_get); } +ViewLayer* BlenderPyContext::viewLayer() +{ + return (ViewLayer*)get_pointer(m_ptr, BlenderPyContext_viewlayer); +} + void BlenderPyContext::UpdateDepsgraph(Depsgraph* depsgraph) { call(g_context, depsgraph, BlenderPyContext_depsgraph_update); diff --git a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.h b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.h index 0880c723..ae26adef 100644 --- a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.h +++ b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.h @@ -16,6 +16,7 @@ namespace blender Main* data(); Scene* scene(); Depsgraph* evaluated_depsgraph_get(); + ViewLayer* viewLayer(); static void UpdateDepsgraph(Depsgraph* depsgraph); }; diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp index a6fa1e4e..ad5a13f2 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp @@ -64,6 +64,7 @@ extern PropertyRNA* BlenderPyContext_blend_data; extern PropertyRNA* BlenderPyContext_scene; extern FunctionRNA* BlenderPyContext_evaluated_depsgraph_get; extern FunctionRNA* BlenderPyContext_depsgraph_update; +extern PropertyRNA* BlenderPyContext_viewlayer; extern PropertyRNA* BlenderPyDepsgraphObjectInstance_instance_object; extern PropertyRNA* BlenderPyDepsgraphObjectInstance_is_instance; @@ -200,6 +201,7 @@ void setup(py::object bpy_context) each_prop{ if (match_prop("blend_data")) BlenderPyContext_blend_data = prop; if (match_prop("scene")) BlenderPyContext_scene = prop; + if (match_prop("view_layer")) BlenderPyContext_viewlayer = prop; } each_func{ if (match_func("evaluated_depsgraph_get")) BlenderPyContext_evaluated_depsgraph_get = func; diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index 5568d7d6..b13af20e 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -310,7 +310,7 @@ void msblenContext::extractTransformData(BlenderSyncSettings& settings, const Ob mu::float3& t, mu::quatf& r, mu::float3& s, ms::VisibilityFlags& vis, mu::float4x4 *dst_world, mu::float4x4 *dst_local) { - vis = { true, visible_in_render(obj), visible_in_viewport(obj) }; + vis = { visible_in_collection(obj), visible_in_render(obj), visible_in_viewport(obj) }; const mu::float4x4 local = getLocalMatrix(obj); const mu::float4x4 world = getWorldMatrix(obj); @@ -559,8 +559,7 @@ ms::TransformPtr msblenContext::exportReference(msblenContextState& state, msble auto assign_base_params = [&]() { extractTransformData(settings, src, *dst); dst->path = path; - // todo: - dst->visibility = {}; + dst->visibility = {visible_in_collection(src), visible_in_render(ctx.group_host), visible_in_viewport(ctx.group_host)}; dst->world_matrix *= ctx.dst->world_matrix; }; @@ -627,7 +626,7 @@ ms::TransformPtr msblenContext::exportDupliGroup(msblenContextState& state, msbl std::shared_ptr dst = ms::Transform::create(); dst->path = path; - dst->visibility = { true, visible_in_render(ctx.group_host), visible_in_viewport(ctx.group_host) }; + dst->visibility = { visible_in_collection(src), visible_in_render(ctx.group_host), visible_in_viewport(ctx.group_host) }; const mu::tvec3 offset_pos = -get_instance_offset(group); dst->position = settings.BakeTransform ? mu::float3::zero() : offset_pos; @@ -642,7 +641,7 @@ ms::TransformPtr msblenContext::exportDupliGroup(msblenContextState& state, msbl auto obj = go->ob; if (auto t = exportObject(state, paths, settings, obj, true, false)) { const bool non_lib = obj->id.lib == nullptr; - t->visibility = { true, non_lib, non_lib }; + t->visibility = { visible_in_collection(obj), non_lib, non_lib }; } exportReference(state, paths, settings, obj, ctx2); } diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenUtils.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenUtils.cpp index e95d6a16..0617f82f 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenUtils.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenUtils.cpp @@ -73,6 +73,38 @@ namespace msblenUtils { return !bl::BObject(obj).hide_viewport(); } + bool visible_in_collection(LayerCollection* layerCollection, const Object* obj) { + // Check if the object is in the layer collection, if it is, check if the layer is excluded: + for (auto collectionObject : blender::list_range((CollectionObject*)layerCollection->collection->gobject.first)) { + if (collectionObject->ob == obj) { + if (!(layerCollection->flag & LAYER_COLLECTION_EXCLUDE)) { + return true; + } + } + } + + // Check child layer collections: + for (auto childCollection : blender::list_range((LayerCollection*)layerCollection->layer_collections.first)) { + if (visible_in_collection(childCollection, obj)) { + return true; + } + } + + return false; + } + + bool visible_in_collection(const Object* obj) { + auto viewLayer = bl::BlenderPyContext::get().viewLayer(); + + for (auto layerCollection : blender::list_range((LayerCollection*)viewLayer->layer_collections.first)) { + if (visible_in_collection(layerCollection, obj)) { + return true; + } + } + + return false; + } + const ModifierData* FindModifier(const Object* obj, ModifierType type) { for (auto* it = (ModifierData*)obj->modifiers.first; it != nullptr; it = it->next) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenUtils.h b/Plugins~/Src/MeshSyncClientBlender/msblenUtils.h index 9fbd0b9e..2645b847 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenUtils.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenUtils.h @@ -12,6 +12,10 @@ namespace msblenUtils { std::string get_path(const Object* arm, const Bone* obj); bool visible_in_render(const Object* obj); bool visible_in_viewport(const Object* obj); + + bool visible_in_collection(LayerCollection* layerCollection, const Object* obj); + bool visible_in_collection(const Object* obj); + const ModifierData* FindModifier(const Object* obj, ModifierType type); Bone* find_bone_recursive(Bone* bone, const char* name); Bone* find_bone(Object* obj, const char* name); From a163c78295b0e7724a0b69444bdc64e500672dac Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Mon, 4 Apr 2022 15:08:32 +0100 Subject: [PATCH 46/67] Geometry Nodes: use parallel for when converting matrices --- .../MeshSyncClientBlender/msblenContext.cpp | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index b13af20e..9900aa26 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -1718,9 +1718,14 @@ void msblenContext::exportInstacesFromFile(Object* instancedObject, Object* pare auto object_world_matrix = getWorldMatrix(instancedObject); auto inverse = mu::invert(object_world_matrix); +; + mu::parallel_for(0, mat.size(), 10, [this, &mat, &inverse](int i) + { + mat[i] = m_geometryNodeUtils.blenderToUnityWorldMatrix(mat[i] * inverse); + }); for (int i = 0; i < mat.size(); i++) { - mat[i] = m_geometryNodeUtils.blenderToUnityWorldMatrix( mat[i] * inverse); + } exportInstanceInfo(*m_instances_state, m_default_paths, settings, instancedObject, parent, std::move(mat)); @@ -1732,9 +1737,11 @@ void msblenContext::exportInstacesFromScene(Object* instancedObject, Object* par auto world_matrix = getWorldMatrix(instancedObject); auto inverse = mu::invert(world_matrix); - for (int i = 0; i < mat.size(); i++) { - mat[i] = m_geometryNodeUtils.blenderToUnityWorldMatrix(mat[i]* inverse); - } + + mu::parallel_for(0, mat.size(), 10, [this, &mat, &inverse](int i) + { + mat[i] = m_geometryNodeUtils.blenderToUnityWorldMatrix(mat[i] * inverse); + }); exportInstanceInfo(*m_instances_state, m_default_paths, settings, instancedObject, parent, std::move(mat)); } @@ -1749,9 +1756,10 @@ void msblenContext::exportInstancesFromTree(Object* instancedObject, Object* par auto transform = exportObject(*m_instances_state, m_intermediate_paths, settings, instancedObject, false); transform->reset(); - for (int i = 0; i < mat.size(); i++) { - mat[i] = m_geometryNodeUtils.blenderToUnityWorldMatrix(mat[i]); - } + mu::parallel_for(0, mat.size(), 10, [this, &mat](int i) + { + mat[i] = m_geometryNodeUtils.blenderToUnityWorldMatrix(mat[i]); + }); exportInstanceInfo(*m_instances_state, m_intermediate_paths, settings, instancedObject, parent, std::move(mat)); } From 30693c0129c82df60100367767d73acb50d565f5 Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Mon, 4 Apr 2022 20:01:38 +0100 Subject: [PATCH 47/67] Geometry Nodes: removed dead code --- Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index 9900aa26..e5d0236d 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -1724,10 +1724,6 @@ void msblenContext::exportInstacesFromFile(Object* instancedObject, Object* pare mat[i] = m_geometryNodeUtils.blenderToUnityWorldMatrix(mat[i] * inverse); }); - for (int i = 0; i < mat.size(); i++) { - - } - exportInstanceInfo(*m_instances_state, m_default_paths, settings, instancedObject, parent, std::move(mat)); } void msblenContext::exportInstacesFromScene(Object* instancedObject, Object* parent, SharedVector mat) From 75fc52362ba6675e942a21a6489bb65d373d81bf Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Mon, 4 Apr 2022 20:29:30 +0100 Subject: [PATCH 48/67] Geometry Nodes: Temporary fix for skinned mesh renderer glitch --- Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index e5d0236d..478f3a6b 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -1714,6 +1714,10 @@ void msblenContext::exportInstacesFromFile(Object* instancedObject, Object* pare auto settings = m_settings; settings.BakeTransform = false; + // There is some race condition that is causing rendering glitches on Unity. Seems related to UVs or triangle indices. + // Not using threads seems to fix it but should be investigated more. + settings.multithreaded = false; + auto transform = exportObject(*m_instances_state, m_default_paths, settings, instancedObject, false); auto object_world_matrix = getWorldMatrix(instancedObject); @@ -1728,9 +1732,6 @@ void msblenContext::exportInstacesFromFile(Object* instancedObject, Object* pare } void msblenContext::exportInstacesFromScene(Object* instancedObject, Object* parent, SharedVector mat) { - auto settings = m_settings; - settings.BakeTransform = false; - auto world_matrix = getWorldMatrix(instancedObject); auto inverse = mu::invert(world_matrix); From 90910a57c8e5d18b373406431d93117c012025bf Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Tue, 5 Apr 2022 11:26:27 +0100 Subject: [PATCH 49/67] Geometry Nodes: removed dead var --- Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp | 9 ++++----- Plugins~/Src/MeshSyncClientBlender/msblenContext.h | 1 - 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index 478f3a6b..2e30926c 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -1659,8 +1659,7 @@ void msblenContext::onDepsgraphUpdatedPost(Depsgraph* graph) ms::InstanceInfoPtr msblenContext::exportInstanceInfo( msblenContextState& state, - msblenContextPathProvider& paths, - BlenderSyncSettings& settings, + msblenContextPathProvider& paths, Object* instancedObject, Object* parent, SharedVector mat) { @@ -1728,7 +1727,7 @@ void msblenContext::exportInstacesFromFile(Object* instancedObject, Object* pare mat[i] = m_geometryNodeUtils.blenderToUnityWorldMatrix(mat[i] * inverse); }); - exportInstanceInfo(*m_instances_state, m_default_paths, settings, instancedObject, parent, std::move(mat)); + exportInstanceInfo(*m_instances_state, m_default_paths, instancedObject, parent, std::move(mat)); } void msblenContext::exportInstacesFromScene(Object* instancedObject, Object* parent, SharedVector mat) { @@ -1740,7 +1739,7 @@ void msblenContext::exportInstacesFromScene(Object* instancedObject, Object* par mat[i] = m_geometryNodeUtils.blenderToUnityWorldMatrix(mat[i] * inverse); }); - exportInstanceInfo(*m_instances_state, m_default_paths, settings, instancedObject, parent, std::move(mat)); + exportInstanceInfo(*m_instances_state, m_default_paths, instancedObject, parent, std::move(mat)); } void msblenContext::exportInstancesFromTree(Object* instancedObject, Object* parent, SharedVector mat) @@ -1758,7 +1757,7 @@ void msblenContext::exportInstancesFromTree(Object* instancedObject, Object* par mat[i] = m_geometryNodeUtils.blenderToUnityWorldMatrix(mat[i]); }); - exportInstanceInfo(*m_instances_state, m_intermediate_paths, settings, instancedObject, parent, std::move(mat)); + exportInstanceInfo(*m_instances_state, m_intermediate_paths, instancedObject, parent, std::move(mat)); } #endif diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h index 6235615e..3756953a 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h @@ -171,7 +171,6 @@ class msblenContext { ms::InstanceInfoPtr exportInstanceInfo( msblenContextState& state, msblenContextPathProvider& paths, - BlenderSyncSettings& settings, Object* instancedObject, Object* parent, SharedVector mat); From 66dbca266cf4633f78573e078a7a8ebd55df42e8 Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Tue, 5 Apr 2022 16:23:33 +0100 Subject: [PATCH 50/67] Geometry Nodes: Fix for compilation error for versions < 300 --- Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp index aadd5715..5ca15111 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp @@ -14,6 +14,7 @@ using namespace mu; namespace blender { +#if BLENDER_VERSION >= 300 GeometryNodesUtils::GeometryNodesUtils() { auto rotation = rotate_x(-90 * DegToRad); @@ -34,7 +35,6 @@ namespace blender { scale44(scale_z); } -#if BLENDER_VERSION >= 300 /// /// Converts the world matrix from blender to Unity coordinate systems /// From e9738589477de8d9d7cd7179a534a7e5c590315c Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Tue, 5 Apr 2022 19:38:22 +0100 Subject: [PATCH 51/67] Geometry Nodes: fix for mac compilation issues --- .../BlenderPyObjects/BlenderPyCommon.h | 1 + Plugins~/Src/MeshSyncClientBlender/msblenContextState.h | 6 +++--- Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp | 2 +- Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyCommon.h b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyCommon.h index 4379a63d..bbc6614a 100644 --- a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyCommon.h +++ b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyCommon.h @@ -2,6 +2,7 @@ #include //PropertyRNA #include "MeshSync/msFoundation.h" //msPacked +#include "msblenMacros.h" namespace blender { diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContextState.h b/Plugins~/Src/MeshSyncClientBlender/msblenContextState.h index 37509df2..89410889 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContextState.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContextState.h @@ -37,12 +37,12 @@ class msblenContextState { ms::TransformManager& manager; - void msblenContextState::eraseObjectRecords(); - void msblenContextState::eraseStaleObjects(); + void eraseObjectRecords(); + void eraseStaleObjects(); void clear(); void clearRecordsState(); - msblenContextState::ObjectRecord& msblenContextState::touchRecord( + msblenContextState::ObjectRecord& touchRecord( msblenContextPathProvider& path, const Object* obj, const std::string& base_path = "", diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp index 5ca15111..65dcf84e 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp @@ -40,7 +40,7 @@ namespace blender { /// /// /// - float4x4 GeometryNodesUtils::blenderToUnityWorldMatrix(float4x4& blenderMatrix) { + float4x4 GeometryNodesUtils::blenderToUnityWorldMatrix(const float4x4& blenderMatrix) { return m_blender_to_unity_world * diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h index 5d9e1a7c..d214dadf 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h @@ -42,7 +42,7 @@ namespace blender { /// /// /// Converts the world matrix from blender to Unity coordinate system /// /// - mu::float4x4 blenderToUnityWorldMatrix(mu::float4x4& blenderMatrix); + mu::float4x4 blenderToUnityWorldMatrix(const mu::float4x4& blenderMatrix); void setInstancesDirty(bool dirty); bool getInstancesDirty(); From bebd542beaed41c97522e7a58344fe8282f562e4 Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Thu, 7 Apr 2022 18:02:45 +0100 Subject: [PATCH 52/67] Geometry Nodes: revert visibility fix, better formating in meshUtils --- .../MeshSyncClientBlender/msblenContext.cpp | 10 +- .../Src/MeshSyncClientBlender/msblenUtils.cpp | 224 ++++++++---------- .../Src/MeshSyncClientBlender/msblenUtils.h | 181 +++++++------- 3 files changed, 191 insertions(+), 224 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index 2e30926c..16f9c405 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -310,7 +310,7 @@ void msblenContext::extractTransformData(BlenderSyncSettings& settings, const Ob mu::float3& t, mu::quatf& r, mu::float3& s, ms::VisibilityFlags& vis, mu::float4x4 *dst_world, mu::float4x4 *dst_local) { - vis = { visible_in_collection(obj), visible_in_render(obj), visible_in_viewport(obj) }; + vis = { true, visible_in_render(obj), visible_in_viewport(obj) }; const mu::float4x4 local = getLocalMatrix(obj); const mu::float4x4 world = getWorldMatrix(obj); @@ -559,7 +559,9 @@ ms::TransformPtr msblenContext::exportReference(msblenContextState& state, msble auto assign_base_params = [&]() { extractTransformData(settings, src, *dst); dst->path = path; - dst->visibility = {visible_in_collection(src), visible_in_render(ctx.group_host), visible_in_viewport(ctx.group_host)}; + // todo + + dst->visibility = {}; dst->world_matrix *= ctx.dst->world_matrix; }; @@ -626,7 +628,7 @@ ms::TransformPtr msblenContext::exportDupliGroup(msblenContextState& state, msbl std::shared_ptr dst = ms::Transform::create(); dst->path = path; - dst->visibility = { visible_in_collection(src), visible_in_render(ctx.group_host), visible_in_viewport(ctx.group_host) }; + dst->visibility = { true, visible_in_render(ctx.group_host), visible_in_viewport(ctx.group_host) }; const mu::tvec3 offset_pos = -get_instance_offset(group); dst->position = settings.BakeTransform ? mu::float3::zero() : offset_pos; @@ -641,7 +643,7 @@ ms::TransformPtr msblenContext::exportDupliGroup(msblenContextState& state, msbl auto obj = go->ob; if (auto t = exportObject(state, paths, settings, obj, true, false)) { const bool non_lib = obj->id.lib == nullptr; - t->visibility = { visible_in_collection(obj), non_lib, non_lib }; + t->visibility = { true, non_lib, non_lib }; } exportReference(state, paths, settings, obj, ctx2); } diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenUtils.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenUtils.cpp index 0617f82f..8109e931 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenUtils.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenUtils.cpp @@ -5,155 +5,123 @@ namespace bl = blender; namespace msblenUtils { - std::string get_name(const Material* obj) - { - std::string ret; - if (obj) { - ret.assign(obj->id.name + 2); - mu::SanitizeNodeName(ret); - } - return ret; +std::string get_name(const Material* obj) +{ + std::string ret; + if (obj) { + ret.assign(obj->id.name + 2); + mu::SanitizeNodeName(ret); } + return ret; +} - std::string get_name(const Object* obj) - { - std::string ret; - if (obj) { - ret.assign(obj->id.name + 2); - mu::SanitizeNodeName(ret); - } - return ret; - } - - std::string get_name(const Bone* obj) - { - std::string ret; - if (obj) { - ret.assign(obj->name); - mu::SanitizeNodeName(ret); - } - return ret; - } - - std::string get_path(const Object* obj) - { - std::string ret; - if (obj->parent) { - if (obj->partype == PARBONE) { - if (auto bone = find_bone(obj->parent, obj->parsubstr)) { - ret += get_path(obj->parent, bone); - } - } - else { - ret += get_path(obj->parent); - } - } - ret += '/'; - ret += get_name(obj); - return ret; - } - std::string get_path(const Object* arm, const Bone* obj) - { - std::string ret; - if (obj->parent) - ret += get_path(arm, obj->parent); - else - ret += get_path(arm); - ret += '/'; - ret += get_name(obj); - return ret; +std::string get_name(const Object* obj) +{ + std::string ret; + if (obj) { + ret.assign(obj->id.name + 2); + mu::SanitizeNodeName(ret); } + return ret; +} - bool visible_in_render(const Object* obj) - { - return !bl::BObject(obj).hide_render(); - } - bool visible_in_viewport(const Object* obj) - { - return !bl::BObject(obj).hide_viewport(); +std::string get_name(const Bone* obj) +{ + std::string ret; + if (obj) { + ret.assign(obj->name); + mu::SanitizeNodeName(ret); } + return ret; +} - bool visible_in_collection(LayerCollection* layerCollection, const Object* obj) { - // Check if the object is in the layer collection, if it is, check if the layer is excluded: - for (auto collectionObject : blender::list_range((CollectionObject*)layerCollection->collection->gobject.first)) { - if (collectionObject->ob == obj) { - if (!(layerCollection->flag & LAYER_COLLECTION_EXCLUDE)) { - return true; - } +std::string get_path(const Object* obj) +{ + std::string ret; + if (obj->parent) { + if (obj->partype == PARBONE) { + if (auto bone = find_bone(obj->parent, obj->parsubstr)) { + ret += get_path(obj->parent, bone); } } - - // Check child layer collections: - for (auto childCollection : blender::list_range((LayerCollection*)layerCollection->layer_collections.first)) { - if (visible_in_collection(childCollection, obj)) { - return true; - } + else { + ret += get_path(obj->parent); } - - return false; } + ret += '/'; + ret += get_name(obj); + return ret; +} +std::string get_path(const Object* arm, const Bone* obj) +{ + std::string ret; + if (obj->parent) + ret += get_path(arm, obj->parent); + else + ret += get_path(arm); + ret += '/'; + ret += get_name(obj); + return ret; +} - bool visible_in_collection(const Object* obj) { - auto viewLayer = bl::BlenderPyContext::get().viewLayer(); - - for (auto layerCollection : blender::list_range((LayerCollection*)viewLayer->layer_collections.first)) { - if (visible_in_collection(layerCollection, obj)) { - return true; - } - } - - return false; - } +bool visible_in_render(const Object* obj) +{ + return !bl::BObject(obj).hide_render(); +} +bool visible_in_viewport(const Object* obj) +{ + return !bl::BObject(obj).hide_viewport(); +} - const ModifierData* FindModifier(const Object* obj, ModifierType type) - { - for (auto* it = (ModifierData*)obj->modifiers.first; it != nullptr; it = it->next) - if (it->type == type) - return it; - return nullptr;; - } +const ModifierData* FindModifier(const Object* obj, ModifierType type) +{ + for (auto* it = (ModifierData*)obj->modifiers.first; it != nullptr; it = it->next) + if (it->type == type) + return it; + return nullptr;; +} - Bone* find_bone_recursive(Bone* bone, const char* name) - { - if (strcmp(bone->name, name) == 0) { - return bone; - } - else { - for (auto* child = (Bone*)bone->childbase.first; child != nullptr; child = child->next) { - auto* found = find_bone_recursive(child, name); - if (found) - return found; - } - } - return nullptr; +Bone* find_bone_recursive(Bone* bone, const char* name) +{ + if (strcmp(bone->name, name) == 0) { + return bone; } - - Bone* find_bone(Object* obj, const char* name) - { - if (!obj) { return nullptr; } - auto* arm = (bArmature*)obj->data; - for (auto* bone = (Bone*)arm->bonebase.first; bone != nullptr; bone = bone->next) - { - auto found = find_bone_recursive(bone, name); + else { + for (auto* child = (Bone*)bone->childbase.first; child != nullptr; child = child->next) { + auto* found = find_bone_recursive(child, name); if (found) return found; } - return nullptr; } + return nullptr; +} - bPoseChannel* find_pose(Object* obj, const char* name) +Bone* find_bone(Object* obj, const char* name) +{ + if (!obj) { return nullptr; } + auto* arm = (bArmature*)obj->data; + for (auto* bone = (Bone*)arm->bonebase.first; bone != nullptr; bone = bone->next) { - if (!obj || !obj->pose) { return nullptr; } - for (auto* it = (bPoseChannel*)obj->pose->chanbase.first; it != nullptr; it = it->next) - if (std::strcmp(it->name, name) == 0) - return it; - return nullptr; + auto found = find_bone_recursive(bone, name); + if (found) + return found; } + return nullptr; +} + +bPoseChannel* find_pose(Object* obj, const char* name) +{ + if (!obj || !obj->pose) { return nullptr; } + for (auto* it = (bPoseChannel*)obj->pose->chanbase.first; it != nullptr; it = it->next) + if (std::strcmp(it->name, name) == 0) + return it; + return nullptr; +} - bool is_mesh(const Object* obj) { return obj->type == OB_MESH; } - bool is_camera(const Object* obj) { return obj->type == OB_CAMERA; } - bool is_light(const Object* obj) { return obj->type == OB_LAMP; } - bool is_armature(const Object* obj) { return obj->type == OB_ARMATURE; } +bool is_mesh(const Object* obj) { return obj->type == OB_MESH; } +bool is_camera(const Object* obj) { return obj->type == OB_CAMERA; } +bool is_light(const Object* obj) { return obj->type == OB_LAMP; } +bool is_armature(const Object* obj) { return obj->type == OB_ARMATURE; } - bool is_valid_pointer(void* ptr) { return ptr != nullptr && ptr != ((void*)-1); } +bool is_valid_pointer(void* ptr) { return ptr != nullptr && ptr != ((void*)-1); } } diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenUtils.h b/Plugins~/Src/MeshSyncClientBlender/msblenUtils.h index 2645b847..291526be 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenUtils.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenUtils.h @@ -5,113 +5,110 @@ #include "BlenderPyObjects/BlenderPyContext.h" namespace msblenUtils { - std::string get_name(const Material* obj); - std::string get_name(const Object* obj); - std::string get_name(const Bone* obj); - std::string get_path(const Object* obj); - std::string get_path(const Object* arm, const Bone* obj); - bool visible_in_render(const Object* obj); - bool visible_in_viewport(const Object* obj); +std::string get_name(const Material* obj); +std::string get_name(const Object* obj); +std::string get_name(const Bone* obj); +std::string get_path(const Object* obj); +std::string get_path(const Object* arm, const Bone* obj); +bool visible_in_render(const Object* obj); +bool visible_in_viewport(const Object* obj); - bool visible_in_collection(LayerCollection* layerCollection, const Object* obj); - bool visible_in_collection(const Object* obj); - - const ModifierData* FindModifier(const Object* obj, ModifierType type); - Bone* find_bone_recursive(Bone* bone, const char* name); - Bone* find_bone(Object* obj, const char* name); - bPoseChannel* find_pose(Object* obj, const char* name); - - bool is_mesh(const Object* obj); - bool is_camera(const Object* obj); - bool is_light(const Object* obj); - bool is_armature(const Object* obj); - - inline Collection* get_instance_collection(const Object* obj) { - return obj->instance_collection; - } +const ModifierData* FindModifier(const Object* obj, ModifierType type); +Bone* find_bone_recursive(Bone* bone, const char* name); +Bone* find_bone(Object* obj, const char* name); +bPoseChannel* find_pose(Object* obj, const char* name); + +bool is_mesh(const Object* obj); +bool is_camera(const Object* obj); +bool is_light(const Object* obj); +bool is_armature(const Object* obj); + +inline Collection* get_instance_collection(const Object* obj) { + return obj->instance_collection; +} - inline const mu::float3& get_instance_offset(const Collection* col) { - return (mu::float3&)col->instance_offset; - } +inline const mu::float3& get_instance_offset(const Collection* col) { + return (mu::float3&)col->instance_offset; +} - inline BMEditMesh* get_edit_mesh(Mesh* mesh) { - return mesh->edit_mesh; - } +inline BMEditMesh* get_edit_mesh(Mesh* mesh) { + return mesh->edit_mesh; +} - // Body: [](const FCurve*) -> void - template - static inline void each_child(const Object* obj, const Body& body) - { - // Object doesn't have children data. need to enumerate all objects and check its parent... - auto bpy_data = blender::BData(blender::BlenderPyContext::get().data()); - for (auto obj : bpy_data.objects()) { - if (obj->parent == obj) - body(obj); - } +// Body: [](const FCurve*) -> void +template +static inline void each_child(const Object* obj, const Body& body) +{ + // Object doesn't have children data. need to enumerate all objects and check its parent... + auto bpy_data = blender::BData(blender::BlenderPyContext::get().data()); + for (auto obj : bpy_data.objects()) { + if (obj->parent == obj) + body(obj); } +} - // Body: [](const FCurve*) -> void - template - static inline void each_fcurve(Object* obj, const Body& body) - { - if (!obj->adt || !obj->adt->action) return; - for (auto* curve = (FCurve*)obj->adt->action->curves.first; curve; curve = curve->next) { - body(curve); - } +// Body: [](const FCurve*) -> void +template +static inline void each_fcurve(Object* obj, const Body& body) +{ + if (!obj->adt || !obj->adt->action) return; + for (auto* curve = (FCurve*)obj->adt->action->curves.first; curve; curve = curve->next) { + body(curve); } +} - // Body: [](const ModifierData*) -> void - template - inline void each_modifier(Object* obj, const Body& body) - { - auto* it = (const ModifierData*)obj->modifiers.first; - auto* end = (const ModifierData*)obj->modifiers.last; - for (; it != end; it = it->next) - body(it); - } +// Body: [](const ModifierData*) -> void +template +inline void each_modifier(Object* obj, const Body& body) +{ + auto* it = (const ModifierData*)obj->modifiers.first; + auto* end = (const ModifierData*)obj->modifiers.last; + for (; it != end; it = it->next) + body(it); +} - // Body: [](const bDeformGroup*) -> void - template - static inline void each_deform_group(const Object* obj, const Body& body) - { - for (auto* it = (const bDeformGroup*)obj->defbase.first; it != nullptr; it = it->next) - body(it); - } +// Body: [](const bDeformGroup*) -> void +template +static inline void each_deform_group(const Object* obj, const Body& body) +{ + for (auto* it = (const bDeformGroup*)obj->defbase.first; it != nullptr; it = it->next) + body(it); +} - // Body: [](const KeyBlock*) -> void - template - static inline void each_key(Mesh* obj, const Body& body) - { - if (obj->key == nullptr || obj->key->block.first == nullptr) { return; } - for (auto* it = (const KeyBlock*)obj->key->block.first; it != nullptr; it = it->next) - body(it); - } +// Body: [](const KeyBlock*) -> void +template +static inline void each_key(Mesh* obj, const Body& body) +{ + if (obj->key == nullptr || obj->key->block.first == nullptr) { return; } + for (auto* it = (const KeyBlock*)obj->key->block.first; it != nullptr; it = it->next) + body(it); +} - inline mu::float3 to_float3(const float(&v)[3]) - { - return (mu::float3&)v; - } +inline mu::float3 to_float3(const float(&v)[3]) +{ + return (mu::float3&)v; +} - inline mu::float3 to_float3(const short(&v)[3]) - { - return mu::float3{ - v[0] * (1.0f / 32767.0f), - v[1] * (1.0f / 32767.0f), - v[2] * (1.0f / 32767.0f), - }; - } +inline mu::float3 to_float3(const short(&v)[3]) +{ + return mu::float3{ + v[0] * (1.0f / 32767.0f), + v[1] * (1.0f / 32767.0f), + v[2] * (1.0f / 32767.0f), + }; +} - inline mu::float4 to_float4(const MLoopCol& c) - { - return mu::float4{ - c.r * (1.0f / 255.0f), - c.g * (1.0f / 255.0f), - c.b * (1.0f / 255.0f), - c.a * (1.0f / 255.0f), - }; - } +inline mu::float4 to_float4(const MLoopCol& c) +{ + return mu::float4{ + c.r * (1.0f / 255.0f), + c.g * (1.0f / 255.0f), + c.b * (1.0f / 255.0f), + c.a * (1.0f / 255.0f), + }; +} } From e7818c1e6b6be9dabcc5a5a2b856dc71f89c0696 Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Thu, 7 Apr 2022 18:11:33 +0100 Subject: [PATCH 53/67] Geometry Nodes: style changes --- .../Src/MeshSyncClientBlender/msblenUtils.h | 62 +++++++++---------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenUtils.h b/Plugins~/Src/MeshSyncClientBlender/msblenUtils.h index 291526be..8ecf43ac 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenUtils.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenUtils.h @@ -5,40 +5,40 @@ #include "BlenderPyObjects/BlenderPyContext.h" namespace msblenUtils { -std::string get_name(const Material* obj); -std::string get_name(const Object* obj); -std::string get_name(const Bone* obj); -std::string get_path(const Object* obj); -std::string get_path(const Object* arm, const Bone* obj); -bool visible_in_render(const Object* obj); -bool visible_in_viewport(const Object* obj); - -const ModifierData* FindModifier(const Object* obj, ModifierType type); -Bone* find_bone_recursive(Bone* bone, const char* name); -Bone* find_bone(Object* obj, const char* name); -bPoseChannel* find_pose(Object* obj, const char* name); - -bool is_mesh(const Object* obj); -bool is_camera(const Object* obj); -bool is_light(const Object* obj); -bool is_armature(const Object* obj); - -inline Collection* get_instance_collection(const Object* obj) { +std::string get_name(const Material *obj); +std::string get_name(const Object *obj); +std::string get_name(const Bone *obj); +std::string get_path(const Object *obj); +std::string get_path(const Object *arm, const Bone *obj); +bool visible_in_render(const Object *obj); +bool visible_in_viewport(const Object *obj); + +const ModifierData* FindModifier(const Object *obj, ModifierType type); +Bone* find_bone_recursive(Bone *bone, const char *name); +Bone* find_bone(Object *obj, const char *name); +bPoseChannel* find_pose(Object *obj, const char *name); + +bool is_mesh(const Object *obj); +bool is_camera(const Object *obj); +bool is_light(const Object *obj); +bool is_armature(const Object *obj); + +inline Collection* get_instance_collection(const Object *obj) { return obj->instance_collection; } -inline const mu::float3& get_instance_offset(const Collection* col) { +inline const mu::float3& get_instance_offset(const Collection *col) { return (mu::float3&)col->instance_offset; } -inline BMEditMesh* get_edit_mesh(Mesh* mesh) { +inline BMEditMesh* get_edit_mesh(Mesh *mesh) { return mesh->edit_mesh; } // Body: [](const FCurve*) -> void template -static inline void each_child(const Object* obj, const Body& body) +static inline void each_child(const Object *obj, const Body& body) { // Object doesn't have children data. need to enumerate all objects and check its parent... auto bpy_data = blender::BData(blender::BlenderPyContext::get().data()); @@ -50,38 +50,38 @@ static inline void each_child(const Object* obj, const Body& body) // Body: [](const FCurve*) -> void template -static inline void each_fcurve(Object* obj, const Body& body) +static inline void each_fcurve(Object *obj, const Body& body) { if (!obj->adt || !obj->adt->action) return; - for (auto* curve = (FCurve*)obj->adt->action->curves.first; curve; curve = curve->next) { + for (auto *curve = (FCurve*)obj->adt->action->curves.first; curve; curve = curve->next) { body(curve); } } // Body: [](const ModifierData*) -> void template -inline void each_modifier(Object* obj, const Body& body) +inline void each_modifier(Object *obj, const Body& body) { - auto* it = (const ModifierData*)obj->modifiers.first; - auto* end = (const ModifierData*)obj->modifiers.last; + auto *it = (const ModifierData*)obj->modifiers.first; + auto *end = (const ModifierData*)obj->modifiers.last; for (; it != end; it = it->next) body(it); } // Body: [](const bDeformGroup*) -> void template -static inline void each_deform_group(const Object* obj, const Body& body) +static inline void each_deform_group(const Object *obj, const Body& body) { - for (auto* it = (const bDeformGroup*)obj->defbase.first; it != nullptr; it = it->next) + for (auto *it = (const bDeformGroup*)obj->defbase.first; it != nullptr; it = it->next) body(it); } // Body: [](const KeyBlock*) -> void template -static inline void each_key(Mesh* obj, const Body& body) +static inline void each_key(Mesh *obj, const Body& body) { if (obj->key == nullptr || obj->key->block.first == nullptr) { return; } - for (auto* it = (const KeyBlock*)obj->key->block.first; it != nullptr; it = it->next) + for (auto *it = (const KeyBlock*)obj->key->block.first; it != nullptr; it = it->next) body(it); } From f10f6aec4f50c6ef20cac389c6796c8820efc11b Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Thu, 7 Apr 2022 18:15:37 +0100 Subject: [PATCH 54/67] Geometry Nodes: reverted changes on BlenderPyContext for exposing view layer via DNA --- .../BlenderPyObjects/BlenderPyContext.cpp | 8 ++------ .../BlenderPyObjects/BlenderPyContext.h | 3 +-- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp index 6ac08055..4a18d94d 100644 --- a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.cpp @@ -11,7 +11,7 @@ PropertyRNA* BlenderPyContext_blend_data = nullptr; PropertyRNA* BlenderPyContext_scene = nullptr; FunctionRNA* BlenderPyContext_evaluated_depsgraph_get = nullptr; FunctionRNA* BlenderPyContext_depsgraph_update = nullptr; -PropertyRNA* BlenderPyContext_viewlayer = nullptr; + BlenderPyContext BlenderPyContext::get() { @@ -31,14 +31,10 @@ Depsgraph* BlenderPyContext::evaluated_depsgraph_get() return call(g_context, m_ptr, BlenderPyContext_evaluated_depsgraph_get); } -ViewLayer* BlenderPyContext::viewLayer() -{ - return (ViewLayer*)get_pointer(m_ptr, BlenderPyContext_viewlayer); -} - void BlenderPyContext::UpdateDepsgraph(Depsgraph* depsgraph) { call(g_context, depsgraph, BlenderPyContext_depsgraph_update); } + } // namespace blender diff --git a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.h b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.h index ae26adef..2150cd1d 100644 --- a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.h +++ b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyContext.h @@ -2,7 +2,6 @@ #include //bContext #include "msblenMacros.h" //MSBLEN_BOILERPLATE2 -#include "MeshUtils/muMath.h" namespace blender { @@ -16,9 +15,9 @@ namespace blender Main* data(); Scene* scene(); Depsgraph* evaluated_depsgraph_get(); - ViewLayer* viewLayer(); static void UpdateDepsgraph(Depsgraph* depsgraph); + }; } // namespace blender From 374ded91c2b520b6467ba4f0e377984243bbb688 Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Thu, 7 Apr 2022 18:19:12 +0100 Subject: [PATCH 55/67] Geometry Nodes: Removed view layer RNA binding --- Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp index ad5a13f2..a6fa1e4e 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenBinder.cpp @@ -64,7 +64,6 @@ extern PropertyRNA* BlenderPyContext_blend_data; extern PropertyRNA* BlenderPyContext_scene; extern FunctionRNA* BlenderPyContext_evaluated_depsgraph_get; extern FunctionRNA* BlenderPyContext_depsgraph_update; -extern PropertyRNA* BlenderPyContext_viewlayer; extern PropertyRNA* BlenderPyDepsgraphObjectInstance_instance_object; extern PropertyRNA* BlenderPyDepsgraphObjectInstance_is_instance; @@ -201,7 +200,6 @@ void setup(py::object bpy_context) each_prop{ if (match_prop("blend_data")) BlenderPyContext_blend_data = prop; if (match_prop("scene")) BlenderPyContext_scene = prop; - if (match_prop("view_layer")) BlenderPyContext_viewlayer = prop; } each_func{ if (match_func("evaluated_depsgraph_get")) BlenderPyContext_evaluated_depsgraph_get = func; From 777b4d1e08904c7e4a1040ac7471a6a01d3a3b4c Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Thu, 7 Apr 2022 18:37:46 +0100 Subject: [PATCH 56/67] Geometry Nodes: style update --- .../Src/MeshSyncClientBlender/msblenUtils.cpp | 44 +++++++++---------- .../Src/MeshSyncClientBlender/msblenUtils.h | 1 - 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenUtils.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenUtils.cpp index 8109e931..f52e6e8c 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenUtils.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenUtils.cpp @@ -5,7 +5,7 @@ namespace bl = blender; namespace msblenUtils { -std::string get_name(const Material* obj) +std::string get_name(const Material *obj) { std::string ret; if (obj) { @@ -15,7 +15,7 @@ std::string get_name(const Material* obj) return ret; } -std::string get_name(const Object* obj) +std::string get_name(const Object *obj) { std::string ret; if (obj) { @@ -25,7 +25,7 @@ std::string get_name(const Object* obj) return ret; } -std::string get_name(const Bone* obj) +std::string get_name(const Bone *obj) { std::string ret; if (obj) { @@ -35,7 +35,7 @@ std::string get_name(const Bone* obj) return ret; } -std::string get_path(const Object* obj) +std::string get_path(const Object *obj) { std::string ret; if (obj->parent) { @@ -52,7 +52,7 @@ std::string get_path(const Object* obj) ret += get_name(obj); return ret; } -std::string get_path(const Object* arm, const Bone* obj) +std::string get_path(const Object *arm, const Bone *obj) { std::string ret; if (obj->parent) @@ -64,31 +64,31 @@ std::string get_path(const Object* arm, const Bone* obj) return ret; } -bool visible_in_render(const Object* obj) +bool visible_in_render(const Object *obj) { return !bl::BObject(obj).hide_render(); } -bool visible_in_viewport(const Object* obj) +bool visible_in_viewport(const Object *obj) { return !bl::BObject(obj).hide_viewport(); } -const ModifierData* FindModifier(const Object* obj, ModifierType type) +const ModifierData* FindModifier(const Object *obj, ModifierType type) { - for (auto* it = (ModifierData*)obj->modifiers.first; it != nullptr; it = it->next) + for (auto *it = (ModifierData*)obj->modifiers.first; it != nullptr; it = it->next) if (it->type == type) return it; return nullptr;; } -Bone* find_bone_recursive(Bone* bone, const char* name) +Bone* find_bone_recursive(Bone *bone, const char *name) { if (strcmp(bone->name, name) == 0) { return bone; } else { - for (auto* child = (Bone*)bone->childbase.first; child != nullptr; child = child->next) { - auto* found = find_bone_recursive(child, name); + for (auto *child = (Bone*)bone->childbase.first; child != nullptr; child = child->next) { + auto *found = find_bone_recursive(child, name); if (found) return found; } @@ -96,11 +96,11 @@ Bone* find_bone_recursive(Bone* bone, const char* name) return nullptr; } -Bone* find_bone(Object* obj, const char* name) +Bone* find_bone(Object *obj, const char *name) { if (!obj) { return nullptr; } - auto* arm = (bArmature*)obj->data; - for (auto* bone = (Bone*)arm->bonebase.first; bone != nullptr; bone = bone->next) + auto *arm = (bArmature*)obj->data; + for (auto *bone = (Bone*)arm->bonebase.first; bone != nullptr; bone = bone->next) { auto found = find_bone_recursive(bone, name); if (found) @@ -109,19 +109,17 @@ Bone* find_bone(Object* obj, const char* name) return nullptr; } -bPoseChannel* find_pose(Object* obj, const char* name) +bPoseChannel* find_pose(Object *obj, const char *name) { if (!obj || !obj->pose) { return nullptr; } - for (auto* it = (bPoseChannel*)obj->pose->chanbase.first; it != nullptr; it = it->next) + for (auto *it = (bPoseChannel*)obj->pose->chanbase.first; it != nullptr; it = it->next) if (std::strcmp(it->name, name) == 0) return it; return nullptr; } -bool is_mesh(const Object* obj) { return obj->type == OB_MESH; } -bool is_camera(const Object* obj) { return obj->type == OB_CAMERA; } -bool is_light(const Object* obj) { return obj->type == OB_LAMP; } -bool is_armature(const Object* obj) { return obj->type == OB_ARMATURE; } - -bool is_valid_pointer(void* ptr) { return ptr != nullptr && ptr != ((void*)-1); } +bool is_mesh(const Object *obj) { return obj->type == OB_MESH; } +bool is_camera(const Object *obj) { return obj->type == OB_CAMERA; } +bool is_light(const Object *obj) { return obj->type == OB_LAMP; } +bool is_armature(const Object *obj) { return obj->type == OB_ARMATURE; } } diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenUtils.h b/Plugins~/Src/MeshSyncClientBlender/msblenUtils.h index 8ecf43ac..fdfe4677 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenUtils.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenUtils.h @@ -12,7 +12,6 @@ std::string get_path(const Object *obj); std::string get_path(const Object *arm, const Bone *obj); bool visible_in_render(const Object *obj); bool visible_in_viewport(const Object *obj); - const ModifierData* FindModifier(const Object *obj, ModifierType type); Bone* find_bone_recursive(Bone *bone, const char *name); Bone* find_bone(Object *obj, const char *name); From 84853421b9b0a0cdaef43685e8add79d6b1259c2 Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Thu, 7 Apr 2022 18:51:31 +0100 Subject: [PATCH 57/67] Geometry Nodes: used override keyword for functions of EntityManager and InstancesManager --- .../Include/MeshSyncClient/msEntityManager.h | 10 +++++----- .../Include/MeshSyncClient/msInstancesManager.h | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msEntityManager.h b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msEntityManager.h index 7f9a57a7..aba17e56 100644 --- a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msEntityManager.h +++ b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msEntityManager.h @@ -16,7 +16,7 @@ class EntityManager : public TransformManager bool empty() const; // clear all states (both entity and delete record will be cleared) - void clear(); + void clear() override; void clearEntityRecords(); void clearDeleteRecords(); @@ -28,9 +28,9 @@ class EntityManager : public TransformManager bool eraseThreadSafe(TransformPtr v); // thread safe - void add(TransformPtr v); + void add(TransformPtr v) override; - void touch(const std::string& path); + void touch(const std::string& path) override; std::vector getAllEntities(); std::vector getDirtyTransforms(); @@ -40,9 +40,9 @@ class EntityManager : public TransformManager void clearDirtyFlags(); std::vector getStaleEntities(); - void eraseStaleEntities(); + void eraseStaleEntities() override; - void setAlwaysMarkDirty(bool v); + void setAlwaysMarkDirty(bool v) override; private: struct Record diff --git a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h index d8c9d8af..840bcebe 100644 --- a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h +++ b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h @@ -20,13 +20,13 @@ namespace ms { std::vector& getDeleted(); void clearDirtyFlags(); void add(InstanceInfoPtr instanceInfo); - void add(TransformPtr entity); - void clear(); - void touch(const std::string& path); + void add (TransformPtr entity) override; + void clear() override; + void touch(const std::string& path) override; - void eraseStaleEntities(); + void eraseStaleEntities() override; - void setAlwaysMarkDirty(bool alwaysDirty); + void setAlwaysMarkDirty(bool alwaysDirty) override; private: From 2afbcb0851297c59e63f5cfee1e7b35c119d8fd8 Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Thu, 7 Apr 2022 21:23:48 +0100 Subject: [PATCH 58/67] Geometry Nodes: moved duplicate code in EntityManager and InstanceInfoManager up to TransformManager. Introduced ITransformManager interface. --- .../Include/MeshSyncClient/msEntityManager.h | 41 +++++----- .../MeshSyncClient/msITransformManager.h | 15 ++++ .../MeshSyncClient/msInstancesManager.h | 59 ++++++--------- .../MeshSyncClient/msTransformManager.h | 74 ++++++++++++------- .../Src/MeshSyncClient/msEntityManager.cpp | 32 ++------ .../Src/MeshSyncClient/msInstancesManager.cpp | 23 +----- .../msblenContextState.h | 4 +- 7 files changed, 119 insertions(+), 129 deletions(-) create mode 100644 Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msITransformManager.h diff --git a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msEntityManager.h b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msEntityManager.h index aba17e56..674eb018 100644 --- a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msEntityManager.h +++ b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msEntityManager.h @@ -8,7 +8,22 @@ msDeclClassPtr(Transform) #ifndef msRuntime namespace ms { -class EntityManager : public TransformManager + +struct EntityManagerRecord + { + TransformPtr entity; + int order = 0; + uint64_t checksum_trans = 0; + uint64_t checksum_geom = 0; + bool dirty_trans = false; + bool dirty_geom = false; + bool updated = false; + std::future task; + + void waitTask(); +}; + +class EntityManager : public TransformManager { public: EntityManager(); @@ -42,34 +57,16 @@ class EntityManager : public TransformManager std::vector getStaleEntities(); void eraseStaleEntities() override; - void setAlwaysMarkDirty(bool v) override; - private: - struct Record - { - TransformPtr entity; - int order = 0; - uint64_t checksum_trans = 0; - uint64_t checksum_geom = 0; - bool dirty_trans = false; - bool dirty_geom = false; - bool updated = false; - std::future task; - - void waitTask(); - }; + void waitTasks(); - Record& lockAndGet(const std::string& path); + void addTransform(TransformPtr v); void addGeometry(TransformPtr v); - using kvp = std::map::value_type; + using kvp = std::map::value_type; int m_order = 0; - bool m_always_mark_dirty = false; - std::map m_records; - std::vector m_deleted; - std::mutex m_mutex; }; } // namespace ms diff --git a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msITransformManager.h b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msITransformManager.h new file mode 100644 index 00000000..32091982 --- /dev/null +++ b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msITransformManager.h @@ -0,0 +1,15 @@ +#pragma once + +#include "pch.h" +#include "MeshSync/MeshSync.h" + +namespace ms{ +class ITransformManager { +public: + virtual void add(TransformPtr transform) = 0; + virtual void touch(const std::string& path) = 0; + virtual void eraseStaleEntities() = 0; + virtual void clear() = 0; + virtual void setAlwaysMarkDirty(bool flag) = 0; +}; +} \ No newline at end of file diff --git a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h index 840bcebe..d0a6d122 100644 --- a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h +++ b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h @@ -1,7 +1,6 @@ #pragma once #include "MeshSync/MeshSync.h" -#include "MeshSync/SceneGraph/msIdentifier.h" #include #include #include "msTransformManager.h" @@ -12,41 +11,29 @@ msDeclClassPtr(InstanceInfo) namespace ms { - class InstancesManager : public TransformManager - { - public: - std::vector getDirtyMeshes(); - std::vector getDirtyInstances(); - std::vector& getDeleted(); - void clearDirtyFlags(); - void add(InstanceInfoPtr instanceInfo); - void add (TransformPtr entity) override; - void clear() override; - void touch(const std::string& path) override; - - void eraseStaleEntities() override; - - void setAlwaysMarkDirty(bool alwaysDirty) override; - - private: - - struct Record - { - bool dirtyInstances = false; - bool dirtyMesh = false; - InstanceInfoPtr instances = nullptr; - TransformPtr entity = nullptr; - bool updated = false; - }; - - std::map m_records; - std::vector m_deleted; - bool m_always_mark_dirty; - - std::mutex m_mutex; - - Record& lockAndGet(const std::string& path); - }; +struct InstancesManagerRecord +{ + bool dirtyInstances = false; + bool dirtyMesh = false; + InstanceInfoPtr instances = nullptr; + TransformPtr entity = nullptr; + bool updated = false; +}; + +class InstancesManager : public TransformManager +{ +public: + std::vector getDirtyMeshes(); + std::vector getDirtyInstances(); + std::vector& getDeleted(); + void clearDirtyFlags(); + void add(InstanceInfoPtr instanceInfo); + void add (TransformPtr entity) override; + void clear() override; + void touch(const std::string& path) override; + + void eraseStaleEntities() override; +}; diff --git a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msTransformManager.h b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msTransformManager.h index 92c38943..dc0e70fd 100644 --- a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msTransformManager.h +++ b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msTransformManager.h @@ -2,36 +2,60 @@ #include "pch.h" #include "MeshSync/MeshSync.h" +#include "msITransformManager.h" +#include "MeshSync/SceneGraph/msIdentifier.h" namespace ms{ - class TransformManager { - public: - virtual void add(TransformPtr transform) = 0; - virtual void touch(const std::string& path) = 0; - virtual void eraseStaleEntities() = 0; - virtual void clear() = 0; - virtual void setAlwaysMarkDirty(bool flag) = 0; - - TransformManager() {} - ~TransformManager() {} - - TransformManager& operator=(const TransformManager& v) - { - return *this; - } +template +class TransformManager : public ITransformManager { +public: + void setAlwaysMarkDirty(bool v) override { + m_always_mark_dirty = v; + } - TransformManager(TransformManager&& v) - { - *this = std::move(v); - } + virtual void add(TransformPtr transform) = 0; + virtual void touch(const std::string& path) = 0; + virtual void eraseStaleEntities() = 0; + virtual void clear() = 0; + + TransformManager() {} + ~TransformManager() {} + + TransformManager& operator=(const TransformManager& v) + { + return *this; + } + + + TransformManager(TransformManager&& v) + { + *this = std::move(v); + } - TransformManager& operator=(TransformManager&& v) - { + TransformManager& operator=(TransformManager&& v) + { - return *this; - } + return *this; + } + + TransformManager(const TransformManager& v){ *this = v; } + +protected: + bool m_always_mark_dirty = false; + std::mutex m_mutex; + std::vector m_deleted; - TransformManager(const TransformManager& v){ *this = v; } - }; + std::map m_records; + + T& lockAndGet(const std::string& path) { + std::unique_lock lock(m_mutex); + if (!m_deleted.empty()) { + auto it = std::find_if(m_deleted.begin(), m_deleted.end(), [&path](Identifier& v) { return v.name == path; }); + if (it != m_deleted.end()) + m_deleted.erase(it); + } + return m_records[path]; + } +}; } \ No newline at end of file diff --git a/Plugins~/Src/MeshSyncClient/msEntityManager.cpp b/Plugins~/Src/MeshSyncClient/msEntityManager.cpp index 7152874d..4b153c00 100644 --- a/Plugins~/Src/MeshSyncClient/msEntityManager.cpp +++ b/Plugins~/Src/MeshSyncClient/msEntityManager.cpp @@ -97,7 +97,7 @@ bool EntityManager::eraseThreadSafe(TransformPtr v) inline void EntityManager::addTransform(TransformPtr obj) { - EntityManager::Record& rec = lockAndGet(obj->path); + EntityManagerRecord& rec = lockAndGet(obj->path); rec.updated = true; rec.waitTask(); @@ -127,7 +127,7 @@ inline void EntityManager::addTransform(TransformPtr obj) inline void EntityManager::addGeometry(TransformPtr obj) { - EntityManager::Record& rec = lockAndGet(obj->path); + EntityManagerRecord& rec = lockAndGet(obj->path); rec.updated = true; rec.waitTask(); @@ -195,7 +195,7 @@ std::vector EntityManager::getDirtyTransforms() std::vector ret; for (auto& p : m_records) { - Record& r = p.second; + EntityManagerRecord& r = p.second; if (r.dirty_trans) { if (r.entity->isGeometry()) { std::shared_ptr t = Transform::create(); @@ -216,7 +216,7 @@ std::vector EntityManager::getDirtyGeometries() std::vector ret; for (auto& p : m_records) { - Record& r = p.second; + EntityManagerRecord& r = p.second; if (r.dirty_geom) { ret.push_back(r.entity); } @@ -232,7 +232,7 @@ std::vector& EntityManager::getDeleted() void EntityManager::makeDirtyAll() { for (auto& p : m_records) { - Record& r = p.second; + EntityManagerRecord& r = p.second; if(r.entity->isGeometry()) r.dirty_geom = true; else @@ -243,7 +243,7 @@ void EntityManager::makeDirtyAll() void EntityManager::clearDirtyFlags() { for (auto& p : m_records) { - Record& r = p.second; + EntityManagerRecord& r = p.second; r.updated = r.dirty_geom = r.dirty_trans = false; } m_deleted.clear(); @@ -255,7 +255,7 @@ std::vector EntityManager::getStaleEntities() std::vector ret; for (auto& p : m_records) { - Record& r = p.second; + EntityManagerRecord& r = p.second; if (!r.updated) ret.push_back(r.entity); } @@ -274,29 +274,13 @@ void EntityManager::eraseStaleEntities() } } -void EntityManager::setAlwaysMarkDirty(bool v) -{ - m_always_mark_dirty = v; -} - void EntityManager::waitTasks() { for (auto& p : m_records) p.second.waitTask(); } -EntityManager::Record& EntityManager::lockAndGet(const std::string &path) -{ - std::unique_lock lock(m_mutex); - if (!m_deleted.empty()) { - auto it = std::find_if(m_deleted.begin(), m_deleted.end(), [&path](Identifier& v) { return v.name == path; }); - if (it != m_deleted.end()) - m_deleted.erase(it); - } - return m_records[path]; -} - -void EntityManager::Record::waitTask() +void EntityManagerRecord::waitTask() { if (task.valid()) { task.wait(); diff --git a/Plugins~/Src/MeshSyncClient/msInstancesManager.cpp b/Plugins~/Src/MeshSyncClient/msInstancesManager.cpp index eae4ed69..b81d0235 100644 --- a/Plugins~/Src/MeshSyncClient/msInstancesManager.cpp +++ b/Plugins~/Src/MeshSyncClient/msInstancesManager.cpp @@ -8,7 +8,7 @@ namespace ms { { vector ret; for (auto& p : m_records) { - Record& r = p.second; + InstancesManagerRecord& r = p.second; if (r.dirtyMesh) { ret.push_back(r.entity); } @@ -19,7 +19,7 @@ namespace ms { { vector ret; for (auto& p : m_records) { - Record& r = p.second; + InstancesManagerRecord& r = p.second; if (r.dirtyInstances) { ret.push_back(r.instances); } @@ -34,7 +34,7 @@ namespace ms { void InstancesManager::clearDirtyFlags() { for (auto& p : m_records) { - Record& r = p.second; + InstancesManagerRecord& r = p.second; r.dirtyInstances = false; r.dirtyMesh = false; r.updated = false; @@ -61,7 +61,6 @@ namespace ms { { auto& rec = lockAndGet(info->path); - //TODO implement hash for InstanceInfo and check if (m_always_mark_dirty || rec.instances == nullptr) { rec.dirtyInstances = true; } @@ -93,20 +92,4 @@ namespace ms { ++it; } } - - void InstancesManager::setAlwaysMarkDirty(bool alwaysDirty) { - m_always_mark_dirty = alwaysDirty; - } - - InstancesManager::Record& InstancesManager::lockAndGet(const std::string& path) - { - std::unique_lock lock(m_mutex); - if (!m_deleted.empty()) { - auto it = std::find_if(m_deleted.begin(), m_deleted.end(), [&path](Identifier& v) { return v.name == path; }); - if (it != m_deleted.end()) - m_deleted.erase(it); - } - - return m_records[path]; - } } diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContextState.h b/Plugins~/Src/MeshSyncClientBlender/msblenContextState.h index 89410889..2d6248d1 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContextState.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContextState.h @@ -27,7 +27,7 @@ class msblenContextState { void clearState(); }; - msblenContextState(ms::TransformManager& manager) : manager(manager) + msblenContextState(ms::ITransformManager& manager) : manager(manager) { }; @@ -35,7 +35,7 @@ class msblenContextState { std::map records; std::map bones; - ms::TransformManager& manager; + ms::ITransformManager& manager; void eraseObjectRecords(); void eraseStaleObjects(); From bf225540ac9e000e9f1deae8554c5bcff0dcc8b5 Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Thu, 7 Apr 2022 21:35:19 +0100 Subject: [PATCH 59/67] Geometry Nodes: override keywords on path providers. Simplified code for path providers --- .../msblenContextDefaultPathProvider.cpp | 8 ++++---- .../msblenContextDefaultPathProvider.h | 5 +---- .../msblenContextIntermediatePathProvider.cpp | 16 ++-------------- .../msblenContextIntermediatePathProvider.h | 3 +-- .../msblenContextPathProvider.h | 3 +-- 5 files changed, 9 insertions(+), 26 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContextDefaultPathProvider.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContextDefaultPathProvider.cpp index 5b7edf8e..3632d5a4 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContextDefaultPathProvider.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContextDefaultPathProvider.cpp @@ -1,11 +1,11 @@ #include "msblenContextDefaultPathProvider.h" #include "msblenUtils.h" -std::string msblenContextDefaultPathProvider::get_path(const Object* obj) -{ - return msblenUtils::get_path(obj); -} std::string msblenContextDefaultPathProvider::get_path(const Object* arm, const Bone* obj) { + if (obj == nullptr) { + return msblenUtils::get_path(arm); + } + return msblenUtils::get_path(arm, obj); } diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContextDefaultPathProvider.h b/Plugins~/Src/MeshSyncClientBlender/msblenContextDefaultPathProvider.h index 883914b6..daad065e 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContextDefaultPathProvider.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContextDefaultPathProvider.h @@ -6,8 +6,5 @@ class msblenContextDefaultPathProvider : public msblenContextPathProvider { public: - std::string get_path(const Object* obj); - std::string get_path(const Object* arm, const Bone* obj); - - + std::string get_path(const Object* arm, const Bone* obj = nullptr) override; }; \ No newline at end of file diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContextIntermediatePathProvider.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContextIntermediatePathProvider.cpp index eab50f68..fa753bb0 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContextIntermediatePathProvider.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContextIntermediatePathProvider.cpp @@ -9,8 +9,8 @@ std::string append_id(std::string path, const Object* obj) { return path; } -std::string get_name_with_id(const Object* obj, const Bone* bone = nullptr) { - +std::string msblenContextIntermediatePathProvider::get_path(const Object* obj, const Bone* bone) +{ std::string path; if (bone) { path = msblenUtils::get_path(obj, bone); @@ -24,15 +24,3 @@ std::string get_name_with_id(const Object* obj, const Bone* bone = nullptr) { return append_id(path, obj); } - -std::string msblenContextIntermediatePathProvider::get_path(const Object* obj) -{ - auto path = get_name_with_id(obj); - return path; -} - -std::string msblenContextIntermediatePathProvider::get_path(const Object* obj, const Bone* bone) -{ - auto path = get_name_with_id(obj, bone); - return path; -} diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContextIntermediatePathProvider.h b/Plugins~/Src/MeshSyncClientBlender/msblenContextIntermediatePathProvider.h index d1de5afc..178c6610 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContextIntermediatePathProvider.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContextIntermediatePathProvider.h @@ -3,6 +3,5 @@ class msblenContextIntermediatePathProvider: public msblenContextPathProvider { public: - std::string get_path(const Object* obj); - std::string get_path(const Object* obj, const Bone* bone); + std::string get_path(const Object* obj, const Bone* bone) override; }; \ No newline at end of file diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContextPathProvider.h b/Plugins~/Src/MeshSyncClientBlender/msblenContextPathProvider.h index 2e8e7a6a..7ff492a2 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContextPathProvider.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContextPathProvider.h @@ -4,6 +4,5 @@ class msblenContextPathProvider { public: - virtual std::string get_path(const Object* obj) = 0; - virtual std::string get_path(const Object* arm, const Bone* obj) = 0; + virtual std::string get_path(const Object* arm, const Bone* obj = nullptr) = 0; }; \ No newline at end of file From 05b3f8d6c558546d65886041a1e06ab028760a0f Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Thu, 7 Apr 2022 22:05:26 +0100 Subject: [PATCH 60/67] Geometry Nodes: Chagend raw pointers to states to shared pointers. Reverted change to singleton pattern that used a raw pointer --- .../Src/MeshSyncClientBlender/msblenContext.cpp | 14 ++------------ Plugins~/Src/MeshSyncClientBlender/msblenContext.h | 7 +++++-- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index 16f9c405..b2ea64e8 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -65,15 +65,12 @@ void msblenContext::NodeRecord::recordAnimation(msblenContext *_this) const { //---------------------------------------------------------------------------------------------------------------------- -static msblenContext* s_instance = nullptr; msblenContext& msblenContext::getInstance() { - if (s_instance == nullptr) { - s_instance = new msblenContext(); - } + static msblenContext Instance; - return *s_instance; + return Instance; } void msblenContext::Destroy() { @@ -82,24 +79,17 @@ void msblenContext::Destroy() { m_entities_state->clear(); m_instances_state->clear(); - - delete s_instance; } msblenContext::msblenContext() { - m_entities_state = new msblenContextState(m_entity_manager); - m_instances_state = new msblenContextState(m_instances_manager); - m_settings.scene_settings.handedness = ms::Handedness::RightZUp; } msblenContext::~msblenContext() { - delete m_entities_state; - delete m_instances_state; // no wait() because it can cause deadlock... } diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h index 3756953a..f0117d1d 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h @@ -179,8 +179,11 @@ class msblenContext { private: - msblenContextState* m_entities_state = nullptr; - msblenContextState* m_instances_state = nullptr; + std::shared_ptr m_entities_state = + std::shared_ptr(new msblenContextState(m_entity_manager)); + + std::shared_ptr m_instances_state = + std::shared_ptr(new msblenContextState(m_instances_manager)); msblenContextDefaultPathProvider m_default_paths; msblenContextIntermediatePathProvider m_intermediate_paths; From cba846a694027829bfd7bba2b8f2be53b9e99aba Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Thu, 7 Apr 2022 22:10:43 +0100 Subject: [PATCH 61/67] Geometry Nodes: fixed typo --- Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp | 8 ++++---- Plugins~/Src/MeshSyncClientBlender/msblenContext.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index b2ea64e8..66f0eec4 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -1689,10 +1689,10 @@ void msblenContext::exportInstances() { // check if the object has been already exported as part of the scene auto scene_object = scene_objects.find(instanced); if (scene_object == scene_objects.end()) { - return exportInstacesFromFile(instanced, parent, std::move(matrices)); + return exportInstancesFromFile(instanced, parent, std::move(matrices)); } else { - return exportInstacesFromScene(instanced, parent, std::move(matrices)); + return exportInstancesFromScene(instanced, parent, std::move(matrices)); } }); @@ -1700,7 +1700,7 @@ void msblenContext::exportInstances() { scene_objects.clear(); } -void msblenContext::exportInstacesFromFile(Object* instancedObject, Object* parent, SharedVector mat) +void msblenContext::exportInstancesFromFile(Object* instancedObject, Object* parent, SharedVector mat) { auto settings = m_settings; settings.BakeTransform = false; @@ -1721,7 +1721,7 @@ void msblenContext::exportInstacesFromFile(Object* instancedObject, Object* pare exportInstanceInfo(*m_instances_state, m_default_paths, instancedObject, parent, std::move(mat)); } -void msblenContext::exportInstacesFromScene(Object* instancedObject, Object* parent, SharedVector mat) +void msblenContext::exportInstancesFromScene(Object* instancedObject, Object* parent, SharedVector mat) { auto world_matrix = getWorldMatrix(instancedObject); auto inverse = mu::invert(world_matrix); diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h index f0117d1d..3fc8f7be 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h @@ -164,8 +164,8 @@ class msblenContext { #if BLENDER_VERSION >= 300 void exportInstances(); - void exportInstacesFromFile(Object* object, Object* parent, SharedVector); - void exportInstacesFromScene(Object* object, Object* parent, SharedVector); + void exportInstancesFromFile(Object* object, Object* parent, SharedVector); + void exportInstancesFromScene(Object* object, Object* parent, SharedVector); void exportInstancesFromTree(Object* object, Object* parent, SharedVector); ms::InstanceInfoPtr exportInstanceInfo( From 12fde34eb7c3dfcadcf972bd13061c370eb2c9cb Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Thu, 7 Apr 2022 22:18:28 +0100 Subject: [PATCH 62/67] Geometry Nodes: removed hungarian notation from local variable --- .../MeshSyncClientBlender/msblenGeometryNodes.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp index 65dcf84e..61ca1ef4 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp @@ -59,21 +59,21 @@ namespace blender { void GeometryNodesUtils::each_instanced_object(std::function, bool)> handler) { - std::unordered_map m_records; - std::unordered_map m_records_by_name; + std::unordered_map records; + std::unordered_map records_by_name; each_instance([&](Object* obj, Object* parent, float4x4 matrix) { // Critical path, must do as few things as possible auto id = (ID*)obj->data; - auto& rec = m_records[id->session_uuid]; + auto& rec = records[id->session_uuid]; if (!rec.updated) { rec.parent = parent; rec.object_copy = *obj; rec.updated = true; - m_records_by_name[obj->id.name] = &rec; + records_by_name[obj->id.name] = &rec; } rec.matrices.push_back(matrix); @@ -88,8 +88,8 @@ namespace blender { continue; // Check if there is record with the same object name - auto rec = m_records_by_name.find(obj->id.name); - if (rec == m_records_by_name.end()) + auto rec = records_by_name.find(obj->id.name); + if (rec == records_by_name.end()) continue; // Check if the data names also match @@ -105,7 +105,7 @@ namespace blender { } // Export objects that are not in the file - for (auto& rec : m_records) { + for (auto& rec : records) { if (rec.second.handled) continue; From 38ee9086c4170c32ca7b0ef0c612a57f5cdbaabf Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Thu, 7 Apr 2022 22:47:07 +0100 Subject: [PATCH 63/67] Geometry Nodes: Deduplicated code when exporting instances --- .../MeshSyncClientBlender/msblenContext.cpp | 52 +++++++------------ .../Src/MeshSyncClientBlender/msblenContext.h | 3 +- 2 files changed, 19 insertions(+), 36 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index 66f0eec4..95aa741b 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -1681,18 +1681,33 @@ void msblenContext::exportInstances() { m_instances_state->manager.setAlwaysMarkDirty(true); m_geometryNodeUtils.each_instanced_object([this, &scene_objects](Object* instanced, Object* parent, SharedVector matrices, bool fromFile){ + + auto settings = m_settings; + settings.BakeTransform = false; + + // There is some race condition that is causing rendering glitches on Unity. Seems related to UVs or triangle indices. + // Not using threads seems to fix it but should be investigated more. + settings.multithreaded = false; + // If the instanced object is not present in the file if (!fromFile) { + settings.BakeModifiers = false; + auto transform = exportObject(*m_instances_state, m_intermediate_paths, settings, instanced, false); + transform->reset(); return exportInstancesFromTree(instanced, parent, std::move(matrices)); } + auto world_matrix = getWorldMatrix(instanced); + auto inverse = mu::invert(world_matrix); + // check if the object has been already exported as part of the scene auto scene_object = scene_objects.find(instanced); if (scene_object == scene_objects.end()) { - return exportInstancesFromFile(instanced, parent, std::move(matrices)); + exportObject(*m_instances_state, m_default_paths, settings, instanced, false); + return exportInstancesFromFile(instanced, parent, std::move(matrices), inverse); } else { - return exportInstancesFromScene(instanced, parent, std::move(matrices)); + return exportInstancesFromFile(instanced, parent, std::move(matrices), inverse); } }); @@ -1700,20 +1715,8 @@ void msblenContext::exportInstances() { scene_objects.clear(); } -void msblenContext::exportInstancesFromFile(Object* instancedObject, Object* parent, SharedVector mat) +void msblenContext::exportInstancesFromFile(Object* instancedObject, Object* parent, SharedVector mat, mu::float4x4& inverse) { - auto settings = m_settings; - settings.BakeTransform = false; - - // There is some race condition that is causing rendering glitches on Unity. Seems related to UVs or triangle indices. - // Not using threads seems to fix it but should be investigated more. - settings.multithreaded = false; - - auto transform = exportObject(*m_instances_state, m_default_paths, settings, instancedObject, false); - - auto object_world_matrix = getWorldMatrix(instancedObject); - auto inverse = mu::invert(object_world_matrix); -; mu::parallel_for(0, mat.size(), 10, [this, &mat, &inverse](int i) { mat[i] = m_geometryNodeUtils.blenderToUnityWorldMatrix(mat[i] * inverse); @@ -1721,28 +1724,9 @@ void msblenContext::exportInstancesFromFile(Object* instancedObject, Object* par exportInstanceInfo(*m_instances_state, m_default_paths, instancedObject, parent, std::move(mat)); } -void msblenContext::exportInstancesFromScene(Object* instancedObject, Object* parent, SharedVector mat) -{ - auto world_matrix = getWorldMatrix(instancedObject); - auto inverse = mu::invert(world_matrix); - - mu::parallel_for(0, mat.size(), 10, [this, &mat, &inverse](int i) - { - mat[i] = m_geometryNodeUtils.blenderToUnityWorldMatrix(mat[i] * inverse); - }); - - exportInstanceInfo(*m_instances_state, m_default_paths, instancedObject, parent, std::move(mat)); -} void msblenContext::exportInstancesFromTree(Object* instancedObject, Object* parent, SharedVector mat) { - auto settings = m_settings; - settings.BakeTransform = false; - settings.BakeModifiers = false; - settings.multithreaded = false; - - auto transform = exportObject(*m_instances_state, m_intermediate_paths, settings, instancedObject, false); - transform->reset(); mu::parallel_for(0, mat.size(), 10, [this, &mat](int i) { diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h index 3fc8f7be..4ad644c5 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h @@ -164,8 +164,7 @@ class msblenContext { #if BLENDER_VERSION >= 300 void exportInstances(); - void exportInstancesFromFile(Object* object, Object* parent, SharedVector); - void exportInstancesFromScene(Object* object, Object* parent, SharedVector); + void exportInstancesFromFile(Object* object, Object* parent, SharedVector, mu::float4x4& inverse); void exportInstancesFromTree(Object* object, Object* parent, SharedVector); ms::InstanceInfoPtr exportInstanceInfo( From dcdcebc634d917784ffd41ebd24271b8b3b345f9 Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Thu, 7 Apr 2022 23:04:41 +0100 Subject: [PATCH 64/67] Geometry Nodes: moved msblenContext Geometry node function implemetations to msblenContextGeometryNodes.cpp. Renamed msblenGeometryNodes to msblenGeometryNodeUtils --- .../MeshSyncClientBlender/msblenContext.cpp | 91 ------------------ .../Src/MeshSyncClientBlender/msblenContext.h | 4 +- .../msblenContextGeometryNodes.cpp | 94 +++++++++++++++++++ ...metryNodes.h => msblenGeometryNodeUtils.h} | 0 ...Nodes.cpp => msblenGeometryNodesUtils.cpp} | 2 +- 5 files changed, 97 insertions(+), 94 deletions(-) create mode 100644 Plugins~/Src/MeshSyncClientBlender/msblenContextGeometryNodes.cpp rename Plugins~/Src/MeshSyncClientBlender/{msblenGeometryNodes.h => msblenGeometryNodeUtils.h} (100%) rename Plugins~/Src/MeshSyncClientBlender/{msblenGeometryNodes.cpp => msblenGeometryNodesUtils.cpp} (99%) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp index 95aa741b..b29f5189 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.cpp @@ -1646,94 +1646,3 @@ void msblenContext::onDepsgraphUpdatedPost(Depsgraph* graph) } -/// Geometry Nodes Blender Context Functionality /// -#if BLENDER_VERSION >= 300 - -ms::InstanceInfoPtr msblenContext::exportInstanceInfo( - msblenContextState& state, - msblenContextPathProvider& paths, - Object* instancedObject, - Object* parent, - SharedVector mat) { - - auto info = ms::InstanceInfo::create(); - info->path = paths.get_path(instancedObject); - info->parent_path = m_default_paths.get_path(parent); // parent will always be part of the scene - - info->transforms = std::move(mat); - - m_instances_manager.add(info); - - return info; -} - -void msblenContext::exportInstances() { - - bl::BlenderPyScene scene = bl::BlenderPyScene(bl::BlenderPyContext::get().scene()); - - std::unordered_set scene_objects; - scene.each_objects([this, &scene_objects](Object* obj) - { - scene_objects.insert(obj); - }); - - // Assume everything is now dirty - m_instances_state->manager.setAlwaysMarkDirty(true); - - m_geometryNodeUtils.each_instanced_object([this, &scene_objects](Object* instanced, Object* parent, SharedVector matrices, bool fromFile){ - - auto settings = m_settings; - settings.BakeTransform = false; - - // There is some race condition that is causing rendering glitches on Unity. Seems related to UVs or triangle indices. - // Not using threads seems to fix it but should be investigated more. - settings.multithreaded = false; - - // If the instanced object is not present in the file - if (!fromFile) { - settings.BakeModifiers = false; - auto transform = exportObject(*m_instances_state, m_intermediate_paths, settings, instanced, false); - transform->reset(); - return exportInstancesFromTree(instanced, parent, std::move(matrices)); - } - - auto world_matrix = getWorldMatrix(instanced); - auto inverse = mu::invert(world_matrix); - - // check if the object has been already exported as part of the scene - auto scene_object = scene_objects.find(instanced); - if (scene_object == scene_objects.end()) { - exportObject(*m_instances_state, m_default_paths, settings, instanced, false); - return exportInstancesFromFile(instanced, parent, std::move(matrices), inverse); - } - else { - return exportInstancesFromFile(instanced, parent, std::move(matrices), inverse); - } - }); - - m_geometryNodeUtils.setInstancesDirty(false); - - scene_objects.clear(); -} -void msblenContext::exportInstancesFromFile(Object* instancedObject, Object* parent, SharedVector mat, mu::float4x4& inverse) -{ - mu::parallel_for(0, mat.size(), 10, [this, &mat, &inverse](int i) - { - mat[i] = m_geometryNodeUtils.blenderToUnityWorldMatrix(mat[i] * inverse); - }); - - exportInstanceInfo(*m_instances_state, m_default_paths, instancedObject, parent, std::move(mat)); -} - -void msblenContext::exportInstancesFromTree(Object* instancedObject, Object* parent, SharedVector mat) -{ - - mu::parallel_for(0, mat.size(), 10, [this, &mat](int i) - { - mat[i] = m_geometryNodeUtils.blenderToUnityWorldMatrix(mat[i]); - }); - - exportInstanceInfo(*m_instances_state, m_intermediate_paths, instancedObject, parent, std::move(mat)); -} -#endif - diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h index 4ad644c5..77da1a95 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h @@ -19,14 +19,14 @@ #include "BlenderCacheSettings.h" #include "BlenderSyncSettings.h" #include "MeshSyncClient/AsyncTasksController.h" -#include "msblenGeometryNodes.h" +#include "msblenGeometryNodeUtils.h" #include "MeshSyncClient/msInstancesManager.h" #include "MeshSyncClient/msTransformManager.h" #if BLENDER_VERSION >= 300 -#include +#include #endif #include "../MeshSyncClientBlender/msblenContextState.h" diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContextGeometryNodes.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContextGeometryNodes.cpp new file mode 100644 index 00000000..5ad9d731 --- /dev/null +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContextGeometryNodes.cpp @@ -0,0 +1,94 @@ +#include "msblenGeometryNodeUtils.h" +#include "msblenContext.h" +#include "BlenderPyObjects/BlenderPyScene.h" //BlenderPyScene + +/// Geometry Nodes Blender Context Functionality /// +#if BLENDER_VERSION >= 300 + +ms::InstanceInfoPtr msblenContext::exportInstanceInfo( + msblenContextState& state, + msblenContextPathProvider& paths, + Object* instancedObject, + Object* parent, + SharedVector mat) { + + auto info = ms::InstanceInfo::create(); + info->path = paths.get_path(instancedObject); + info->parent_path = m_default_paths.get_path(parent); // parent will always be part of the scene + + info->transforms = std::move(mat); + + m_instances_manager.add(info); + + return info; +} + +void msblenContext::exportInstances() { + + blender::BlenderPyScene scene = blender::BlenderPyScene(blender::BlenderPyContext::get().scene()); + + std::unordered_set scene_objects; + scene.each_objects([this, &scene_objects](Object* obj) + { + scene_objects.insert(obj); + }); + + // Assume everything is now dirty + m_instances_state->manager.setAlwaysMarkDirty(true); + + m_geometryNodeUtils.each_instanced_object([this, &scene_objects](Object* instanced, Object* parent, SharedVector matrices, bool fromFile) { + + auto settings = m_settings; + settings.BakeTransform = false; + + // There is some race condition that is causing rendering glitches on Unity. Seems related to UVs or triangle indices. + // Not using threads seems to fix it but should be investigated more. + settings.multithreaded = false; + + // If the instanced object is not present in the file + if (!fromFile) { + settings.BakeModifiers = false; + auto transform = exportObject(*m_instances_state, m_intermediate_paths, settings, instanced, false); + transform->reset(); + return exportInstancesFromTree(instanced, parent, std::move(matrices)); + } + + auto world_matrix = getWorldMatrix(instanced); + auto inverse = mu::invert(world_matrix); + + // check if the object has been already exported as part of the scene + auto scene_object = scene_objects.find(instanced); + if (scene_object == scene_objects.end()) { + exportObject(*m_instances_state, m_default_paths, settings, instanced, false); + return exportInstancesFromFile(instanced, parent, std::move(matrices), inverse); + } + else { + return exportInstancesFromFile(instanced, parent, std::move(matrices), inverse); + } + }); + + m_geometryNodeUtils.setInstancesDirty(false); + + scene_objects.clear(); +} +void msblenContext::exportInstancesFromFile(Object* instancedObject, Object* parent, SharedVector mat, mu::float4x4& inverse) +{ + mu::parallel_for(0, mat.size(), 10, [this, &mat, &inverse](int i) + { + mat[i] = m_geometryNodeUtils.blenderToUnityWorldMatrix(mat[i] * inverse); + }); + + exportInstanceInfo(*m_instances_state, m_default_paths, instancedObject, parent, std::move(mat)); +} + +void msblenContext::exportInstancesFromTree(Object* instancedObject, Object* parent, SharedVector mat) +{ + + mu::parallel_for(0, mat.size(), 10, [this, &mat](int i) + { + mat[i] = m_geometryNodeUtils.blenderToUnityWorldMatrix(mat[i]); + }); + + exportInstanceInfo(*m_instances_state, m_intermediate_paths, instancedObject, parent, std::move(mat)); +} +#endif \ No newline at end of file diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodeUtils.h similarity index 100% rename from Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.h rename to Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodeUtils.h diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodesUtils.cpp similarity index 99% rename from Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp rename to Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodesUtils.cpp index 61ca1ef4..779baacb 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodes.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodesUtils.cpp @@ -1,4 +1,4 @@ -#include "msblenGeometryNodes.h" +#include "msblenGeometryNodeUtils.h" #include #include #include From 8be11f83b17a15499d80eb9698c4bed16d9a2c18 Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Thu, 7 Apr 2022 23:27:58 +0100 Subject: [PATCH 65/67] Geometry Nodes: added XML comments --- .../MeshSyncClient/msITransformManager.h | 4 ++ .../MeshSyncClient/msInstancesManager.h | 40 +++++++++++++++++++ .../MeshSyncClient/msTransformManager.h | 5 +++ .../BlenderPyObjects/BlenderPyDepsgraph.h | 26 +++++++++++- 4 files changed, 74 insertions(+), 1 deletion(-) diff --git a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msITransformManager.h b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msITransformManager.h index 32091982..2ca31216 100644 --- a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msITransformManager.h +++ b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msITransformManager.h @@ -4,6 +4,10 @@ #include "MeshSync/MeshSync.h" namespace ms{ + +/// +/// Interface for managers that deal with Transforms. +/// class ITransformManager { public: virtual void add(TransformPtr transform) = 0; diff --git a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h index d0a6d122..8cd351da 100644 --- a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h +++ b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msInstancesManager.h @@ -20,18 +20,58 @@ struct InstancesManagerRecord bool updated = false; }; +/// +/// Manager for transforms and transform instances. +/// class InstancesManager : public TransformManager { public: + /// + /// Returns meshes that have changed since the last export. + /// std::vector getDirtyMeshes(); + + /// + /// Returns instaces that have changed since the last export. + /// std::vector getDirtyInstances(); + + /// + /// Returns identifiers of records that have been deleted since the last export. + /// std::vector& getDeleted(); + + /// + /// Clears the dirty flags on the records. + /// void clearDirtyFlags(); + + /// + /// Adds a record about instancing information. + /// void add(InstanceInfoPtr instanceInfo); + + /// + /// Adds or updates a record about the transform. + /// void add (TransformPtr entity) override; + + /// + /// Clears the records collection. + /// void clear() override; + + /// + /// Touches the record at given path. + /// The record will not be considered stale + /// at the end of exportation. + /// void touch(const std::string& path) override; + /// + /// Erases records that have not + /// been added or touched in the last exportation. + /// void eraseStaleEntities() override; }; diff --git a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msTransformManager.h b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msTransformManager.h index dc0e70fd..736e5528 100644 --- a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msTransformManager.h +++ b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msTransformManager.h @@ -6,6 +6,11 @@ #include "MeshSync/SceneGraph/msIdentifier.h" namespace ms{ + +/// +/// Abstraction for managers that handle records with TransformPtr data. +/// +/// The type of record that the manager uses template class TransformManager : public ITransformManager { public: diff --git a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyDepsgraph.h b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyDepsgraph.h index 404c59be..d88e4510 100644 --- a/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyDepsgraph.h +++ b/Plugins~/Src/MeshSyncClientBlender/BlenderPyObjects/BlenderPyDepsgraph.h @@ -4,14 +4,38 @@ namespace blender { - + /// + /// A wrapper around the RNA callbacks for accessing properties and collections related + /// to the Depsgraph. + /// class BlenderPyDepsgraph { public: + + /// + /// Creates a wrapper from the given Depsgraph pointer. + /// BlenderPyDepsgraph(Depsgraph* depsgraph); + + /// + /// Sets the iterator to the begin of the object instances of Depsgraph. + /// void object_instances_begin(CollectionPropertyIterator* it); + + /// + /// Sets the iterator to the end of the object instances of Depsgraph. + /// Will also cleanup resources used by the iterator. + /// void object_instances_end(CollectionPropertyIterator* it); + + /// + /// Moves the iterator to the next element of the object instances of Depsgraph. + /// void object_instances_next(CollectionPropertyIterator* it); + + /// + /// Fetches the iterator value + /// PointerRNA object_instances_get(CollectionPropertyIterator* it); private: From bbd9c1188e02c79f02ddf7d725765382aaa143e2 Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Mon, 11 Apr 2022 12:18:37 +0100 Subject: [PATCH 66/67] Geometry Nodes: Fixed formatting issue --- .../MeshSyncClient/msTransformManager.h | 8 +- .../Src/MeshSyncClientBlender/msblenContext.h | 2 +- .../msblenGeometryNodeUtils.h | 82 +++++++++---------- 3 files changed, 46 insertions(+), 46 deletions(-) diff --git a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msTransformManager.h b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msTransformManager.h index 736e5528..fdbbfd33 100644 --- a/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msTransformManager.h +++ b/Plugins~/Src/MeshSyncClient/Include/MeshSyncClient/msTransformManager.h @@ -19,10 +19,10 @@ class TransformManager : public ITransformManager { m_always_mark_dirty = v; } - virtual void add(TransformPtr transform) = 0; - virtual void touch(const std::string& path) = 0; - virtual void eraseStaleEntities() = 0; - virtual void clear() = 0; + virtual void add(TransformPtr transform) = 0; + virtual void touch(const std::string& path) = 0; + virtual void eraseStaleEntities() = 0; + virtual void clear() = 0; TransformManager() {} ~TransformManager() {} diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h index 77da1a95..ae72d1a6 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContext.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContext.h @@ -118,7 +118,7 @@ class msblenContext { void RegisterObjectMaterials(const std::vector objects); void RegisterMaterial(Material* mat, const uint32_t matIndex); - ms::TransformPtr exportObject(msblenContextState& state, msblenContextPathProvider& paths, BlenderSyncSettings& settings, const Object* obj, bool parent, bool tip = true); + ms::TransformPtr exportObject(msblenContextState& state, msblenContextPathProvider& paths, BlenderSyncSettings& settings, const Object *obj, bool parent, bool tip = true); ms::TransformPtr exportTransform(msblenContextState& state, msblenContextPathProvider& paths, BlenderSyncSettings& settings, const Object *obj); ms::TransformPtr exportPose(msblenContextState& state, msblenContextPathProvider& paths, BlenderSyncSettings& settings, const Object *armature, bPoseChannel *obj); ms::TransformPtr exportArmature(msblenContextState& state, msblenContextPathProvider& paths, BlenderSyncSettings& settings, const Object *obj); diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodeUtils.h b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodeUtils.h index d214dadf..b12b9c5b 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodeUtils.h +++ b/Plugins~/Src/MeshSyncClientBlender/msblenGeometryNodeUtils.h @@ -12,55 +12,55 @@ namespace blender { #if BLENDER_VERSION >= 300 - class GeometryNodesUtils - { - public: +class GeometryNodesUtils +{ +public: - GeometryNodesUtils(); + GeometryNodesUtils(); - /// - /// Invokes the handler function for each instance. - /// - /// - /// The handling function: - /// instancedObject is the object that is being instanced. - /// transform is the transform of the instance - /// - void each_instance(std::function handler); + /// + /// Invokes the handler function for each instance. + /// + /// + /// The handling function: + /// instancedObject is the object that is being instanced. + /// transform is the transform of the instance + /// + void each_instance(std::function handler); - /// - /// Invokes the handler function for each instanced object. - /// - /// - /// The handling function: - /// instancedObject is the object that is being instanced. - /// parent is the object that has the geometry node modifier. - /// transforms is the collection of transforms for the instanced object. - /// - void each_instanced_object(std::function, bool)> handler); + /// + /// Invokes the handler function for each instanced object. + /// + /// + /// The handling function: + /// instancedObject is the object that is being instanced. + /// parent is the object that has the geometry node modifier. + /// transforms is the collection of transforms for the instanced object. + /// + void each_instanced_object(std::function, bool)> handler); - /// - /// /// Converts the world matrix from blender to Unity coordinate system - /// /// - mu::float4x4 blenderToUnityWorldMatrix(const mu::float4x4& blenderMatrix); + /// + /// /// Converts the world matrix from blender to Unity coordinate system + /// /// + mu::float4x4 blenderToUnityWorldMatrix(const mu::float4x4& blenderMatrix); - void setInstancesDirty(bool dirty); - bool getInstancesDirty(); + void setInstancesDirty(bool dirty); + bool getInstancesDirty(); - private: - bool m_instances_dirty; +private: + bool m_instances_dirty; - mu::float4x4 m_blender_to_unity_local; - mu::float4x4 m_blender_to_unity_world; + mu::float4x4 m_blender_to_unity_local; + mu::float4x4 m_blender_to_unity_world; - struct Record { - Object object_copy; - Object* parent = nullptr; - SharedVector matrices; - bool handled = false; - bool updated = false; - }; - }; + struct Record { + Object object_copy; + Object* parent = nullptr; + SharedVector matrices; + bool handled = false; + bool updated = false; + }; +}; #endif From 37989d7e0525e88e5ade4b0ef44a7742074e87d0 Mon Sep 17 00:00:00 2001 From: Sean Dillon Date: Mon, 11 Apr 2022 12:19:28 +0100 Subject: [PATCH 67/67] Geometry Nodes: simplified branching --- .../MeshSyncClientBlender/msblenContextGeometryNodes.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Plugins~/Src/MeshSyncClientBlender/msblenContextGeometryNodes.cpp b/Plugins~/Src/MeshSyncClientBlender/msblenContextGeometryNodes.cpp index 5ad9d731..1ff49c53 100644 --- a/Plugins~/Src/MeshSyncClientBlender/msblenContextGeometryNodes.cpp +++ b/Plugins~/Src/MeshSyncClientBlender/msblenContextGeometryNodes.cpp @@ -60,11 +60,10 @@ void msblenContext::exportInstances() { auto scene_object = scene_objects.find(instanced); if (scene_object == scene_objects.end()) { exportObject(*m_instances_state, m_default_paths, settings, instanced, false); - return exportInstancesFromFile(instanced, parent, std::move(matrices), inverse); - } - else { - return exportInstancesFromFile(instanced, parent, std::move(matrices), inverse); } + + return exportInstancesFromFile(instanced, parent, std::move(matrices), inverse); + }); m_geometryNodeUtils.setInstancesDirty(false);