diff --git a/Code/Tools/SceneAPI/SceneData/Tests/GraphData/GraphDataBehaviorTests.cpp b/Code/Tools/SceneAPI/SceneData/Tests/GraphData/GraphDataBehaviorTests.cpp index 9a2a6f7364..bdcf690844 100644 --- a/Code/Tools/SceneAPI/SceneData/Tests/GraphData/GraphDataBehaviorTests.cpp +++ b/Code/Tools/SceneAPI/SceneData/Tests/GraphData/GraphDataBehaviorTests.cpp @@ -94,7 +94,7 @@ namespace AZ tangentData->AppendTangent(AZ::Vector4{0.12f, 0.34f, 0.56f, 0.78f}); tangentData->AppendTangent(AZ::Vector4{0.18f, 0.28f, 0.19f, 0.29f}); tangentData->AppendTangent(AZ::Vector4{0.21f, 0.43f, 0.65f, 0.87f}); - tangentData->SetTangentSpace(AZ::SceneAPI::DataTypes::TangentSpace::EMotionFX); + tangentData->SetTangentSpace(AZ::SceneAPI::DataTypes::TangentSpace::MikkT); tangentData->SetTangentSetIndex(2); return true; } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp index 93744e0a51..aa2ad37647 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp @@ -540,7 +540,9 @@ namespace AZ } else { - AZ_Warning(s_builderName, false, "Found multiple tangent data sets. Only the first will be used."); + AZ_Warning(s_builderName, false, + "Found multiple tangent data sets for mesh '%s'. Only the first will be used.", + content.m_name.GetCStr()); } } else if (azrtti_istypeof(data.get())) @@ -552,7 +554,9 @@ namespace AZ } else { - AZ_Warning(s_builderName, false, "Found multiple bitangent data sets. Only the first will be used."); + AZ_Warning(s_builderName, false, + "Found multiple bitangent data sets for mesh '%s'. Only the first will be used.", + content.m_name.GetCStr()); } } else if (azrtti_istypeof(data.get())) diff --git a/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerateComponent.cpp b/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerateComponent.cpp index e5faf610b3..c1c47e1955 100644 --- a/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerateComponent.cpp +++ b/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerateComponent.cpp @@ -52,11 +52,8 @@ namespace AZ::SceneGenerationComponents } } - - AZStd::vector TangentGenerateComponent::CollectRequiredTangentSpaces(const AZ::SceneAPI::Containers::Scene& scene) const + AZ::SceneAPI::DataTypes::TangentSpace TangentGenerateComponent::GetTangentSpaceFromRule(const AZ::SceneAPI::Containers::Scene& scene) const { - AZStd::vector result; - for (const auto& object : scene.GetManifest().GetValueStorage()) { if (object->RTTI_IsTypeOf(AZ::SceneAPI::DataTypes::IGroup::TYPEINFO_Uuid())) @@ -65,18 +62,14 @@ namespace AZ::SceneGenerationComponents const AZ::SceneAPI::SceneData::TangentsRule* rule = group->GetRuleContainerConst().FindFirstByType().get(); if (rule) { - if (AZStd::find(result.begin(), result.end(), rule->GetTangentSpace()) == result.end()) - { - result.emplace_back(rule->GetTangentSpace()); - } + return rule->GetTangentSpace(); } } } - return result; + return AZ::SceneAPI::DataTypes::TangentSpace::FromSourceScene; } - AZ::SceneAPI::Events::ProcessingResult TangentGenerateComponent::GenerateTangentData(TangentGenerateContext& context) { // Iterate over all graph content and filter out all meshes. @@ -115,17 +108,15 @@ namespace AZ::SceneGenerationComponents return AZ::SceneAPI::Events::ProcessingResult::Success; } - void TangentGenerateComponent::UpdateFbxTangentWValues(AZ::SceneAPI::Containers::SceneGraph& graph, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, const AZ::SceneAPI::DataTypes::IMeshData* meshData) { // Iterate over all UV sets. - AZ::SceneAPI::DataTypes::IMeshVertexUVData* uvData = AZ::SceneAPI::SceneData::TangentsRule::FindUVData(graph, nodeIndex, 0); + AZ::SceneAPI::DataTypes::IMeshVertexUVData* uvData = FindUvData(graph, nodeIndex, 0); size_t uvSetIndex = 0; while (uvData) { - // Get the tangents and bitangents from the source scene. - AZ::SceneAPI::DataTypes::IMeshVertexTangentData* fbxTangentData = AZ::SceneAPI::SceneData::TangentsRule::FindTangentData(graph, nodeIndex, uvSetIndex, AZ::SceneAPI::DataTypes::TangentSpace::FromSourceScene); - AZ::SceneAPI::DataTypes::IMeshVertexBitangentData* fbxBitangentData = AZ::SceneAPI::SceneData::TangentsRule::FindBitangentData(graph, nodeIndex, uvSetIndex, AZ::SceneAPI::DataTypes::TangentSpace::FromSourceScene); + AZ::SceneAPI::DataTypes::IMeshVertexTangentData* fbxTangentData = FindTangentData(graph, nodeIndex, uvSetIndex); + AZ::SceneAPI::DataTypes::IMeshVertexBitangentData* fbxBitangentData = FindBitangentData(graph, nodeIndex, uvSetIndex); if (fbxTangentData && fbxBitangentData) { @@ -163,7 +154,7 @@ namespace AZ::SceneGenerationComponents } // Find the next UV set. - uvData = AZ::SceneAPI::SceneData::TangentsRule::FindUVData(graph, nodeIndex, ++uvSetIndex); + uvData = FindUvData(graph, nodeIndex, ++uvSetIndex); } } @@ -191,148 +182,249 @@ namespace AZ::SceneGenerationComponents AZ::SceneAPI::Containers::SceneGraph& graph = scene.GetGraph(); // Check if we have any UV data, if not, we cannot possibly generate the tangents. - AZ::SceneAPI::DataTypes::IMeshVertexUVData* uvData = AZ::SceneAPI::SceneData::TangentsRule::FindUVData(graph, nodeIndex, 0); - if (!uvData) + const size_t uvSetCount = CalcUvSetCount(graph, nodeIndex); + if (uvSetCount == 0) { - AZ_TracePrintf(AZ::SceneAPI::Utilities::WarningWindow, "We cannot generate tangents for this mesh, as it has no UV coordinates!\n"); + AZ_Warning(AZ::SceneAPI::Utilities::WarningWindow, false, "Cannot generate tangents for this mesh, as it has no UV coordinates.\n"); return true; // No fatal error } - // Check if we had tangents inside the source scene file. - AZ::SceneAPI::DataTypes::IMeshVertexTangentData* fbxTangentData = AZ::SceneAPI::SceneData::TangentsRule::FindTangentData(graph, nodeIndex, 0, AZ::SceneAPI::DataTypes::TangentSpace::FromSourceScene); - AZ::SceneAPI::DataTypes::IMeshVertexBitangentData* fbxBitangentData = AZ::SceneAPI::SceneData::TangentsRule::FindBitangentData(graph, nodeIndex, 0, AZ::SceneAPI::DataTypes::TangentSpace::FromSourceScene); - // Check what tangent spaces we need. - AZStd::vector requiredSpaces = CollectRequiredTangentSpaces(scene); - - // If we have no tangent rules, so if the required spaces is empty. - if (requiredSpaces.empty()) - { - AZ_TracePrintf(AZ::SceneAPI::Utilities::LogWindow, "Mesh '%s' has no tangents rule, assuming MikkT tangent space on UV set 0, using normalized tangents and orthogonal bitangents!\n", scene.GetGraph().GetNodeName(nodeIndex).GetName()); - requiredSpaces.emplace_back(AZ::SceneAPI::DataTypes::TangentSpace::MikkT); - } - - // If all we need is import from the source scene, and we have tangent data from the source scene already, then skip generating. - if ((requiredSpaces.size() == 1 && requiredSpaces[0] == AZ::SceneAPI::DataTypes::TangentSpace::FromSourceScene) && fbxTangentData && fbxBitangentData) - { - return true; - } + const AZ::SceneAPI::DataTypes::TangentSpace ruleTangentSpace = GetTangentSpaceFromRule(scene); // Find all blend shape data under the mesh. We need to generate the tangent and bitangent for blend shape as well. AZStd::vector blendShapes; FindBlendShapes(graph, nodeIndex, blendShapes); - // Generate all the tangent spaces we need. - // Do this for every UV set. + // Generate tangents/bitangents for all uv sets. bool allSuccess = true; - size_t uvSetIndex = 0; - while (uvData) + for (size_t uvSetIndex = 0; uvSetIndex < uvSetCount; ++uvSetIndex) { - for (AZ::SceneAPI::DataTypes::TangentSpace space : requiredSpaces) + AZ::SceneAPI::DataTypes::IMeshVertexUVData* uvData = FindUvData(graph, nodeIndex, uvSetIndex); + if (!uvData) { - switch (space) - { - // If we want Fbx tangents, we don't need to do anything for that. - case AZ::SceneAPI::DataTypes::TangentSpace::FromSourceScene: - { - allSuccess &= true; - } - break; + AZ_Error(AZ::SceneAPI::Utilities::ErrorWindow, false, "Cannot generate tangents for uv set %zu as it cannot be retrieved.\n", uvSetIndex); + continue; + } - // Generate using MikkT space. - case AZ::SceneAPI::DataTypes::TangentSpace::MikkT: - { - allSuccess &= AZ::TangentGeneration::Mesh::MikkT::GenerateTangents( - scene.GetManifest(), graph, nodeIndex, const_cast(meshData), uvSetIndex); - for (AZ::SceneData::GraphData::BlendShapeData* blendShape : blendShapes) - { - allSuccess &= AZ::TangentGeneration::BlendShape::MikkT::GenerateTangents(blendShape, uvSetIndex); - } - } - break; + // Check if we had tangents inside the source scene file. + AZ::SceneAPI::DataTypes::TangentSpace tangentSpace = ruleTangentSpace; + AZ::SceneAPI::DataTypes::IMeshVertexTangentData* tangentData = FindTangentData(graph, nodeIndex, uvSetIndex); + AZ::SceneAPI::DataTypes::IMeshVertexBitangentData* bitangentData = FindBitangentData(graph, nodeIndex, uvSetIndex); - // If we use EMotion FX calculated tangents, we don't need to generate this here. - case AZ::SceneAPI::DataTypes::TangentSpace::EMotionFX: - allSuccess &= true; - break; - - default: + // If all we need is import from the source scene, and we have tangent data from the source scene already, then skip generating. + if ((tangentSpace == AZ::SceneAPI::DataTypes::TangentSpace::FromSourceScene)) + { + if (tangentData && bitangentData) { - AZ_Assert(false, "Unknown tangent space selected (spaceID=%d) for UV set %d, cannot generate tangents!\n", static_cast(space), uvSetIndex); - allSuccess = false; + AZ_TracePrintf(AZ::SceneAPI::Utilities::LogWindow, "Using source scene tangents and bitangents for uv set %zu for mesh '%s'.\n", + uvSetIndex, scene.GetGraph().GetNodeName(nodeIndex).GetName()); + continue; } + else + { + // In case there are no tangents/bitangents while the user selected to use the source ones, default to MikkT. + AZ_Warning(AZ::SceneAPI::Utilities::WarningWindow, false, "Cannot use source scene tangents as there are none in the asset for mesh '%s' for uv set %zu. Defaulting to generating tangents using MikkT.\n", + scene.GetGraph().GetNodeName(nodeIndex).GetName(), uvSetIndex); + tangentSpace = AZ::SceneAPI::DataTypes::TangentSpace::MikkT; } } - // Try to find the next UV set. - uvData = AZ::SceneAPI::SceneData::TangentsRule::FindUVData(graph, nodeIndex, ++uvSetIndex); + if (!tangentData) + { + if (!AZ::SceneGenerationComponents::TangentGenerateComponent::CreateTangentLayer(scene.GetManifest(), nodeIndex, meshData->GetVertexCount(), uvSetIndex, + tangentSpace, graph, &tangentData)) + { + AZ_Error(AZ::SceneAPI::Utilities::ErrorWindow, false, "Failed to create tangents data set for mesh %s for uv set %zu.\n", + scene.GetGraph().GetNodeName(nodeIndex).GetName(), uvSetIndex); + continue; + } + } + if (!bitangentData) + { + if (!AZ::SceneGenerationComponents::TangentGenerateComponent::CreateBitangentLayer(scene.GetManifest(), nodeIndex, meshData->GetVertexCount(), uvSetIndex, + tangentSpace, graph, &bitangentData)) + { + AZ_Error(AZ::SceneAPI::Utilities::ErrorWindow, false, "Failed to create bitangents data set for mesh %s for uv set %zu.\n", + scene.GetGraph().GetNodeName(nodeIndex).GetName(), uvSetIndex); + continue; + } + } + tangentData->SetTangentSpace(tangentSpace); + bitangentData->SetTangentSpace(tangentSpace); + + switch (tangentSpace) + { + // Generate using MikkT space. + case AZ::SceneAPI::DataTypes::TangentSpace::MikkT: + { + allSuccess &= AZ::TangentGeneration::Mesh::MikkT::GenerateTangents(meshData, uvData, tangentData, bitangentData); + + for (AZ::SceneData::GraphData::BlendShapeData* blendShape : blendShapes) + { + allSuccess &= AZ::TangentGeneration::BlendShape::MikkT::GenerateTangents(blendShape, uvSetIndex); + } + } + break; + + default: + { + AZ_Assert(false, "Unknown tangent space selected (spaceID=%d) for UV set %d, cannot generate tangents!\n", static_cast(tangentSpace), uvSetIndex); + allSuccess = false; + } + } } return allSuccess; } - - bool TangentGenerateComponent::CreateTangentBitangentLayers(AZ::SceneAPI::Containers::SceneManifest& manifest, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, size_t numVerts, size_t uvSetIndex, AZ::SceneAPI::DataTypes::TangentSpace tangentSpace, const char* spaceName, AZ::SceneAPI::Containers::SceneGraph& graph, AZ::SceneAPI::DataTypes::IMeshVertexTangentData** outTangentData, AZ::SceneAPI::DataTypes::IMeshVertexBitangentData** outBitangentData) + size_t TangentGenerateComponent::CalcUvSetCount(AZ::SceneAPI::Containers::SceneGraph& graph, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex) const { - *outTangentData = nullptr; - *outBitangentData = nullptr; + const auto nameContentView = AZ::SceneAPI::Containers::Views::MakePairView(graph.GetNameStorage(), graph.GetContentStorage()); + + size_t result = 0; + auto meshChildView = AZ::SceneAPI::Containers::Views::MakeSceneGraphChildView(graph, nodeIndex, nameContentView.begin(), true); + for (auto child = meshChildView.begin(); child != meshChildView.end(); ++child) + { + AZ::SceneAPI::DataTypes::IMeshVertexUVData* data = azrtti_cast(child->second.get()); + if (data) + { + result++; + } + } + + return result; + } + + AZ::SceneAPI::DataTypes::IMeshVertexUVData* TangentGenerateComponent::FindUvData(AZ::SceneAPI::Containers::SceneGraph& graph, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, AZ::u64 uvSet) const + { + const auto nameContentView = AZ::SceneAPI::Containers::Views::MakePairView(graph.GetNameStorage(), graph.GetContentStorage()); + + AZ::u64 uvSetIndex = 0; + auto meshChildView = AZ::SceneAPI::Containers::Views::MakeSceneGraphChildView(graph, nodeIndex, nameContentView.begin(), true); + for (auto child = meshChildView.begin(); child != meshChildView.end(); ++child) + { + AZ::SceneAPI::DataTypes::IMeshVertexUVData* data = azrtti_cast(child->second.get()); + if (data) + { + if (uvSetIndex == uvSet) + { + return data; + } + uvSetIndex++; + } + } + + return nullptr; + } + + AZ::SceneAPI::DataTypes::IMeshVertexTangentData* TangentGenerateComponent::FindTangentData(AZ::SceneAPI::Containers::SceneGraph& graph, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, AZ::u64 setIndex) const + { + const auto nameContentView = AZ::SceneAPI::Containers::Views::MakePairView(graph.GetNameStorage(), graph.GetContentStorage()); + + auto meshChildView = AZ::SceneAPI::Containers::Views::MakeSceneGraphChildView(graph, nodeIndex, nameContentView.begin(), true); + for (auto child = meshChildView.begin(); child != meshChildView.end(); ++child) + { + AZ::SceneAPI::DataTypes::IMeshVertexTangentData* data = azrtti_cast(child->second.get()); + if (data && setIndex == data->GetTangentSetIndex()) + { + return data; + } + } + + return nullptr; + } + + bool TangentGenerateComponent::CreateTangentLayer(AZ::SceneAPI::Containers::SceneManifest& manifest, + const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, + size_t numVerts, + size_t uvSetIndex, + AZ::SceneAPI::DataTypes::TangentSpace tangentSpace, + AZ::SceneAPI::Containers::SceneGraph& graph, + AZ::SceneAPI::DataTypes::IMeshVertexTangentData** outTangentData) + { + *outTangentData = nullptr; - //------------------------------------------------------------- - // Create tangent layer. - //------------------------------------------------------------- AZStd::shared_ptr tangentData = AZStd::make_shared(); tangentData->Resize(numVerts); AZ_Assert(tangentData, "Failed to allocate tangent data for scene graph."); if (!tangentData) { - AZ_TracePrintf(AZ::SceneAPI::Utilities::ErrorWindow, "Failed to allocate tangent data.\n"); + AZ_Error(AZ::SceneAPI::Utilities::ErrorWindow, false, "Failed to allocate tangent data.\n"); return false; } tangentData->SetTangentSetIndex(uvSetIndex); tangentData->SetTangentSpace(tangentSpace); - const AZStd::string tangentGeneratedName = AZStd::string::format("TangentSet_%s_%zu", spaceName, uvSetIndex); + const AZStd::string tangentGeneratedName = AZStd::string::format("TangentSet_%zu", uvSetIndex); const AZStd::string tangentSetName = AZ::SceneAPI::DataTypes::Utilities::CreateUniqueName(tangentGeneratedName, manifest); AZ::SceneAPI::Containers::SceneGraph::NodeIndex newIndex = graph.AddChild(nodeIndex, tangentSetName.c_str(), tangentData); AZ_Assert(newIndex.IsValid(), "Failed to create SceneGraph node for tangent attribute."); if (!newIndex.IsValid()) { - AZ_TracePrintf(AZ::SceneAPI::Utilities::ErrorWindow, "Failed to create node in scene graph that stores tangent data.\n"); + AZ_Error(AZ::SceneAPI::Utilities::ErrorWindow, false, "Failed to create node in scene graph that stores tangent data.\n"); return false; } graph.MakeEndPoint(newIndex); - //------------------------------------------------------------- - // Create bitangent layer. - //------------------------------------------------------------- + *outTangentData = tangentData.get(); + return true; + } + + AZ::SceneAPI::DataTypes::IMeshVertexBitangentData* TangentGenerateComponent::FindBitangentData(AZ::SceneAPI::Containers::SceneGraph& graph, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, AZ::u64 setIndex) const + { + const auto nameContentView = AZ::SceneAPI::Containers::Views::MakePairView(graph.GetNameStorage(), graph.GetContentStorage()); + + auto meshChildView = AZ::SceneAPI::Containers::Views::MakeSceneGraphChildView(graph, nodeIndex, nameContentView.begin(), true); + for (auto child = meshChildView.begin(); child != meshChildView.end(); ++child) + { + AZ::SceneAPI::DataTypes::IMeshVertexBitangentData* data = azrtti_cast(child->second.get()); + if (data && setIndex == data->GetBitangentSetIndex()) + { + return data; + } + } + + return nullptr; + } + + bool TangentGenerateComponent::CreateBitangentLayer(AZ::SceneAPI::Containers::SceneManifest& manifest, + const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, + size_t numVerts, + size_t uvSetIndex, + AZ::SceneAPI::DataTypes::TangentSpace tangentSpace, + AZ::SceneAPI::Containers::SceneGraph& graph, + AZ::SceneAPI::DataTypes::IMeshVertexBitangentData** outBitangentData) + { + *outBitangentData = nullptr; + AZStd::shared_ptr bitangentData = AZStd::make_shared(); bitangentData->Resize(numVerts); AZ_Assert(bitangentData, "Failed to allocate bitangent data for scene graph."); if (!bitangentData) { - AZ_TracePrintf(AZ::SceneAPI::Utilities::ErrorWindow, "Failed to allocate bitangent data.\n"); + AZ_Error(AZ::SceneAPI::Utilities::ErrorWindow, false, "Failed to allocate bitangent data.\n"); return false; } bitangentData->SetBitangentSetIndex(uvSetIndex); bitangentData->SetTangentSpace(tangentSpace); - const AZStd::string bitangentGeneratedName = AZStd::string::format("BitangentSet_%s_%zu", spaceName, uvSetIndex); + const AZStd::string bitangentGeneratedName = AZStd::string::format("BitangentSet_%zu", uvSetIndex); const AZStd::string bitangentSetName = AZ::SceneAPI::DataTypes::Utilities::CreateUniqueName(bitangentGeneratedName, manifest); - newIndex = graph.AddChild(nodeIndex, bitangentSetName.c_str(), bitangentData); + AZ::SceneAPI::Containers::SceneGraph::NodeIndex newIndex = graph.AddChild(nodeIndex, bitangentSetName.c_str(), bitangentData); AZ_Assert(newIndex.IsValid(), "Failed to create SceneGraph node for bitangent attribute."); if (!newIndex.IsValid()) { - AZ_TracePrintf(AZ::SceneAPI::Utilities::ErrorWindow, "Failed to create node in scene graph that stores bitangent data.\n"); + AZ_Error(AZ::SceneAPI::Utilities::ErrorWindow, false, "Failed to create node in scene graph that stores bitangent data.\n"); return false; } graph.MakeEndPoint(newIndex); - *outTangentData = tangentData.get(); - *outBitangentData = bitangentData.get(); + *outBitangentData = bitangentData.get(); return true; } } // namespace AZ::SceneGenerationComponents diff --git a/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerateComponent.h b/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerateComponent.h index a720c3a191..06d9aded11 100644 --- a/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerateComponent.h +++ b/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerateComponent.h @@ -50,8 +50,6 @@ namespace AZ::SceneGenerationComponents TangentGenerateComponent(); static void Reflect(AZ::ReflectContext* context); - static bool CreateTangentBitangentLayers(AZ::SceneAPI::Containers::SceneManifest& manifest, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, size_t numVerts, size_t uvSetIndex, AZ::SceneAPI::DataTypes::TangentSpace tangentSpace, - const char* spaceName, AZ::SceneAPI::Containers::SceneGraph& graph, AZ::SceneAPI::DataTypes::IMeshVertexTangentData** outTangentData, AZ::SceneAPI::DataTypes::IMeshVertexBitangentData** outBitangentData); AZ::SceneAPI::Events::ProcessingResult GenerateTangentData(TangentGenerateContext& context); @@ -61,6 +59,27 @@ namespace AZ::SceneGenerationComponents AZStd::vector& outBlendShapes) const; bool GenerateTangentsForMesh(AZ::SceneAPI::Containers::Scene& scene, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, AZ::SceneAPI::DataTypes::IMeshData* meshData); void UpdateFbxTangentWValues(AZ::SceneAPI::Containers::SceneGraph& graph, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, const AZ::SceneAPI::DataTypes::IMeshData* meshData); - AZStd::vector CollectRequiredTangentSpaces(const AZ::SceneAPI::Containers::Scene& scene) const; + AZ::SceneAPI::DataTypes::TangentSpace GetTangentSpaceFromRule(const AZ::SceneAPI::Containers::Scene& scene) const; + + size_t CalcUvSetCount(AZ::SceneAPI::Containers::SceneGraph& graph, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex) const; + AZ::SceneAPI::DataTypes::IMeshVertexUVData* FindUvData(AZ::SceneAPI::Containers::SceneGraph& graph, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, AZ::u64 uvSet) const; + + AZ::SceneAPI::DataTypes::IMeshVertexTangentData* FindTangentData(AZ::SceneAPI::Containers::SceneGraph& graph, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, AZ::u64 setIndex) const; + bool CreateTangentLayer(AZ::SceneAPI::Containers::SceneManifest& manifest, + const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, + size_t numVerts, + size_t uvSetIndex, + AZ::SceneAPI::DataTypes::TangentSpace tangentSpace, + AZ::SceneAPI::Containers::SceneGraph& graph, + AZ::SceneAPI::DataTypes::IMeshVertexTangentData** outTangentData); + + AZ::SceneAPI::DataTypes::IMeshVertexBitangentData* FindBitangentData(AZ::SceneAPI::Containers::SceneGraph& graph, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, AZ::u64 setIndex) const; + bool CreateBitangentLayer(AZ::SceneAPI::Containers::SceneManifest& manifest, + const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, + size_t numVerts, + size_t uvSetIndex, + AZ::SceneAPI::DataTypes::TangentSpace tangentSpace, + AZ::SceneAPI::Containers::SceneGraph& graph, + AZ::SceneAPI::DataTypes::IMeshVertexBitangentData** outBitangentData); }; } // namespace AZ::SceneGenerationComponents