diff --git a/Gems/Prefab/PrefabBuilder/PrefabGroup/PrefabBehaviorTests.cpp b/Gems/Prefab/PrefabBuilder/PrefabGroup/PrefabBehaviorTests.cpp index 7187bdf081..2642608a6c 100644 --- a/Gems/Prefab/PrefabBuilder/PrefabGroup/PrefabBehaviorTests.cpp +++ b/Gems/Prefab/PrefabBuilder/PrefabGroup/PrefabBehaviorTests.cpp @@ -348,7 +348,7 @@ namespace UnitTest { AZ::SceneAPI::DataTypes::IMeshGroup* meshGroup = reinterpret_cast(scene->GetManifest().GetValue(i).get()); AZStd::string groupName = meshGroup->GetName(); - EXPECT_TRUE(groupName.starts_with("manifest_src_file_xml")); + EXPECT_TRUE(groupName.starts_with("default_mock_")); } } } diff --git a/Gems/Prefab/PrefabBuilder/PrefabGroup/PrefabGroupBehavior.cpp b/Gems/Prefab/PrefabBuilder/PrefabGroup/PrefabGroupBehavior.cpp index 5fce7a674a..751c04952c 100644 --- a/Gems/Prefab/PrefabBuilder/PrefabGroup/PrefabGroupBehavior.cpp +++ b/Gems/Prefab/PrefabBuilder/PrefabGroup/PrefabGroupBehavior.cpp @@ -30,20 +30,21 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include namespace AZStd { @@ -98,6 +99,10 @@ namespace AZ::SceneAPI::Behaviors using MeshTransformPair = AZStd::pair; using MeshTransformEntry = AZStd::pair; using MeshTransformMap = AZStd::unordered_map; + using MeshIndexContainer = AZStd::unordered_set; + using ManifestUpdates = AZStd::vector>; + using NodeEntityMap = AZStd::unordered_map; + using EntityIdList = AZStd::vector; MeshTransformMap CalculateMeshTransformMap(const Containers::Scene& scene) { @@ -108,47 +113,60 @@ namespace AZ::SceneAPI::Behaviors graph.GetContentStorage().cbegin(), true); - if (view.begin() == view.end()) + if (view.empty()) { return {}; } + MeshIndexContainer meshIndexContainer; MeshTransformMap meshTransformMap; for (auto it = view.begin(); it != view.end(); ++it) { Containers::SceneGraph::NodeIndex currentIndex = graph.ConvertToNodeIndex(it.GetHierarchyIterator()); AZStd::string currentNodeName = graph.GetNodeName(currentIndex).GetPath(); - auto currentContent = graph.GetNodeContent(currentIndex); + const auto currentContent = graph.GetNodeContent(currentIndex); if (currentContent) { if (azrtti_istypeof(currentContent.get())) { - auto parentIndex = graph.GetNodeParent(currentIndex); + const auto parentIndex = graph.GetNodeParent(currentIndex); if (parentIndex.IsValid() == false) { continue; } - auto parentContent = graph.GetNodeContent(parentIndex); + const auto parentContent = graph.GetNodeContent(parentIndex); if (parentContent && azrtti_istypeof(parentContent.get())) { // map the node parent to the ITransform + meshIndexContainer.erase(parentIndex); MeshTransformPair pair{ parentIndex, currentIndex }; meshTransformMap.emplace(MeshTransformEntry{ graph.GetNodeParent(parentIndex), AZStd::move(pair) }); } } + else if (azrtti_istypeof(currentContent.get())) + { + meshIndexContainer.insert(currentIndex); + } } } + + // all mesh data nodes left in the meshIndexContainer do not have a matching TransformData node + // since the nodes have an identity transform, so map the MeshData index with an Invalid mesh index to + // indicate the transform should not be set to a default value + for( const auto meshIndex : meshIndexContainer) + { + MeshTransformPair pair{ meshIndex, Containers::SceneGraph::NodeIndex{} }; + meshTransformMap.emplace(MeshTransformEntry{ graph.GetNodeParent(meshIndex), AZStd::move(pair) }); + } + return meshTransformMap; } - using ManifestUpdates = AZStd::vector>; - using NodeEntityMap = AZStd::unordered_map; - NodeEntityMap CreateMeshGroups( ManifestUpdates& manifestUpdates, const MeshTransformMap& meshTransformMap, const Containers::Scene& scene, - AZStd::string& relativeSourcePath) + const AZStd::string& relativeSourcePath) { NodeEntityMap nodeEntityMap; const auto& graph = scene.GetGraph(); @@ -158,15 +176,15 @@ namespace AZ::SceneAPI::Behaviors const auto thisNodeIndex = entry.first; const auto meshNodeIndex = entry.second.first; const auto meshNodeName = graph.GetNodeName(meshNodeIndex); - AZStd::string meshNodePath{ meshNodeName.GetPath() }; - AZStd::string meshNodeFullName; - meshNodeFullName = relativeSourcePath; - meshNodeFullName.append("_"); - meshNodeFullName.append(meshNodeName.GetName()); + AZStd::string meshNodePath{ meshNodeName.GetPath() }; + AZStd::string meshGroupName = "default_"; + meshGroupName += scene.GetName(); + meshGroupName += meshNodePath; + AZ::StringFunc::Replace(meshGroupName, ".", "_"); auto meshGroup = AZStd::make_shared(); - meshGroup->SetName(meshNodeFullName); + meshGroup->SetName(meshGroupName); meshGroup->GetSceneNodeSelectionList().AddSelectedNode(AZStd::move(meshNodePath)); for (const auto& meshGoupNamePair : meshTransformMap) { @@ -190,6 +208,9 @@ namespace AZ::SceneAPI::Behaviors coordinateSystemRule->SetScale(1.0f); meshGroup->GetRuleContainer().AddRule(coordinateSystemRule); + // create an empty LOD rule in order to skip the LOD buffer creation + meshGroup->GetRuleContainer().AddRule(AZStd::make_shared()); + manifestUpdates.emplace_back(meshGroup); // create an entity for each MeshGroup @@ -219,10 +240,15 @@ namespace AZ::SceneAPI::Behaviors } // assign mesh asset id hint using JSON + AZStd::string modelAssetPath; + modelAssetPath = relativeSourcePath; + AZ::StringFunc::Path::ReplaceFullName(modelAssetPath, meshGroupName.c_str()); + AZ::StringFunc::Replace(modelAssetPath, "\\", "/"); // asset paths use forward slashes + auto meshAssetJson = AZStd::string::format( R"JSON( {"Controller": {"Configuration": {"ModelAsset": { "assetHint": "%s.azmodel"}}}} - )JSON", meshNodeFullName.c_str()); + )JSON", modelAssetPath.c_str()); bool result = false; AzToolsFramework::EntityUtilityBus::BroadcastResult( @@ -244,8 +270,6 @@ namespace AZ::SceneAPI::Behaviors return nodeEntityMap; } - using EntityIdList = AZStd::vector; - EntityIdList FixUpEntityParenting( const NodeEntityMap& nodeEntityMap, const Containers::SceneGraph& graph, @@ -303,7 +327,14 @@ namespace AZ::SceneAPI::Behaviors // get node matrix data to set the entity's local transform const auto nodeTransform = azrtti_cast(graph.GetNodeContent(thisTransformIndex)); - entityTransform->SetLocalTM(AZ::Transform::CreateFromMatrix3x4(nodeTransform->GetMatrix())); + if (nodeTransform) + { + entityTransform->SetLocalTM(AZ::Transform::CreateFromMatrix3x4(nodeTransform->GetMatrix())); + } + else + { + entityTransform->SetLocalTM(AZ::Transform::CreateUniformScale(1.0f)); + } } return entities; diff --git a/Gems/SceneProcessing/Code/Source/Generation/Components/MeshOptimizer/MeshOptimizerComponent.cpp b/Gems/SceneProcessing/Code/Source/Generation/Components/MeshOptimizer/MeshOptimizerComponent.cpp index edc0d728fc..eeb3994c76 100644 --- a/Gems/SceneProcessing/Code/Source/Generation/Components/MeshOptimizer/MeshOptimizerComponent.cpp +++ b/Gems/SceneProcessing/Code/Source/Generation/Components/MeshOptimizer/MeshOptimizerComponent.cpp @@ -349,7 +349,10 @@ namespace AZ::SceneGenerationComponents } const AZStd::string name = - AZStd::string(graph.GetNodeName(nodeIndex).GetName(), graph.GetNodeName(nodeIndex).GetNameLength()).append(SceneAPI::Utilities::OptimizedMeshSuffix); + AZStd::string(graph.GetNodeName(nodeIndex).GetName(), graph.GetNodeName(nodeIndex).GetNameLength()) + .append("_") + .append(meshGroup.GetName()) + .append(SceneAPI::Utilities::OptimizedMeshSuffix); if (graph.Find(name).IsValid()) { AZ_TracePrintf(AZ::SceneAPI::Utilities::LogWindow, "Optimized mesh already exists at '%s', there must be multiple mesh groups that have selected this mesh. Skipping the additional ones.", name.c_str()); diff --git a/Gems/SceneProcessing/Code/Source/SceneBuilder/SceneBuilderWorker.cpp b/Gems/SceneProcessing/Code/Source/SceneBuilder/SceneBuilderWorker.cpp index c4300fc34d..8889f41a95 100644 --- a/Gems/SceneProcessing/Code/Source/SceneBuilder/SceneBuilderWorker.cpp +++ b/Gems/SceneProcessing/Code/Source/SceneBuilder/SceneBuilderWorker.cpp @@ -79,7 +79,7 @@ namespace SceneBuilder m_cachedFingerprint.append(element); } // A general catch all version fingerprint. Update this to force all FBX files to recompile. - m_cachedFingerprint.append("Version 2"); + m_cachedFingerprint.append("Version 3"); } return m_cachedFingerprint.c_str(); diff --git a/Gems/SceneProcessing/Code/Tests/MeshBuilder/MeshOptimizerComponentTests.cpp b/Gems/SceneProcessing/Code/Tests/MeshBuilder/MeshOptimizerComponentTests.cpp index d3f4383094..68336bd5de 100644 --- a/Gems/SceneProcessing/Code/Tests/MeshBuilder/MeshOptimizerComponentTests.cpp +++ b/Gems/SceneProcessing/Code/Tests/MeshBuilder/MeshOptimizerComponentTests.cpp @@ -176,7 +176,7 @@ namespace SceneProcessing component.OptimizeMeshes(context); AZ::SceneAPI::Containers::SceneGraph::NodeIndex optimizedNodeIndex = - graph.Find(AZStd::string("testMesh").append(AZ::SceneAPI::Utilities::OptimizedMeshSuffix)); + graph.Find(AZStd::string("testMesh_").append(AZ::SceneAPI::Utilities::OptimizedMeshSuffix)); ASSERT_TRUE(optimizedNodeIndex.IsValid()) << "Mesh optimizer did not add an optimized version of the mesh"; const auto& optimizedMesh = @@ -184,7 +184,7 @@ namespace SceneProcessing ASSERT_TRUE(optimizedMesh); AZ::SceneAPI::Containers::SceneGraph::NodeIndex optimizedSkinDataNodeIndex = - graph.Find(AZStd::string("testMesh").append(AZ::SceneAPI::Utilities::OptimizedMeshSuffix).append(".skinWeights")); + graph.Find(AZStd::string("testMesh_").append(AZ::SceneAPI::Utilities::OptimizedMeshSuffix).append(".skinWeights")); ASSERT_TRUE(optimizedSkinDataNodeIndex.IsValid()) << "Mesh optimizer did not add an optimized version of the skin data"; const auto& optimizedSkinWeights = @@ -227,7 +227,7 @@ namespace SceneProcessing AZ::SceneAPI::Events::GenerateSimplificationEventContext context(scene, "pc"); component.OptimizeMeshes(context); - AZ::SceneAPI::Containers::SceneGraph::NodeIndex optimizedNodeIndex = graph.Find(AZStd::string("testMesh").append(AZ::SceneAPI::Utilities::OptimizedMeshSuffix)); + AZ::SceneAPI::Containers::SceneGraph::NodeIndex optimizedNodeIndex = graph.Find(AZStd::string("testMesh_").append(AZ::SceneAPI::Utilities::OptimizedMeshSuffix)); ASSERT_TRUE(optimizedNodeIndex.IsValid()) << "Mesh optimizer did not add an optimized version of the mesh"; const auto& optimizedMesh = AZStd::rtti_pointer_cast(graph.GetNodeContent(optimizedNodeIndex));