From 36e3155a8a8b1bb3d6fc1aeefccee398281a1d53 Mon Sep 17 00:00:00 2001 From: ayuan9957 <107920784+ayuan9957@users.noreply.github.com> Date: Fri, 22 May 2026 15:13:57 +0800 Subject: [PATCH] =?UTF-8?q?fix(render):=20=E4=BF=AE=E5=A4=8D=E5=B1=82?= =?UTF-8?q?=E7=BA=A7=E5=B5=8C=E5=A5=97=E6=A8=A1=E5=9E=8B=E5=8A=A0=E8=BD=BD?= =?UTF-8?q?=E5=A4=B1=E8=B4=A5=E5=8F=8A=E6=8B=96=E5=8A=A8=E7=88=B6=E8=8A=82?= =?UTF-8?q?=E7=82=B9=E6=97=B6=E5=AD=90=E7=BA=A7=E5=9D=90=E6=A0=87=E5=90=8C?= =?UTF-8?q?=E6=AD=A5Bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SandboxProject/Scenes/Main.mcscene | 541 +----------------- .../MetaCoreBuiltinCoreServicesModule.cpp | 5 + .../Private/MetaCoreFilamentSceneBridge.cpp | 21 +- .../Private/MetaCoreSceneRenderSync.cpp | 14 +- tests/MetaCoreSmokeTests.cpp | 79 +++ 5 files changed, 107 insertions(+), 553 deletions(-) diff --git a/SandboxProject/Scenes/Main.mcscene b/SandboxProject/Scenes/Main.mcscene index e3d82b6..1b9bd30 100644 --- a/SandboxProject/Scenes/Main.mcscene +++ b/SandboxProject/Scenes/Main.mcscene @@ -57,547 +57,12 @@ 1.0 ] } - }, - { - "Id": 3, - "MeshRenderer": { - "AlphaCutoff": 0.5, - "AlphaMode": 0, - "AoTextureGuid": "", - "AoTexturePath": "", - "BaseColor": [ - 1.0, - 1.0, - 1.0 - ], - "BaseColorTextureGuid": "", - "BaseColorTexturePath": "", - "BuiltinMesh": 0, - "DoubleSided": false, - "EmissiveColor": [ - 0.0, - 0.0, - 0.0 - ], - "EmissiveTextureGuid": "", - "EmissiveTexturePath": "", - "MaterialAssetGuids": [ - "9833a707-d635-426e-5db2-4cb58fbb5d03" - ], - "MeshAssetGuid": "34a6ed73-d4a5-83a3-5863-742c204c4869", - "MeshSource": 1, - "Metallic": 0.0, - "MetallicRoughnessTextureGuid": "", - "MetallicRoughnessTexturePath": "", - "ModelNodeIndex": 0, - "NormalTextureGuid": "", - "NormalTexturePath": "", - "Roughness": 1.0, - "SourceModelAssetGuid": "7033a4a0-8f64-4826-8fec-22ce0fccb514", - "SourceModelPath": "Assets/Models/box1.glb", - "SourceNodePath": "box1", - "SubMeshIndex": -1, - "Visible": true - }, - "Name": "box1.glb", - "ParentId": 0, - "Transform": { - "Position": [ - 0.0, - 0.0, - 0.0 - ], - "RotationEulerDegrees": [ - 0.0, - 0.0, - 0.0 - ], - "Scale": [ - 1.0, - 1.0, - 1.0 - ] - } - }, - { - "Id": 4, - "MeshRenderer": { - "AlphaCutoff": 0.5, - "AlphaMode": 0, - "AoTextureGuid": "", - "AoTexturePath": "", - "BaseColor": [ - 0.75, - 0.7799999713897705, - 0.8399999737739563 - ], - "BaseColorTextureGuid": "", - "BaseColorTexturePath": "", - "BuiltinMesh": 0, - "DoubleSided": true, - "EmissiveColor": [ - 0.0, - 0.0, - 0.0 - ], - "EmissiveTextureGuid": "", - "EmissiveTexturePath": "", - "MaterialAssetGuids": [], - "MeshAssetGuid": "", - "MeshSource": 1, - "Metallic": 0.0, - "MetallicRoughnessTextureGuid": "", - "MetallicRoughnessTexturePath": "", - "ModelNodeIndex": 0, - "NormalTextureGuid": "", - "NormalTexturePath": "", - "Roughness": 1.0, - "SourceModelAssetGuid": "", - "SourceModelPath": "", - "SourceNodePath": "", - "SubMeshIndex": -1, - "Visible": true - }, - "Name": "立方体", - "ParentId": 3, - "Transform": { - "Position": [ - -1.6927926540374756, - -4.459673881530762, - 1.949385364241607e-07 - ], - "RotationEulerDegrees": [ - 0.0, - -0.0, - 0.0 - ], - "Scale": [ - 0.9999998807907104, - 1.0, - 1.0 - ] - } - }, - { - "Id": 5, - "MeshRenderer": { - "AlphaCutoff": 0.5, - "AlphaMode": 0, - "AoTextureGuid": "", - "AoTexturePath": "", - "BaseColor": [ - 0.75, - 0.7799999713897705, - 0.8399999737739563 - ], - "BaseColorTextureGuid": "", - "BaseColorTexturePath": "", - "BuiltinMesh": 0, - "DoubleSided": true, - "EmissiveColor": [ - 0.0, - 0.0, - 0.0 - ], - "EmissiveTextureGuid": "", - "EmissiveTexturePath": "", - "MaterialAssetGuids": [], - "MeshAssetGuid": "", - "MeshSource": 1, - "Metallic": 0.0, - "MetallicRoughnessTextureGuid": "", - "MetallicRoughnessTexturePath": "", - "ModelNodeIndex": 1, - "NormalTextureGuid": "", - "NormalTexturePath": "", - "Roughness": 1.0, - "SourceModelAssetGuid": "", - "SourceModelPath": "", - "SourceNodePath": "", - "SubMeshIndex": -1, - "Visible": true - }, - "Name": "立方体.001", - "ParentId": 4, - "Transform": { - "Position": [ - 0.0, - -3.55507755279541, - 1.553973731915903e-07 - ], - "RotationEulerDegrees": [ - 0.0, - -0.0, - 0.0 - ], - "Scale": [ - 0.9999998807907104, - 1.0, - 1.0 - ] - } - }, - { - "Id": 6, - "MeshRenderer": { - "AlphaCutoff": 0.5, - "AlphaMode": 0, - "AoTextureGuid": "", - "AoTexturePath": "", - "BaseColor": [ - 0.75, - 0.7799999713897705, - 0.8399999737739563 - ], - "BaseColorTextureGuid": "", - "BaseColorTexturePath": "", - "BuiltinMesh": 0, - "DoubleSided": true, - "EmissiveColor": [ - 0.0, - 0.0, - 0.0 - ], - "EmissiveTextureGuid": "", - "EmissiveTexturePath": "", - "MaterialAssetGuids": [], - "MeshAssetGuid": "", - "MeshSource": 1, - "Metallic": 0.0, - "MetallicRoughnessTextureGuid": "", - "MetallicRoughnessTexturePath": "", - "ModelNodeIndex": 2, - "NormalTextureGuid": "", - "NormalTexturePath": "", - "Roughness": 1.0, - "SourceModelAssetGuid": "", - "SourceModelPath": "", - "SourceNodePath": "", - "SubMeshIndex": -1, - "Visible": true - }, - "Name": "立方体.007", - "ParentId": 5, - "Transform": { - "Position": [ - 4.175572872161865, - 0.0, - 0.0 - ], - "RotationEulerDegrees": [ - 0.0, - -0.0, - 0.0 - ], - "Scale": [ - 0.9999998807907104, - 1.0, - 1.0 - ] - } - }, - { - "Id": 7, - "MeshRenderer": { - "AlphaCutoff": 0.5, - "AlphaMode": 0, - "AoTextureGuid": "", - "AoTexturePath": "", - "BaseColor": [ - 0.75, - 0.7799999713897705, - 0.8399999737739563 - ], - "BaseColorTextureGuid": "", - "BaseColorTexturePath": "", - "BuiltinMesh": 0, - "DoubleSided": true, - "EmissiveColor": [ - 0.0, - 0.0, - 0.0 - ], - "EmissiveTextureGuid": "", - "EmissiveTexturePath": "", - "MaterialAssetGuids": [], - "MeshAssetGuid": "", - "MeshSource": 1, - "Metallic": 0.0, - "MetallicRoughnessTextureGuid": "", - "MetallicRoughnessTexturePath": "", - "ModelNodeIndex": 3, - "NormalTextureGuid": "", - "NormalTexturePath": "", - "Roughness": 1.0, - "SourceModelAssetGuid": "", - "SourceModelPath": "", - "SourceNodePath": "", - "SubMeshIndex": -1, - "Visible": true - }, - "Name": "立方体.003", - "ParentId": 3, - "Transform": { - "Position": [ - 0.0, - 0.0, - 0.0 - ], - "RotationEulerDegrees": [ - 0.0, - -0.0, - 0.0 - ], - "Scale": [ - 0.9999998807907104, - 1.0, - 1.0 - ] - } - }, - { - "Id": 8, - "MeshRenderer": { - "AlphaCutoff": 0.5, - "AlphaMode": 0, - "AoTextureGuid": "", - "AoTexturePath": "", - "BaseColor": [ - 0.75, - 0.7799999713897705, - 0.8399999737739563 - ], - "BaseColorTextureGuid": "", - "BaseColorTexturePath": "", - "BuiltinMesh": 0, - "DoubleSided": true, - "EmissiveColor": [ - 0.0, - 0.0, - 0.0 - ], - "EmissiveTextureGuid": "", - "EmissiveTexturePath": "", - "MaterialAssetGuids": [], - "MeshAssetGuid": "", - "MeshSource": 1, - "Metallic": 0.0, - "MetallicRoughnessTextureGuid": "", - "MetallicRoughnessTexturePath": "", - "ModelNodeIndex": 4, - "NormalTextureGuid": "", - "NormalTexturePath": "", - "Roughness": 1.0, - "SourceModelAssetGuid": "", - "SourceModelPath": "", - "SourceNodePath": "", - "SubMeshIndex": -1, - "Visible": true - }, - "Name": "立方体.002", - "ParentId": 7, - "Transform": { - "Position": [ - 0.0, - -1.4481612709005276e-07, - -3.31300687789917 - ], - "RotationEulerDegrees": [ - 0.0, - -0.0, - 0.0 - ], - "Scale": [ - 0.9999998807907104, - 1.0, - 1.0 - ] - } - }, - { - "Id": 9, - "MeshRenderer": { - "AlphaCutoff": 0.5, - "AlphaMode": 0, - "AoTextureGuid": "", - "AoTexturePath": "", - "BaseColor": [ - 0.75, - 0.7799999713897705, - 0.8399999737739563 - ], - "BaseColorTextureGuid": "", - "BaseColorTexturePath": "", - "BuiltinMesh": 0, - "DoubleSided": true, - "EmissiveColor": [ - 0.0, - 0.0, - 0.0 - ], - "EmissiveTextureGuid": "", - "EmissiveTexturePath": "", - "MaterialAssetGuids": [], - "MeshAssetGuid": "", - "MeshSource": 1, - "Metallic": 0.0, - "MetallicRoughnessTextureGuid": "", - "MetallicRoughnessTexturePath": "", - "ModelNodeIndex": 5, - "NormalTextureGuid": "", - "NormalTexturePath": "", - "Roughness": 1.0, - "SourceModelAssetGuid": "", - "SourceModelPath": "", - "SourceNodePath": "", - "SubMeshIndex": -1, - "Visible": true - }, - "Name": "立方体.004", - "ParentId": 7, - "Transform": { - "Position": [ - 3.776623010635376, - 0.0, - 0.0 - ], - "RotationEulerDegrees": [ - 0.0, - -0.0, - 0.0 - ], - "Scale": [ - 0.9999998807907104, - 1.0, - 1.0 - ] - } - }, - { - "Id": 10, - "MeshRenderer": { - "AlphaCutoff": 0.5, - "AlphaMode": 0, - "AoTextureGuid": "", - "AoTexturePath": "", - "BaseColor": [ - 0.75, - 0.7799999713897705, - 0.8399999737739563 - ], - "BaseColorTextureGuid": "", - "BaseColorTexturePath": "", - "BuiltinMesh": 0, - "DoubleSided": true, - "EmissiveColor": [ - 0.0, - 0.0, - 0.0 - ], - "EmissiveTextureGuid": "", - "EmissiveTexturePath": "", - "MaterialAssetGuids": [], - "MeshAssetGuid": "", - "MeshSource": 1, - "Metallic": 0.0, - "MetallicRoughnessTextureGuid": "", - "MetallicRoughnessTexturePath": "", - "ModelNodeIndex": 6, - "NormalTextureGuid": "", - "NormalTexturePath": "", - "Roughness": 1.0, - "SourceModelAssetGuid": "", - "SourceModelPath": "", - "SourceNodePath": "", - "SubMeshIndex": -1, - "Visible": true - }, - "Name": "立方体.005", - "ParentId": 7, - "Transform": { - "Position": [ - 0.0, - 4.31797981262207, - -1.8874489171594178e-07 - ], - "RotationEulerDegrees": [ - 0.0, - -0.0, - 0.0 - ], - "Scale": [ - 0.9999998807907104, - 1.0, - 1.0 - ] - } - }, - { - "Id": 11, - "MeshRenderer": { - "AlphaCutoff": 0.5, - "AlphaMode": 0, - "AoTextureGuid": "", - "AoTexturePath": "", - "BaseColor": [ - 0.75, - 0.7799999713897705, - 0.8399999737739563 - ], - "BaseColorTextureGuid": "", - "BaseColorTexturePath": "", - "BuiltinMesh": 0, - "DoubleSided": true, - "EmissiveColor": [ - 0.0, - 0.0, - 0.0 - ], - "EmissiveTextureGuid": "", - "EmissiveTexturePath": "", - "MaterialAssetGuids": [], - "MeshAssetGuid": "", - "MeshSource": 1, - "Metallic": 0.0, - "MetallicRoughnessTextureGuid": "", - "MetallicRoughnessTexturePath": "", - "ModelNodeIndex": 7, - "NormalTextureGuid": "", - "NormalTexturePath": "", - "Roughness": 1.0, - "SourceModelAssetGuid": "", - "SourceModelPath": "", - "SourceNodePath": "", - "SubMeshIndex": -1, - "Visible": true - }, - "Name": "立方体.006", - "ParentId": 7, - "Transform": { - "Position": [ - -4.638434886932373, - 0.0, - 0.0 - ], - "RotationEulerDegrees": [ - 0.0, - -0.0, - 0.0 - ], - "Scale": [ - 0.9999998807907104, - 1.0, - 1.0 - ] - } } ], "SceneName": "Main", "Selection": { - "ActiveObjectId": 3, - "SelectedObjectIds": [ - 3 - ], - "SelectionAnchorId": 3 + "ActiveObjectId": 0, + "SelectedObjectIds": [], + "SelectionAnchorId": 0 } } \ No newline at end of file diff --git a/Source/MetaCoreEditor/Private/MetaCoreBuiltinCoreServicesModule.cpp b/Source/MetaCoreEditor/Private/MetaCoreBuiltinCoreServicesModule.cpp index c193750..342ce3b 100644 --- a/Source/MetaCoreEditor/Private/MetaCoreBuiltinCoreServicesModule.cpp +++ b/Source/MetaCoreEditor/Private/MetaCoreBuiltinCoreServicesModule.cpp @@ -5833,6 +5833,11 @@ std::optional MetaCoreBuiltinSceneEditingService::InstantiateModelAs std::vector nodeToIdMap(importedDocument->Nodes.size(), 0); if (importedDocument->Nodes.size() == 1) { + // 给顶级根节点打上 Tag,用以在渲染同步回溯时精确定位宿主根 + if (!modelRootObject.HasComponent()) { + modelRootObject.AddComponent(MetaCoreModelRootTag{ resolvedModelPath.generic_string() }); + } + // 【平坦化优化】:针对单网格模型(如 box11.glb),不创建多余子级,直接将渲染器挂在顶级节点上 const auto& nodeMeta = importedDocument->Nodes[0]; nodeToIdMap[0] = instantiatedRootId; diff --git a/Source/MetaCoreRender/Private/MetaCoreFilamentSceneBridge.cpp b/Source/MetaCoreRender/Private/MetaCoreFilamentSceneBridge.cpp index 0ef7856..283a71e 100644 --- a/Source/MetaCoreRender/Private/MetaCoreFilamentSceneBridge.cpp +++ b/Source/MetaCoreRender/Private/MetaCoreFilamentSceneBridge.cpp @@ -653,7 +653,12 @@ public: if (itMat != snapshot.LocalMatrices.end()) { initLocalMat = itMat->second; } - UpdateTransform(renderable.ObjectId, initLocalMat); + glm::mat4 initWorldMat = initLocalMat; + auto itWorldMat = snapshot.WorldMatrices.find(renderable.ObjectId); + if (itWorldMat != snapshot.WorldMatrices.end()) { + initWorldMat = itWorldMat->second; + } + UpdateTransform(renderable.ObjectId, initLocalMat, initWorldMat); } // 1. 构建反向查找映射,方便反查 entity 对应的 objectId @@ -753,10 +758,11 @@ public: // 4. 同步所有存活实体的本地和全局变换矩阵 for (const auto& [objectId, assetEntity] : ObjectToFilamentEntity_) { - if (snapshot.WorldMatrices.contains(objectId)) { - auto itMat = snapshot.LocalMatrices.find(objectId); - if (itMat != snapshot.LocalMatrices.end()) { - UpdateTransform(objectId, itMat->second); + auto itWorld = snapshot.WorldMatrices.find(objectId); + if (itWorld != snapshot.WorldMatrices.end()) { + auto itLocal = snapshot.LocalMatrices.find(objectId); + if (itLocal != snapshot.LocalMatrices.end()) { + UpdateTransform(objectId, itLocal->second, itWorld->second); } } } @@ -1036,7 +1042,7 @@ private: } } - void UpdateTransform(MetaCoreId objectId, const glm::mat4& localMatrix) { + void UpdateTransform(MetaCoreId objectId, const glm::mat4& localMatrix, const glm::mat4& worldMatrix) { auto it = ObjectToFilamentEntity_.find(objectId); if (it == ObjectToFilamentEntity_.end()) return; @@ -1045,7 +1051,8 @@ private: auto& tm = Engine_->getTransformManager(); auto instance = tm.getInstance(entity); if (instance) { - glm::mat4 matrix = localMatrix; + auto parent = tm.getParent(instance); + glm::mat4 matrix = parent ? localMatrix : worldMatrix; // 【关键修复】:如果当前 entity 是子节点(即不是顶级映射的 pivotEntity) // 由于它的父级(assetRoot)带有了 -90X 旋转,我们必须对子节点应用基变换来抵消这个旋转。 diff --git a/Source/MetaCoreRender/Private/MetaCoreSceneRenderSync.cpp b/Source/MetaCoreRender/Private/MetaCoreSceneRenderSync.cpp index 7d58b3e..cf0f8b7 100644 --- a/Source/MetaCoreRender/Private/MetaCoreSceneRenderSync.cpp +++ b/Source/MetaCoreRender/Private/MetaCoreSceneRenderSync.cpp @@ -89,18 +89,16 @@ MetaCoreSceneRenderSyncSnapshot MetaCoreSceneRenderSync::BuildSnapshot(const Met MetaCoreGameObject foundRoot = {}; // 1. 优先通过运行时 MetaCoreModelRootTag 快速寻找顶级根 - while (current.GetParentId() != 0) { - auto parentObj = scene.FindGameObject(current.GetParentId()); - if (!parentObj) break; - - if (parentObj.HasComponent()) { - auto& tag = parentObj.GetComponent(); + while (current) { + if (current.HasComponent()) { + auto& tag = current.GetComponent(); if (MetaCoreNormalizeSyncPath(tag.SourceModelPath) == normCurrentPath) { - foundRoot = parentObj; + foundRoot = current; break; } } - current = parentObj; + if (current.GetParentId() == 0) break; + current = scene.FindGameObject(current.GetParentId()); } if (foundRoot) { diff --git a/tests/MetaCoreSmokeTests.cpp b/tests/MetaCoreSmokeTests.cpp index b671610..7f5cc4d 100644 --- a/tests/MetaCoreSmokeTests.cpp +++ b/tests/MetaCoreSmokeTests.cpp @@ -2830,6 +2830,82 @@ void MetaCoreTestDecoupledSnapshotSync() { window.Shutdown(); } +void MetaCoreTestNestedModelHierarchyTransformSync() { + // 1. 创建测试场景,建立嵌套模型和父子变换结构 + MetaCore::MetaCoreScene scene = MetaCore::MetaCoreCreateDefaultScene(); + + // 模拟根模型 (box1.glb) + MetaCore::MetaCoreGameObject parentModel = scene.CreateGameObject("ParentModel"); + auto& parentMesh = parentModel.AddComponent(); + parentMesh.MeshSource = MetaCore::MetaCoreMeshSourceKind::Asset; + parentMesh.SourceModelPath = "Assets/Models/box1.glb"; + parentMesh.SourceModelAssetGuid = MetaCore::MetaCoreAssetRegistry::Get().ResolvePathToGuid("Assets/Models/box1.glb"); + parentModel.AddComponent(MetaCore::MetaCoreModelRootTag{ "Assets/Models/box1.glb" }); + parentModel.GetComponent().Position = glm::vec3(0.0F, 1.0F, 0.0F); + + // 模拟子模型 (嵌套相同的 box1.glb,其 parent 为 parentModel) + MetaCore::MetaCoreGameObject childModel = scene.CreateGameObject("ChildModel", parentModel.GetId()); + auto& childMesh = childModel.AddComponent(); + childMesh.MeshSource = MetaCore::MetaCoreMeshSourceKind::Asset; + childMesh.SourceModelPath = "Assets/Models/box1.glb"; + childMesh.SourceModelAssetGuid = MetaCore::MetaCoreAssetRegistry::Get().ResolvePathToGuid("Assets/Models/box1.glb"); + childModel.AddComponent(MetaCore::MetaCoreModelRootTag{ "Assets/Models/box1.glb" }); + childModel.GetComponent().Position = glm::vec3(2.0F, 0.0F, 0.0F); // 局部偏移 x + 2.0 + + MetaCore::MetaCoreSceneRenderSync renderSync; + MetaCore::MetaCoreSceneRenderSyncSnapshot snapshot = renderSync.BuildSnapshot(scene); + + // 验证 Bug 2 修复:子模型的 HostRootId 应该为它自己,而不是父模型 + bool foundChild = false; + for (const auto& renderable : snapshot.Renderables) { + if (renderable.ObjectId == childModel.GetId()) { + foundChild = true; + MetaCoreExpect(renderable.HostRootId == childModel.GetId(), "子模型的 HostRootId 必须等于其自身的 ID,不能被错判为父模型 ID"); + } + } + MetaCoreExpect(foundChild, "快照的渲染实体列表中应包含 ChildModel"); + + // 2. 初始化桥接器 + MetaCore::MetaCoreWindow window; + bool winOk = window.Initialize(800, 600, "NestedModelHierarchyTestWindow"); + MetaCoreExpect(winOk, "测试窗口初始化成功"); + + MetaCore::MetaCoreFilamentSceneBridge bridge; + bridge.SetProjectRootPath("d:/MetaCore/SandboxProject"); + bool bridgeOk = bridge.Initialize(window); + MetaCoreExpect(bridgeOk, "测试桥接器初始化成功"); + + // 同步快照 + bridge.SyncScene(snapshot, nullptr, false, false); + + // 验证 Bug 1 修复:在没有 Filament 层级关系下,子模型在 Filament 侧的变换矩阵应当正确跟随父模型的世界矩阵 + // 子模型局部矩阵 + glm::mat4 childLocalMat = glm::translate(glm::mat4(1.0F), glm::vec3(2.0F, 0.0F, 0.0F)); + // 父模型世界矩阵 + glm::mat4 parentWorldMat = glm::translate(glm::mat4(1.0F), glm::vec3(0.0F, 1.0F, 0.0F)); + // 预期的子模型世界矩阵 + glm::mat4 expectedChildWorldMat = parentWorldMat * childLocalMat; + + bool transOk = bridge.VerifyTransformForTesting(childModel.GetId(), expectedChildWorldMat); + MetaCoreExpect(transOk, "子模型在 Filament 侧的最终变换矩阵应正确应用世界矩阵"); + + // 3. 拖拽父级:修改父模型位置,重新同步,并校验子模型是否跟着移动 + parentModel.GetComponent().Position = glm::vec3(10.0F, 5.0F, 0.0F); + + // 重新构建快照与同步 + snapshot = renderSync.BuildSnapshot(scene); + bridge.SyncScene(snapshot, nullptr, false, false); + + glm::mat4 newParentWorldMat = glm::translate(glm::mat4(1.0F), glm::vec3(10.0F, 5.0F, 0.0F)); + glm::mat4 newExpectedChildWorldMat = newParentWorldMat * childLocalMat; + + bool transOk2 = bridge.VerifyTransformForTesting(childModel.GetId(), newExpectedChildWorldMat); + MetaCoreExpect(transOk2, "拖拽父级后,子模型在 Filament 侧的最终变换矩阵应实时跟随父模型世界矩阵更新"); + + bridge.Shutdown(); + window.Shutdown(); +} + void MetaCoreTestP3ProductivityStage() { const std::filesystem::path tempProjectRoot = std::filesystem::temp_directory_path() / "MetaCoreTestP3Project"; @@ -3115,6 +3191,9 @@ int main() { std::cout << "[RUN] MetaCoreTestDecoupledSnapshotSync..." << std::endl; MetaCoreTestDecoupledSnapshotSync(); + std::cout << "[RUN] MetaCoreTestNestedModelHierarchyTransformSync..." << std::endl; + MetaCoreTestNestedModelHierarchyTransformSync(); + std::cout << "[RUN] MetaCoreTestP3ProductivityStage..." << std::endl; MetaCoreTestP3ProductivityStage();