From 2b89d9d563d584d46e9a13f4898243557f21fa3f Mon Sep 17 00:00:00 2001 From: Benjamin Jillich Date: Tue, 20 Jul 2021 16:25:42 +0200 Subject: [PATCH 1/4] MikkT generator fills given tangent data rather than creating a new scene node Signed-off-by: Benjamin Jillich --- .../TangentGenerators/MikkTGenerator.cpp | 36 ++++--------------- .../TangentGenerators/MikkTGenerator.h | 14 ++++---- 2 files changed, 15 insertions(+), 35 deletions(-) diff --git a/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerators/MikkTGenerator.cpp b/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerators/MikkTGenerator.cpp index a6191e3b36..3f736815e5 100644 --- a/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerators/MikkTGenerator.cpp +++ b/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerators/MikkTGenerator.cpp @@ -32,7 +32,6 @@ namespace AZ::TangentGeneration::Mesh::MikkT return customData->m_meshData->GetFaceCount(); } - int GetNumVerticesOfFace(const SMikkTSpaceContext* context, const int face) { AZ_UNUSED(context); @@ -40,7 +39,6 @@ namespace AZ::TangentGeneration::Mesh::MikkT return 3; } - void GetPosition(const SMikkTSpaceContext* context, float posOut[], const int face, const int vert) { MikktCustomData* customData = static_cast(context->m_pUserData); @@ -51,7 +49,6 @@ namespace AZ::TangentGeneration::Mesh::MikkT posOut[2] = pos.GetZ(); } - void GetNormal(const SMikkTSpaceContext* context, float normOut[], const int face, const int vert) { MikktCustomData* customData = static_cast(context->m_pUserData); @@ -62,7 +59,6 @@ namespace AZ::TangentGeneration::Mesh::MikkT normOut[2] = normal.GetZ(); } - void GetTexCoord(const SMikkTSpaceContext* context, float texOut[], const int face, const int vert) { MikktCustomData* customData = static_cast(context->m_pUserData); @@ -72,7 +68,6 @@ namespace AZ::TangentGeneration::Mesh::MikkT texOut[1] = uv.GetY(); } - // This function is used to return the tangent and signValue to the application. // tangent is a unit length vector. // For normal maps it is sufficient to use the following simplified version of the bitangent which is generated at pixel/vertex level. @@ -91,7 +86,6 @@ namespace AZ::TangentGeneration::Mesh::MikkT customData->m_bitangentData->SetBitangent(vertexIndex, bitangent); } - // This function is used to return tangent space results to the application. // tangent and bitangent are unit length vectors and magS and magT are their // true magnitudes which can be used for relief mapping effects. @@ -111,27 +105,11 @@ namespace AZ::TangentGeneration::Mesh::MikkT customData->m_bitangentData->SetBitangent(vertexIndex, bitangentVec); } - - bool GenerateTangents(AZ::SceneAPI::Containers::SceneManifest& manifest, AZ::SceneAPI::Containers::SceneGraph& graph, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, AZ::SceneAPI::DataTypes::IMeshData* meshData, size_t uvSet) + bool GenerateTangents(const AZ::SceneAPI::DataTypes::IMeshData* meshData, + const AZ::SceneAPI::DataTypes::IMeshVertexUVData* uvData, + AZ::SceneAPI::DataTypes::IMeshVertexTangentData* outTangentData, + AZ::SceneAPI::DataTypes::IMeshVertexBitangentData* outBitangentData) { - // Create tangent and bitangent data sets and relate them to the given UV set. - AZ::SceneAPI::DataTypes::IMeshVertexUVData* uvData = AZ::SceneAPI::SceneData::TangentsRule::FindUVData(graph, nodeIndex, uvSet); - AZ::SceneAPI::DataTypes::IMeshVertexTangentData* tangentData = nullptr; - AZ::SceneAPI::DataTypes::IMeshVertexBitangentData* bitangentData = nullptr; - if (!uvData) - { - AZ_TracePrintf(AZ::SceneAPI::Utilities::ErrorWindow, "Cannot find UV data (set index=%d) to generate tangents and bitangents from in MikkT generator!\n", uvSet); - return false; - } - - if (!AZ::SceneGenerationComponents::TangentGenerateComponent::CreateTangentBitangentLayers(manifest, nodeIndex, meshData->GetVertexCount(), uvSet, AZ::SceneAPI::DataTypes::TangentSpace::MikkT, "MikkT", graph, &tangentData, &bitangentData)) - { - AZ_TracePrintf(AZ::SceneAPI::Utilities::ErrorWindow, "Failed to create tangents and bitangents data sets inside MikkT generator!\n"); - return false; - } - - //---------------------------------- - // Provide the MikkT interface. SMikkTSpaceInterface mikkInterface; mikkInterface.m_getNumFaces = GetNumFaces; @@ -146,8 +124,8 @@ namespace AZ::TangentGeneration::Mesh::MikkT MikktCustomData customData; customData.m_meshData = meshData; customData.m_uvData = uvData; - customData.m_tangentData = tangentData; - customData.m_bitangentData = bitangentData; + customData.m_tangentData = outTangentData; + customData.m_bitangentData = outBitangentData; // Generate the tangents. SMikkTSpaceContext mikkContext; @@ -155,7 +133,7 @@ namespace AZ::TangentGeneration::Mesh::MikkT mikkContext.m_pUserData = &customData; if (genTangSpaceDefault(&mikkContext) == 0) { - AZ_TracePrintf(AZ::SceneAPI::Utilities::ErrorWindow, "Failed to generate tangents and bitangents using MikkT, because MikkT reported failure!\n"); + AZ_TracePrintf(AZ::SceneAPI::Utilities::ErrorWindow, "Failed to generate tangents and bitangents using MikkT.\n"); return false; } diff --git a/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerators/MikkTGenerator.h b/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerators/MikkTGenerator.h index 98451d3c46..4b1d8ebd72 100644 --- a/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerators/MikkTGenerator.h +++ b/Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerators/MikkTGenerator.h @@ -19,12 +19,14 @@ namespace AZ::TangentGeneration::Mesh::MikkT { struct MikktCustomData { - AZ::SceneAPI::DataTypes::IMeshData* m_meshData; - AZ::SceneAPI::DataTypes::IMeshVertexUVData* m_uvData; - AZ::SceneAPI::DataTypes::IMeshVertexTangentData* m_tangentData; - AZ::SceneAPI::DataTypes::IMeshVertexBitangentData* m_bitangentData; + const AZ::SceneAPI::DataTypes::IMeshData* m_meshData; + const AZ::SceneAPI::DataTypes::IMeshVertexUVData* m_uvData; + AZ::SceneAPI::DataTypes::IMeshVertexTangentData* m_tangentData; + AZ::SceneAPI::DataTypes::IMeshVertexBitangentData* m_bitangentData; }; - // The main generation method. - bool GenerateTangents(AZ::SceneAPI::Containers::SceneManifest& manifest, AZ::SceneAPI::Containers::SceneGraph& graph, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, AZ::SceneAPI::DataTypes::IMeshData* meshData, size_t uvSet); + bool GenerateTangents(const AZ::SceneAPI::DataTypes::IMeshData* meshData, + const AZ::SceneAPI::DataTypes::IMeshVertexUVData* uvData, + AZ::SceneAPI::DataTypes::IMeshVertexTangentData* outTangentData, + AZ::SceneAPI::DataTypes::IMeshVertexBitangentData* outBitangentData); } // namespace AZ::TangentGeneration::MikkT From 424ee5d5e8738a3aad19e897f8239110851da230 Mon Sep 17 00:00:00 2001 From: Benjamin Jillich Date: Tue, 20 Jul 2021 16:26:38 +0200 Subject: [PATCH 2/4] Removed emfx legacy tangent generation settings from tangents rule Signed-off-by: Benjamin Jillich --- .../SceneAPI/SceneData/Rules/TangentsRule.cpp | 117 +----------------- .../SceneAPI/SceneData/Rules/TangentsRule.h | 15 +-- 2 files changed, 3 insertions(+), 129 deletions(-) diff --git a/Code/Tools/SceneAPI/SceneData/Rules/TangentsRule.cpp b/Code/Tools/SceneAPI/SceneData/Rules/TangentsRule.cpp index 0bea5863bf..7b4be1dfdf 100644 --- a/Code/Tools/SceneAPI/SceneData/Rules/TangentsRule.cpp +++ b/Code/Tools/SceneAPI/SceneData/Rules/TangentsRule.cpp @@ -27,114 +27,14 @@ namespace AZ TangentsRule::TangentsRule() : DataTypes::IRule() , m_tangentSpace(AZ::SceneAPI::DataTypes::TangentSpace::MikkT) - , m_bitangentMethod(AZ::SceneAPI::DataTypes::BitangentMethod::Orthogonal) - , m_uvSetIndex(0) - , m_normalize(true) { } - AZ::SceneAPI::DataTypes::TangentSpace TangentsRule::GetTangentSpace() const { return m_tangentSpace; } - - AZ::SceneAPI::DataTypes::BitangentMethod TangentsRule::GetBitangentMethod() const - { - return m_bitangentMethod; - } - - - AZ::u64 TangentsRule::GetUVSetIndex() const - { - return m_uvSetIndex; - } - - - bool TangentsRule::GetNormalizeVectors() const - { - return m_normalize; - } - - - // Find UV data. - AZ::SceneAPI::DataTypes::IMeshVertexUVData* TangentsRule::FindUVData(AZ::SceneAPI::Containers::SceneGraph& graph, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, AZ::u64 uvSet) - { - 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; - } - - - // Find tangent data. - AZ::SceneAPI::DataTypes::IMeshVertexTangentData* TangentsRule::FindTangentData(AZ::SceneAPI::Containers::SceneGraph& graph, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, AZ::u64 setIndex, AZ::SceneAPI::DataTypes::TangentSpace tangentSpace) - { - 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) - { - if (setIndex == data->GetTangentSetIndex() && tangentSpace == data->GetTangentSpace()) - { - return data; - } - } - } - - return nullptr; - } - - - // Find bitangent data. - AZ::SceneAPI::DataTypes::IMeshVertexBitangentData* TangentsRule::FindBitangentData(AZ::SceneAPI::Containers::SceneGraph& graph, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, AZ::u64 setIndex, AZ::SceneAPI::DataTypes::TangentSpace tangentSpace) - { - 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) - { - if (setIndex == data->GetBitangentSetIndex() && tangentSpace == data->GetTangentSpace()) - { - return data; - } - } - } - - return nullptr; - } - - AZ::Crc32 TangentsRule::GetNormalizeVisibility() const - { - return (m_tangentSpace == AZ::SceneAPI::DataTypes::TangentSpace::EMotionFX) ? AZ::Edit::PropertyVisibility::Hide : AZ::Edit::PropertyVisibility::Show; - } - - AZ::Crc32 TangentsRule::GetOrthogonalVisibility() const - { - return (m_tangentSpace == AZ::SceneAPI::DataTypes::TangentSpace::EMotionFX) ? AZ::Edit::PropertyVisibility::Hide : AZ::Edit::PropertyVisibility::Show; - } - void TangentsRule::Reflect(AZ::ReflectContext* context) { AZ::SerializeContext* serializeContext = azrtti_cast(context); @@ -143,11 +43,8 @@ namespace AZ return; } - serializeContext->Class()->Version(2) - ->Field("tangentSpace", &TangentsRule::m_tangentSpace) - ->Field("bitangentMethod", &TangentsRule::m_bitangentMethod) - ->Field("normalize", &TangentsRule::m_normalize) - ->Field("uvSetIndex", &TangentsRule::m_uvSetIndex); + serializeContext->Class()->Version(3) + ->Field("tangentSpace", &TangentsRule::m_tangentSpace); AZ::EditContext* editContext = serializeContext->GetEditContext(); if (editContext) @@ -159,17 +56,7 @@ namespace AZ ->DataElement(AZ::Edit::UIHandlers::ComboBox, &AZ::SceneAPI::SceneData::TangentsRule::m_tangentSpace, "Tangent space", "Specify the tangent space used for normal map baking. Choose 'From Fbx' to extract the tangents and bitangents directly from the Fbx file. When there is no tangents rule or the Fbx has no tangents stored inside it, the 'MikkT' option will be used with orthogonal tangents of unit length, so with the normalize option enabled, using the first UV set.") ->EnumAttribute(AZ::SceneAPI::DataTypes::TangentSpace::FromSourceScene, "From Source Scene") ->EnumAttribute(AZ::SceneAPI::DataTypes::TangentSpace::MikkT, "MikkT") - ->EnumAttribute(AZ::SceneAPI::DataTypes::TangentSpace::EMotionFX, "EMotion FX") ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::EntireTree) - ->DataElement(AZ::Edit::UIHandlers::ComboBox, &AZ::SceneAPI::SceneData::TangentsRule::m_bitangentMethod, "Bitangents", "Set to 'use from tangent space' to use the bitangents generated by the algorithm used or inside the fbx file. This can result in non-orthogonal tangents. Set to 'orthogonal' to skip storing the bitangents and let the engine calculate the bitangents in a way it will be perpendicular to both the normal and tangent.") - ->EnumAttribute(AZ::SceneAPI::DataTypes::BitangentMethod::UseFromTangentSpace, "Use from tangent space") - ->EnumAttribute(AZ::SceneAPI::DataTypes::BitangentMethod::Orthogonal, "Orthogonal") - ->Attribute(AZ::Edit::Attributes::Visibility, &TangentsRule::GetOrthogonalVisibility) - ->DataElement(AZ::Edit::UIHandlers::Default, &TangentsRule::m_uvSetIndex, "Uv set", "The UV set index to generate the tangents from. A value of 0 means the first uv set, while 1 means the second uv set.") - ->Attribute(AZ::Edit::Attributes::Min, 0) - ->Attribute(AZ::Edit::Attributes::Max, 1) - ->DataElement(AZ::Edit::UIHandlers::Default, &TangentsRule::m_normalize, "Normalize", "Normalize the tangents and bitangents? When disabled the vectors might no be unit length, which can be useful for relief mapping.") - ->Attribute(AZ::Edit::Attributes::Visibility, &TangentsRule::GetNormalizeVisibility) ; } } diff --git a/Code/Tools/SceneAPI/SceneData/Rules/TangentsRule.h b/Code/Tools/SceneAPI/SceneData/Rules/TangentsRule.h index 28627cfe0c..b368fce88a 100644 --- a/Code/Tools/SceneAPI/SceneData/Rules/TangentsRule.h +++ b/Code/Tools/SceneAPI/SceneData/Rules/TangentsRule.h @@ -46,24 +46,11 @@ namespace AZ SCENE_DATA_API ~TangentsRule() override = default; SCENE_DATA_API AZ::SceneAPI::DataTypes::TangentSpace GetTangentSpace() const; - SCENE_DATA_API AZ::SceneAPI::DataTypes::BitangentMethod GetBitangentMethod() const; - SCENE_DATA_API AZ::u64 GetUVSetIndex() const; - SCENE_DATA_API bool GetNormalizeVectors() const; - - SCENE_DATA_API static AZ::SceneAPI::DataTypes::IMeshVertexUVData* FindUVData(AZ::SceneAPI::Containers::SceneGraph& graph, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, AZ::u64 uvSet); - SCENE_DATA_API static AZ::SceneAPI::DataTypes::IMeshVertexTangentData* FindTangentData(AZ::SceneAPI::Containers::SceneGraph& graph, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, AZ::u64 setIndex, AZ::SceneAPI::DataTypes::TangentSpace tangentSpace); - SCENE_DATA_API static AZ::SceneAPI::DataTypes::IMeshVertexBitangentData* FindBitangentData(AZ::SceneAPI::Containers::SceneGraph& graph, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, AZ::u64 setIndex, AZ::SceneAPI::DataTypes::TangentSpace tangentSpace); static void Reflect(ReflectContext* context); protected: - AZ::Crc32 GetNormalizeVisibility() const; - AZ::Crc32 GetOrthogonalVisibility() const; - - AZ::SceneAPI::DataTypes::TangentSpace m_tangentSpace; /**< Specifies how to handle tangents. Either generate them, or import them. */ - AZ::SceneAPI::DataTypes::BitangentMethod m_bitangentMethod; /**< Grab the bitangents from the generator/source or use an orthogonal basis by always calculating them? */ - AZ::u64 m_uvSetIndex; /**< Generate the tangents from this UV set. */ - bool m_normalize; /**< Normalize the tangent and bitangents? */ + AZ::SceneAPI::DataTypes::TangentSpace m_tangentSpace; /**< Specifies how to handle tangents. Either generate them, or import them. */ }; } // SceneData } // SceneAPI From fe661bc159fbb8d6759286021e4f081fcca6b41a Mon Sep 17 00:00:00 2001 From: Benjamin Jillich Date: Tue, 20 Jul 2021 16:27:52 +0200 Subject: [PATCH 3/4] Register tangents rule for mesh groups, so users can add it to the scene settings Signed-off-by: Benjamin Jillich --- .../SceneCore/DataTypes/GraphData/IMeshVertexTangentData.h | 3 +-- .../SceneAPI/SceneData/GraphData/MeshVertexBitangentData.cpp | 1 - .../SceneAPI/SceneData/GraphData/MeshVertexTangentData.cpp | 1 - Code/Tools/SceneAPI/SceneData/ManifestMetaInfoHandler.cpp | 5 +++++ 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Code/Tools/SceneAPI/SceneCore/DataTypes/GraphData/IMeshVertexTangentData.h b/Code/Tools/SceneAPI/SceneCore/DataTypes/GraphData/IMeshVertexTangentData.h index 3264bcf45d..ffeeedf9fe 100644 --- a/Code/Tools/SceneAPI/SceneCore/DataTypes/GraphData/IMeshVertexTangentData.h +++ b/Code/Tools/SceneAPI/SceneCore/DataTypes/GraphData/IMeshVertexTangentData.h @@ -25,8 +25,7 @@ namespace AZ enum class TangentSpace { FromSourceScene = 0, - MikkT = 1, - EMotionFX = 2 + MikkT = 1 }; enum class BitangentMethod diff --git a/Code/Tools/SceneAPI/SceneData/GraphData/MeshVertexBitangentData.cpp b/Code/Tools/SceneAPI/SceneData/GraphData/MeshVertexBitangentData.cpp index 183288a470..faa9bf457e 100644 --- a/Code/Tools/SceneAPI/SceneData/GraphData/MeshVertexBitangentData.cpp +++ b/Code/Tools/SceneAPI/SceneData/GraphData/MeshVertexBitangentData.cpp @@ -34,7 +34,6 @@ namespace AZ ->Method("GetBitangent", &MeshVertexBitangentData::GetBitangent) ->Method("GetBitangentSetIndex", &MeshVertexBitangentData::GetBitangentSetIndex) ->Method("GetTangentSpace", &MeshVertexBitangentData::GetTangentSpace) - ->Enum<(int)SceneAPI::DataTypes::TangentSpace::EMotionFX>("EMotionFX") ->Enum<(int)SceneAPI::DataTypes::TangentSpace::FromSourceScene>("FromSourceScene") ->Enum<(int)SceneAPI::DataTypes::TangentSpace::MikkT>("MikkT"); } diff --git a/Code/Tools/SceneAPI/SceneData/GraphData/MeshVertexTangentData.cpp b/Code/Tools/SceneAPI/SceneData/GraphData/MeshVertexTangentData.cpp index 41e8bd9f65..9f27f4eb44 100644 --- a/Code/Tools/SceneAPI/SceneData/GraphData/MeshVertexTangentData.cpp +++ b/Code/Tools/SceneAPI/SceneData/GraphData/MeshVertexTangentData.cpp @@ -34,7 +34,6 @@ namespace AZ ->Method("GetTangent", &MeshVertexTangentData::GetTangent) ->Method("GetTangentSetIndex", &MeshVertexTangentData::GetTangentSetIndex) ->Method("GetTangentSpace", &MeshVertexTangentData::GetTangentSpace) - ->Enum<(int)SceneAPI::DataTypes::TangentSpace::EMotionFX>("EMotionFX") ->Enum<(int)SceneAPI::DataTypes::TangentSpace::FromSourceScene>("FromSourceScene") ->Enum<(int)SceneAPI::DataTypes::TangentSpace::MikkT>("MikkT"); } diff --git a/Code/Tools/SceneAPI/SceneData/ManifestMetaInfoHandler.cpp b/Code/Tools/SceneAPI/SceneData/ManifestMetaInfoHandler.cpp index 760221983e..a135ec5073 100644 --- a/Code/Tools/SceneAPI/SceneData/ManifestMetaInfoHandler.cpp +++ b/Code/Tools/SceneAPI/SceneData/ManifestMetaInfoHandler.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -82,6 +83,10 @@ namespace AZ { modifiers.push_back(azrtti_typeid()); } + if (existingRules.find(SceneData::TangentsRule::TYPEINFO_Uuid()) == existingRules.end()) + { + modifiers.push_back(SceneData::TangentsRule::TYPEINFO_Uuid()); + } } else if (target.RTTI_IsTypeOf(DataTypes::ISkinGroup::TYPEINFO_Uuid())) { From d987c45072e027c88d54af7c14d9d3fb40626d90 Mon Sep 17 00:00:00 2001 From: Benjamin Jillich Date: Tue, 20 Jul 2021 16:32:34 +0200 Subject: [PATCH 4/4] MikkT tangent generation support * Default setting when no tangents rule: MikkT tangents. * Calculates tangents/bitangents for all available uv sets. * Creates tangent/bitangent data in in case they are not existing yet (as in: the source scene contains tangents/bitangents) * Overwrites the tangent/bitangent data from the source scene in case MikkT is wished. * Added helper functions to create tangent/bitangent scene nodes, finding tangent/bitangent data for a given uv layer and calculating the number of uv layers provided by the mesh scene node. Signed-off-by: Benjamin Jillich --- .../GraphData/GraphDataBehaviorTests.cpp | 2 +- .../Model/ModelAssetBuilderComponent.cpp | 8 +- .../TangentGenerateComponent.cpp | 272 ++++++++++++------ .../TangentGenerateComponent.h | 25 +- 4 files changed, 211 insertions(+), 96 deletions(-) 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