From 045943ef27b257ad99d8407cc914dca0e7aaab39 Mon Sep 17 00:00:00 2001 From: Menotdan <32620310+Menotdan@users.noreply.github.com> Date: Mon, 1 Jan 2024 19:11:45 -0500 Subject: [PATCH 01/11] Fix prefab scale and rotation. --- Source/Engine/ContentImporters/ImportModel.cpp | 4 +++- Source/Engine/Tools/ModelTool/ModelTool.cpp | 10 ++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Source/Engine/ContentImporters/ImportModel.cpp b/Source/Engine/ContentImporters/ImportModel.cpp index baac1defb..b6fd483d3 100644 --- a/Source/Engine/ContentImporters/ImportModel.cpp +++ b/Source/Engine/ContentImporters/ImportModel.cpp @@ -665,7 +665,9 @@ CreateAssetResult ImportModel::CreatePrefab(CreateAssetContext& context, ModelDa // Setup node in hierarchy nodeToActor.Add(nodeIndex, nodeActor); nodeActor->SetName(node.Name); - nodeActor->SetLocalTransform(node.LocalTransform); + + // Only set translation, since scale and rotation is applied earlier. + nodeActor->SetLocalTransform(Transform(node.LocalTransform.Translation)); if (nodeIndex == 0) { // Special case for root actor to link any unlinked nodes diff --git a/Source/Engine/Tools/ModelTool/ModelTool.cpp b/Source/Engine/Tools/ModelTool/ModelTool.cpp index e2b2f5d8d..ac9cda8b6 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.cpp +++ b/Source/Engine/Tools/ModelTool/ModelTool.cpp @@ -1292,7 +1292,7 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option ! #endif } - if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Geometry) && options.Type != ModelType::Prefab) + if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Geometry)) { // Perform simple nodes mapping to single node (will transform meshes to model local space) SkeletonMapping skeletonMapping(data.Nodes, nullptr); @@ -1312,7 +1312,13 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option if (skeletonMapping.SourceToSource[mesh.NodeIndex] != mesh.NodeIndex) { // Transform vertices - const auto transformationMatrix = hierarchyUpdater.CombineMatricesFromNodeIndices(skeletonMapping.SourceToSource[mesh.NodeIndex], mesh.NodeIndex); + auto transformationMatrix = hierarchyUpdater.CombineMatricesFromNodeIndices(skeletonMapping.SourceToSource[mesh.NodeIndex], mesh.NodeIndex); + if (options.Type == ModelType::Prefab) + { + // Cancel out translation during mesh transformation, to set translation during prefab generation time. + transformationMatrix = transformationMatrix * transformationMatrix.Translation(transformationMatrix.GetTranslation() * -1.0f); + } + if (!transformationMatrix.IsIdentity()) mesh.TransformBuffer(transformationMatrix); } From 827365679376134569561c2bfd83a20827f72059 Mon Sep 17 00:00:00 2001 From: Menotdan <32620310+Menotdan@users.noreply.github.com> Date: Mon, 1 Jan 2024 20:24:13 -0500 Subject: [PATCH 02/11] Fix major issue with transformation. --- .../Engine/ContentImporters/ImportModel.cpp | 5 +++- Source/Engine/Tools/ModelTool/ModelTool.cpp | 30 +++++++++++++++---- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/Source/Engine/ContentImporters/ImportModel.cpp b/Source/Engine/ContentImporters/ImportModel.cpp index b6fd483d3..ac2bacd25 100644 --- a/Source/Engine/ContentImporters/ImportModel.cpp +++ b/Source/Engine/ContentImporters/ImportModel.cpp @@ -666,8 +666,11 @@ CreateAssetResult ImportModel::CreatePrefab(CreateAssetContext& context, ModelDa nodeToActor.Add(nodeIndex, nodeActor); nodeActor->SetName(node.Name); + Transform positionOffset = Transform::Identity; + positionOffset.Translation = node.LocalTransform.Translation; + LOG(Warning, "node name: {0}, offset transform: {1}", node.Name, positionOffset); // Only set translation, since scale and rotation is applied earlier. - nodeActor->SetLocalTransform(Transform(node.LocalTransform.Translation)); + nodeActor->SetLocalTransform(positionOffset); if (nodeIndex == 0) { // Special case for root actor to link any unlinked nodes diff --git a/Source/Engine/Tools/ModelTool/ModelTool.cpp b/Source/Engine/Tools/ModelTool/ModelTool.cpp index ac9cda8b6..899f67a1f 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.cpp +++ b/Source/Engine/Tools/ModelTool/ModelTool.cpp @@ -1292,7 +1292,7 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option ! #endif } - if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Geometry)) + if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Geometry) && !(options.Type == ModelType::Prefab)) { // Perform simple nodes mapping to single node (will transform meshes to model local space) SkeletonMapping skeletonMapping(data.Nodes, nullptr); @@ -1313,11 +1313,6 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option { // Transform vertices auto transformationMatrix = hierarchyUpdater.CombineMatricesFromNodeIndices(skeletonMapping.SourceToSource[mesh.NodeIndex], mesh.NodeIndex); - if (options.Type == ModelType::Prefab) - { - // Cancel out translation during mesh transformation, to set translation during prefab generation time. - transformationMatrix = transformationMatrix * transformationMatrix.Translation(transformationMatrix.GetTranslation() * -1.0f); - } if (!transformationMatrix.IsIdentity()) mesh.TransformBuffer(transformationMatrix); @@ -1328,6 +1323,29 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option } } } + if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Geometry) && options.Type == ModelType::Prefab) + { + // Apply just the scale and rotations. + for (int32 lodIndex = 0; lodIndex < data.LODs.Count(); lodIndex++) + { + for (int32 meshIndex = 0; meshIndex < data.LODs[lodIndex].Meshes.Count(); meshIndex++) + { + auto& mesh = *data.LODs[lodIndex].Meshes[meshIndex]; + auto& node = data.Nodes[mesh.NodeIndex]; + + // Transform vertices + auto transformationMatrix = Matrix::Identity; + transformationMatrix.SetScaleVector(node.LocalTransform.Scale); + + Matrix rotation; + node.LocalTransform.GetRotation(rotation); + transformationMatrix = transformationMatrix * rotation; + + if (!transformationMatrix.IsIdentity()) + mesh.TransformBuffer(transformationMatrix); + } + } + } if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Animations)) { for (auto& animation : data.Animations) From ab51ca6e705e8110db9e14e7e40f7e16bf8c93c3 Mon Sep 17 00:00:00 2001 From: Menotdan <32620310+Menotdan@users.noreply.github.com> Date: Mon, 1 Jan 2024 21:35:18 -0500 Subject: [PATCH 03/11] Change behavior when Use Local Origin is checked. --- .../Engine/ContentImporters/ImportModel.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/Source/Engine/ContentImporters/ImportModel.cpp b/Source/Engine/ContentImporters/ImportModel.cpp index ac2bacd25..a2629baf4 100644 --- a/Source/Engine/ContentImporters/ImportModel.cpp +++ b/Source/Engine/ContentImporters/ImportModel.cpp @@ -666,11 +666,20 @@ CreateAssetResult ImportModel::CreatePrefab(CreateAssetContext& context, ModelDa nodeToActor.Add(nodeIndex, nodeActor); nodeActor->SetName(node.Name); - Transform positionOffset = Transform::Identity; - positionOffset.Translation = node.LocalTransform.Translation; - LOG(Warning, "node name: {0}, offset transform: {1}", node.Name, positionOffset); - // Only set translation, since scale and rotation is applied earlier. - nodeActor->SetLocalTransform(positionOffset); + // When use local origin is checked, it shifts everything over the same amount, including the root. This tries to work around that. + if (!(nodeIndex == 0 && options.UseLocalOrigin)) + { + // Only set translation, since scale and rotation is applied earlier. + Transform positionOffset = Transform::Identity; + positionOffset.Translation = node.LocalTransform.Translation; + if (options.UseLocalOrigin) + { + positionOffset.Translation += data.Nodes[0].LocalTransform.Translation; + } + + nodeActor->SetLocalTransform(positionOffset); + } + if (nodeIndex == 0) { // Special case for root actor to link any unlinked nodes From 8bd84e0616609916e8262a4dd353833d502cc1d8 Mon Sep 17 00:00:00 2001 From: Menotdan <32620310+Menotdan@users.noreply.github.com> Date: Tue, 2 Jan 2024 03:52:57 -0500 Subject: [PATCH 04/11] Fix sub-mesh reimporting with some potentially hacky workarounds? --- Source/Engine/ContentImporters/ImportModel.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/Source/Engine/ContentImporters/ImportModel.cpp b/Source/Engine/ContentImporters/ImportModel.cpp index a2629baf4..08c9e707f 100644 --- a/Source/Engine/ContentImporters/ImportModel.cpp +++ b/Source/Engine/ContentImporters/ImportModel.cpp @@ -269,7 +269,7 @@ CreateAssetResult ImportModel::Import(CreateAssetContext& context) // Import all of the objects recursive but use current model data to skip loading file again options.Cached = &cached; - Function splitImport = [&context, &autoImportOutput](Options& splitOptions, const StringView& objectName, String& outputPath) + Function splitImport = [&context, &autoImportOutput](Options& splitOptions, const StringView& objectName, String& outputPath, MeshData& meshData) { // Recursive importing of the split object String postFix = objectName; @@ -279,6 +279,17 @@ CreateAssetResult ImportModel::Import(CreateAssetContext& context) // TODO: check for name collisions with material/texture assets outputPath = autoImportOutput / String(StringUtils::GetFileNameWithoutExtension(context.TargetAssetPath)) + TEXT(" ") + postFix + TEXT(".flax"); splitOptions.SubAssetFolder = TEXT(" "); // Use the same folder as asset as they all are imported to the subdir for the prefab (see SubAssetFolder usage above) + + if (splitOptions.Type == ModelTool::ModelType::Model) + { + // These settings interfere with submesh reimporting. + splitOptions.CenterGeometry = false; + splitOptions.UseLocalOrigin = false; + + // This properly sets the transformation of the mesh during reimport. + splitOptions.Translation = meshData.OriginTranslation * -1.0f; + } + return AssetsImportingManager::Import(context.InputPath, outputPath, &splitOptions); }; auto splitOptions = options; @@ -294,7 +305,7 @@ CreateAssetResult ImportModel::Import(CreateAssetContext& context) splitOptions.Type = ModelTool::ModelType::Model; splitOptions.ObjectIndex = groupIndex; - if (!splitImport(splitOptions, group.GetKey(), prefabObject.AssetPath)) + if (!splitImport(splitOptions, group.GetKey(), prefabObject.AssetPath, *group.First())) { prefabObjects.Add(prefabObject); } @@ -305,7 +316,7 @@ CreateAssetResult ImportModel::Import(CreateAssetContext& context) auto& animation = data->Animations[i]; splitOptions.Type = ModelTool::ModelType::Animation; splitOptions.ObjectIndex = i; - splitImport(splitOptions, animation.Name, prefabObject.AssetPath); + splitImport(splitOptions, animation.Name, prefabObject.AssetPath, MeshData()); } } else if (options.SplitObjects) From 31adfd2c9cfe50276e19fe658a27a6934a2d323c Mon Sep 17 00:00:00 2001 From: Menotdan <32620310+Menotdan@users.noreply.github.com> Date: Tue, 2 Jan 2024 04:27:35 -0500 Subject: [PATCH 05/11] Attempt to fix builds on unix. --- Source/Engine/ContentImporters/ImportModel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Engine/ContentImporters/ImportModel.cpp b/Source/Engine/ContentImporters/ImportModel.cpp index 08c9e707f..c034bbc0e 100644 --- a/Source/Engine/ContentImporters/ImportModel.cpp +++ b/Source/Engine/ContentImporters/ImportModel.cpp @@ -316,7 +316,7 @@ CreateAssetResult ImportModel::Import(CreateAssetContext& context) auto& animation = data->Animations[i]; splitOptions.Type = ModelTool::ModelType::Animation; splitOptions.ObjectIndex = i; - splitImport(splitOptions, animation.Name, prefabObject.AssetPath, MeshData()); + splitImport(splitOptions, animation.Name, prefabObject.AssetPath, MeshData::MeshData()); } } else if (options.SplitObjects) From 6178cb1bf4f014b09ae339650597885957dd2cca Mon Sep 17 00:00:00 2001 From: Menotdan <32620310+Menotdan@users.noreply.github.com> Date: Tue, 2 Jan 2024 12:36:17 -0500 Subject: [PATCH 06/11] attempt 2 at fixing the build regression. --- Source/Engine/ContentImporters/ImportModel.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Source/Engine/ContentImporters/ImportModel.cpp b/Source/Engine/ContentImporters/ImportModel.cpp index c034bbc0e..67479db24 100644 --- a/Source/Engine/ContentImporters/ImportModel.cpp +++ b/Source/Engine/ContentImporters/ImportModel.cpp @@ -316,7 +316,9 @@ CreateAssetResult ImportModel::Import(CreateAssetContext& context) auto& animation = data->Animations[i]; splitOptions.Type = ModelTool::ModelType::Animation; splitOptions.ObjectIndex = i; - splitImport(splitOptions, animation.Name, prefabObject.AssetPath, MeshData::MeshData()); + + MeshData empty; + splitImport(splitOptions, animation.Name, prefabObject.AssetPath, empty); } } else if (options.SplitObjects) From 1b9984c728088320e7b63fd36d304080f4cc56d1 Mon Sep 17 00:00:00 2001 From: Menotdan <32620310+Menotdan@users.noreply.github.com> Date: Wed, 3 Jan 2024 20:16:57 -0500 Subject: [PATCH 07/11] Fix static import of GLTF (and presumably other assimp) model types. --- Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp b/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp index e62d03b1c..c67a48705 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp +++ b/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp @@ -790,6 +790,7 @@ bool ModelTool::ImportDataAssimp(const char* path, ModelData& data, Options& opt aiProcess_GenUVCoords | aiProcess_FindDegenerates | aiProcess_FindInvalidData | + aiProcess_GlobalScale | //aiProcess_ValidateDataStructure | aiProcess_ConvertToLeftHanded; if (importMeshes) @@ -807,6 +808,7 @@ bool ModelTool::ImportDataAssimp(const char* path, ModelData& data, Options& opt // Setup import options context.AssimpImporter.SetPropertyFloat(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE, options.SmoothingNormalsAngle); context.AssimpImporter.SetPropertyFloat(AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE, options.SmoothingTangentsAngle); + context.AssimpImporter.SetPropertyFloat(AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY, 100.0f); // Convert to cm? //context.AssimpImporter.SetPropertyInteger(AI_CONFIG_PP_SLM_TRIANGLE_LIMIT, MAX_uint16); context.AssimpImporter.SetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_CAMERAS, false); context.AssimpImporter.SetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_LIGHTS, false); From 7d07ed20ea1b8a04d21956e112e15dea1aecfa84 Mon Sep 17 00:00:00 2001 From: Menotdan <32620310+Menotdan@users.noreply.github.com> Date: Wed, 3 Jan 2024 22:20:59 -0500 Subject: [PATCH 08/11] major improvements --- .../Tools/ModelTool/ModelTool.Assimp.cpp | 74 ++++++------------- Source/Engine/Tools/ModelTool/ModelTool.cpp | 23 ++++-- 2 files changed, 39 insertions(+), 58 deletions(-) diff --git a/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp b/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp index c67a48705..6041cbb4f 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp +++ b/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp @@ -484,6 +484,26 @@ bool ProcessMesh(ModelData& result, AssimpImporterData& data, const aiMesh* aMes } } + AssimpNode* curNode = &data.Nodes[mesh.NodeIndex]; + Vector3 translation = Vector3::Zero; + Vector3 scale = Vector3::One; + Quaternion rotation = Quaternion::Identity; + + while(true) + { + translation += curNode->LocalTransform.Translation; + scale *= curNode->LocalTransform.Scale; + rotation *= curNode->LocalTransform.Orientation; + + if (curNode->ParentIndex == -1) + break; + curNode = &data.Nodes[curNode->ParentIndex]; + } + + mesh.OriginTranslation = translation; + mesh.OriginOrientation = rotation; + mesh.Scaling = scale; + return false; } @@ -624,6 +644,7 @@ bool ImportMesh(int32 index, ModelData& result, AssimpImporterData& data, String // Import mesh data MeshData* meshData = New(); + meshData->NodeIndex = data.MeshIndexToNodeIndex[index][0]; if (ProcessMesh(result, data, aMesh, *meshData, errorMsg)) { Delete(meshData); @@ -650,59 +671,6 @@ bool ImportMesh(int32 index, ModelData& result, AssimpImporterData& data, String result.LODs[lodIndex].Meshes.Add(meshData); } - auto root = data.Scene->mRootNode; - Array points; - if (root->mNumChildren == 0) - { - aiQuaternion aiQuat; - aiVector3D aiPos; - aiVector3D aiScale; - root->mTransformation.Decompose(aiScale, aiQuat, aiPos); - auto quat = ToQuaternion(aiQuat); - auto pos = ToFloat3(aiPos); - auto scale = ToFloat3(aiScale); - Transform trans = Transform(pos, quat, scale); - points.Add(trans); - } - else - { - for (unsigned int j = 0; j < root->mNumChildren; j++) - { - aiQuaternion aiQuat; - aiVector3D aiPos; - aiVector3D aiScale; - root->mChildren[j]->mTransformation.Decompose(aiScale, aiQuat, aiPos); - auto quat = ToQuaternion(aiQuat); - auto pos = ToFloat3(aiPos); - auto scale = ToFloat3(aiScale); - Transform trans = Transform(pos, quat, scale); - points.Add(trans); - } - } - - Float3 translation = Float3::Zero; - Float3 scale = Float3::Zero; - Quaternion orientation = Quaternion::Identity; - for (auto point : points) - { - translation += point.Translation; - scale += point.Scale; - orientation *= point.Orientation; - } - - if (points.Count() > 0) - { - meshData->OriginTranslation = translation / (float)points.Count(); - meshData->OriginOrientation = Quaternion::Invert(orientation); - meshData->Scaling = scale / (float)points.Count(); - } - else - { - meshData->OriginTranslation = translation; - meshData->OriginOrientation = Quaternion::Invert(orientation); - meshData->Scaling = Float3(1); - } - return false; } diff --git a/Source/Engine/Tools/ModelTool/ModelTool.cpp b/Source/Engine/Tools/ModelTool/ModelTool.cpp index 899f67a1f..8d5db063f 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.cpp +++ b/Source/Engine/Tools/ModelTool/ModelTool.cpp @@ -1333,13 +1333,26 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option auto& mesh = *data.LODs[lodIndex].Meshes[meshIndex]; auto& node = data.Nodes[mesh.NodeIndex]; + auto currentNode = &data.Nodes[mesh.NodeIndex]; + + Vector3 scale = Vector3::One; + Quaternion rotation = Quaternion::Identity; + while (true) + { + scale *= currentNode->LocalTransform.Scale; + rotation *= currentNode->LocalTransform.Orientation; + + if (currentNode->ParentIndex == -1) + { + break; + } + currentNode = &data.Nodes[currentNode->ParentIndex]; + } + // Transform vertices auto transformationMatrix = Matrix::Identity; - transformationMatrix.SetScaleVector(node.LocalTransform.Scale); - - Matrix rotation; - node.LocalTransform.GetRotation(rotation); - transformationMatrix = transformationMatrix * rotation; + transformationMatrix.SetScaleVector(scale); + transformationMatrix = transformationMatrix * Matrix::RotationQuaternion(rotation); if (!transformationMatrix.IsIdentity()) mesh.TransformBuffer(transformationMatrix); From 35832e5b1c55e6075484645f245490a229af5629 Mon Sep 17 00:00:00 2001 From: Menotdan <32620310+Menotdan@users.noreply.github.com> Date: Thu, 4 Jan 2024 00:57:20 -0500 Subject: [PATCH 09/11] Proper fix now? --- .../Engine/ContentImporters/ImportModel.cpp | 41 ++++++++++++++++++- .../Tools/ModelTool/ModelTool.Assimp.cpp | 6 +-- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/Source/Engine/ContentImporters/ImportModel.cpp b/Source/Engine/ContentImporters/ImportModel.cpp index 67479db24..cf66762ad 100644 --- a/Source/Engine/ContentImporters/ImportModel.cpp +++ b/Source/Engine/ContentImporters/ImportModel.cpp @@ -287,7 +287,23 @@ CreateAssetResult ImportModel::Import(CreateAssetContext& context) splitOptions.UseLocalOrigin = false; // This properly sets the transformation of the mesh during reimport. - splitOptions.Translation = meshData.OriginTranslation * -1.0f; + auto* nodes = &splitOptions.Cached->Data->Nodes; + Vector3 scale = Vector3::One; + + // TODO: Improve this hack. + // This is the same hack as in ImportModel::CreatePrefab(), and it is documented further there. + auto* currentNode = &(*nodes)[meshData.NodeIndex]; + while (true) + { + if (currentNode->ParentIndex == -1) + { + scale *= currentNode->LocalTransform.Scale; + break; + } + currentNode = &(*nodes)[currentNode->ParentIndex]; + } + + splitOptions.Translation = meshData.OriginTranslation * scale * -1.0f; } return AssetsImportingManager::Import(context.InputPath, outputPath, &splitOptions); @@ -682,9 +698,30 @@ CreateAssetResult ImportModel::CreatePrefab(CreateAssetContext& context, ModelDa // When use local origin is checked, it shifts everything over the same amount, including the root. This tries to work around that. if (!(nodeIndex == 0 && options.UseLocalOrigin)) { + // TODO: Improve this hack. + // Assimp importer has the meter -> centimeter conversion scale applied to the local transform of + // the root node, and only the root node. The OpenFBX importer has the same scale applied + // to each node, *except* the root node. This difference makes it hard to calculate the + // global scale properly. Position offsets are not calculated properly from Assimp without summing up + // the global scale because translations from Assimp don't get scaled with the global scaler option, + // but the OpenFBX importer does scale them. So this hack will end up only applying the global scale + // change if its using Assimp due to the difference in where the nodes' local transform scales are set. + auto* currentNode = &node; + Vector3 scale = Vector3::One; + while (true) + { + if (currentNode->ParentIndex == -1) + { + scale *= currentNode->LocalTransform.Scale; + break; + } + currentNode = &data.Nodes[currentNode->ParentIndex]; + } + // Only set translation, since scale and rotation is applied earlier. Transform positionOffset = Transform::Identity; - positionOffset.Translation = node.LocalTransform.Translation; + positionOffset.Translation = node.LocalTransform.Translation * scale; + if (options.UseLocalOrigin) { positionOffset.Translation += data.Nodes[0].LocalTransform.Translation; diff --git a/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp b/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp index 6041cbb4f..8ce3cc0d0 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp +++ b/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp @@ -797,14 +797,14 @@ bool ModelTool::ImportDataAssimp(const char* path, ModelData& data, Options& opt } // Create root node - AssimpNode& rootNode = context.Nodes.AddOne(); + /*AssimpNode& rootNode = context.Nodes.AddOne(); rootNode.ParentIndex = -1; rootNode.LodIndex = 0; - rootNode.Name = TEXT("Root"); rootNode.LocalTransform = Transform::Identity; + rootNode.Name = TEXT("Root");*/ // Process imported scene nodes - ProcessNodes(context, context.Scene->mRootNode, 0); + ProcessNodes(context, context.Scene->mRootNode, -1); // Import materials if (ImportMaterials(data, context, errorMsg)) From 7e948de2db4c65e08c20aa03a96bbfaf138ace52 Mon Sep 17 00:00:00 2001 From: Menotdan <32620310+Menotdan@users.noreply.github.com> Date: Thu, 4 Jan 2024 15:29:23 -0500 Subject: [PATCH 10/11] Handle multiple nodes having the same mesh (probably?) --- .../Tools/ModelTool/ModelTool.Assimp.cpp | 42 +++++++++---------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp b/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp index 8ce3cc0d0..85e320ee6 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp +++ b/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp @@ -483,27 +483,6 @@ bool ProcessMesh(ModelData& result, AssimpImporterData& data, const aiMesh* aMes } } } - - AssimpNode* curNode = &data.Nodes[mesh.NodeIndex]; - Vector3 translation = Vector3::Zero; - Vector3 scale = Vector3::One; - Quaternion rotation = Quaternion::Identity; - - while(true) - { - translation += curNode->LocalTransform.Translation; - scale *= curNode->LocalTransform.Scale; - rotation *= curNode->LocalTransform.Orientation; - - if (curNode->ParentIndex == -1) - break; - curNode = &data.Nodes[curNode->ParentIndex]; - } - - mesh.OriginTranslation = translation; - mesh.OriginOrientation = rotation; - mesh.Scaling = scale; - return false; } @@ -644,7 +623,6 @@ bool ImportMesh(int32 index, ModelData& result, AssimpImporterData& data, String // Import mesh data MeshData* meshData = New(); - meshData->NodeIndex = data.MeshIndexToNodeIndex[index][0]; if (ProcessMesh(result, data, aMesh, *meshData, errorMsg)) { Delete(meshData); @@ -666,6 +644,26 @@ bool ImportMesh(int32 index, ModelData& result, AssimpImporterData& data, String // Link mesh meshData->NodeIndex = nodeIndex; + AssimpNode* curNode = &data.Nodes[meshData->NodeIndex]; + Vector3 translation = Vector3::Zero; + Vector3 scale = Vector3::One; + Quaternion rotation = Quaternion::Identity; + + while (true) + { + translation += curNode->LocalTransform.Translation; + scale *= curNode->LocalTransform.Scale; + rotation *= curNode->LocalTransform.Orientation; + + if (curNode->ParentIndex == -1) + break; + curNode = &data.Nodes[curNode->ParentIndex]; + } + + meshData->OriginTranslation = translation; + meshData->OriginOrientation = rotation; + meshData->Scaling = scale; + if (result.LODs.Count() <= lodIndex) result.LODs.Resize(lodIndex + 1); result.LODs[lodIndex].Meshes.Add(meshData); From 9c9aabcae332af99ff4dac61b877562ffd338571 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 20 Feb 2024 10:49:45 +0100 Subject: [PATCH 11/11] Minor tweaks to #2147 --- .../Engine/ContentImporters/ImportModel.cpp | 22 +++++++++---------- .../Tools/ModelTool/ModelTool.Assimp.cpp | 2 +- Source/Engine/Tools/ModelTool/ModelTool.cpp | 8 ++----- 3 files changed, 13 insertions(+), 19 deletions(-) diff --git a/Source/Engine/ContentImporters/ImportModel.cpp b/Source/Engine/ContentImporters/ImportModel.cpp index cf66762ad..190b4ba41 100644 --- a/Source/Engine/ContentImporters/ImportModel.cpp +++ b/Source/Engine/ContentImporters/ImportModel.cpp @@ -269,7 +269,7 @@ CreateAssetResult ImportModel::Import(CreateAssetContext& context) // Import all of the objects recursive but use current model data to skip loading file again options.Cached = &cached; - Function splitImport = [&context, &autoImportOutput](Options& splitOptions, const StringView& objectName, String& outputPath, MeshData& meshData) + Function splitImport = [&context, &autoImportOutput](Options& splitOptions, const StringView& objectName, String& outputPath, MeshData* meshData) { // Recursive importing of the split object String postFix = objectName; @@ -280,19 +280,19 @@ CreateAssetResult ImportModel::Import(CreateAssetContext& context) outputPath = autoImportOutput / String(StringUtils::GetFileNameWithoutExtension(context.TargetAssetPath)) + TEXT(" ") + postFix + TEXT(".flax"); splitOptions.SubAssetFolder = TEXT(" "); // Use the same folder as asset as they all are imported to the subdir for the prefab (see SubAssetFolder usage above) - if (splitOptions.Type == ModelTool::ModelType::Model) + if (splitOptions.Type == ModelTool::ModelType::Model && meshData) { - // These settings interfere with submesh reimporting. + // These settings interfere with submesh reimporting splitOptions.CenterGeometry = false; splitOptions.UseLocalOrigin = false; - // This properly sets the transformation of the mesh during reimport. + // This properly sets the transformation of the mesh during reimport auto* nodes = &splitOptions.Cached->Data->Nodes; Vector3 scale = Vector3::One; // TODO: Improve this hack. - // This is the same hack as in ImportModel::CreatePrefab(), and it is documented further there. - auto* currentNode = &(*nodes)[meshData.NodeIndex]; + // This is the same hack as in ImportModel::CreatePrefab(), and it is documented further there + auto* currentNode = &(*nodes)[meshData->NodeIndex]; while (true) { if (currentNode->ParentIndex == -1) @@ -303,7 +303,7 @@ CreateAssetResult ImportModel::Import(CreateAssetContext& context) currentNode = &(*nodes)[currentNode->ParentIndex]; } - splitOptions.Translation = meshData.OriginTranslation * scale * -1.0f; + splitOptions.Translation = meshData->OriginTranslation * scale * -1.0f; } return AssetsImportingManager::Import(context.InputPath, outputPath, &splitOptions); @@ -321,7 +321,7 @@ CreateAssetResult ImportModel::Import(CreateAssetContext& context) splitOptions.Type = ModelTool::ModelType::Model; splitOptions.ObjectIndex = groupIndex; - if (!splitImport(splitOptions, group.GetKey(), prefabObject.AssetPath, *group.First())) + if (!splitImport(splitOptions, group.GetKey(), prefabObject.AssetPath, group.First())) { prefabObjects.Add(prefabObject); } @@ -332,9 +332,7 @@ CreateAssetResult ImportModel::Import(CreateAssetContext& context) auto& animation = data->Animations[i]; splitOptions.Type = ModelTool::ModelType::Animation; splitOptions.ObjectIndex = i; - - MeshData empty; - splitImport(splitOptions, animation.Name, prefabObject.AssetPath, empty); + splitImport(splitOptions, animation.Name, prefabObject.AssetPath, nullptr); } } else if (options.SplitObjects) @@ -390,7 +388,7 @@ CreateAssetResult ImportModel::Import(CreateAssetContext& context) auto& group = meshesByName[options.ObjectIndex]; if (&dataThis == data) { - // Use meshes only from the the grouping (others will be removed manually) + // Use meshes only from the grouping (others will be removed manually) { auto& lod = dataThis.LODs[0]; meshesToDelete.Add(lod.Meshes); diff --git a/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp b/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp index 85e320ee6..8b47b21dd 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp +++ b/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp @@ -774,7 +774,7 @@ bool ModelTool::ImportDataAssimp(const char* path, ModelData& data, Options& opt // Setup import options context.AssimpImporter.SetPropertyFloat(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE, options.SmoothingNormalsAngle); context.AssimpImporter.SetPropertyFloat(AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE, options.SmoothingTangentsAngle); - context.AssimpImporter.SetPropertyFloat(AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY, 100.0f); // Convert to cm? + context.AssimpImporter.SetPropertyFloat(AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY, 100.0f); // Convert to cm //context.AssimpImporter.SetPropertyInteger(AI_CONFIG_PP_SLM_TRIANGLE_LIMIT, MAX_uint16); context.AssimpImporter.SetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_CAMERAS, false); context.AssimpImporter.SetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_LIGHTS, false); diff --git a/Source/Engine/Tools/ModelTool/ModelTool.cpp b/Source/Engine/Tools/ModelTool/ModelTool.cpp index a8cb0ecd8..74cbfbb52 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.cpp +++ b/Source/Engine/Tools/ModelTool/ModelTool.cpp @@ -1320,7 +1320,7 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option ! #endif } - if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Geometry) && !(options.Type == ModelType::Prefab)) + if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Geometry) && options.Type != ModelType::Prefab) { // Perform simple nodes mapping to single node (will transform meshes to model local space) SkeletonMapping skeletonMapping(data.Nodes, nullptr); @@ -1340,7 +1340,7 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option if (skeletonMapping.SourceToSource[mesh.NodeIndex] != mesh.NodeIndex) { // Transform vertices - auto transformationMatrix = hierarchyUpdater.CombineMatricesFromNodeIndices(skeletonMapping.SourceToSource[mesh.NodeIndex], mesh.NodeIndex); + const Matrix transformationMatrix = hierarchyUpdater.CombineMatricesFromNodeIndices(skeletonMapping.SourceToSource[mesh.NodeIndex], mesh.NodeIndex); if (!transformationMatrix.IsIdentity()) mesh.TransformBuffer(transformationMatrix); @@ -1360,7 +1360,6 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option { auto& mesh = *data.LODs[lodIndex].Meshes[meshIndex]; auto& node = data.Nodes[mesh.NodeIndex]; - auto currentNode = &data.Nodes[mesh.NodeIndex]; Vector3 scale = Vector3::One; @@ -1369,11 +1368,8 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option { scale *= currentNode->LocalTransform.Scale; rotation *= currentNode->LocalTransform.Orientation; - if (currentNode->ParentIndex == -1) - { break; - } currentNode = &data.Nodes[currentNode->ParentIndex]; }