Bladeren bron

TSpace setting for MikkT tangent generation (#2386)

* Added TSpace method setting which is only visible for MikkT generation.
* Fixed a bug with generating tangents for blend shapes.
* Renamed tangent space into generation method.
* Some code cleaning

Signed-off-by: Benjamin Jillich <[email protected]>
Benjamin Jillich 4 jaren geleden
bovenliggende
commit
a3712b5564
17 gewijzigde bestanden met toevoegingen van 396 en 382 verwijderingen
  1. 1 1
      Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpBitangentStreamImporter.cpp
  2. 1 1
      Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpTangentStreamImporter.cpp
  3. 19 27
      Code/Tools/SceneAPI/SceneCore/DataTypes/GraphData/IMeshVertexBitangentData.h
  4. 31 37
      Code/Tools/SceneAPI/SceneCore/DataTypes/GraphData/IMeshVertexTangentData.h
  5. 77 92
      Code/Tools/SceneAPI/SceneData/GraphData/MeshVertexBitangentData.cpp
  6. 25 35
      Code/Tools/SceneAPI/SceneData/GraphData/MeshVertexBitangentData.h
  7. 80 96
      Code/Tools/SceneAPI/SceneData/GraphData/MeshVertexTangentData.cpp
  8. 25 32
      Code/Tools/SceneAPI/SceneData/GraphData/MeshVertexTangentData.h
  9. 29 11
      Code/Tools/SceneAPI/SceneData/Rules/TangentsRule.cpp
  10. 7 2
      Code/Tools/SceneAPI/SceneData/Rules/TangentsRule.h
  11. 4 4
      Code/Tools/SceneAPI/SceneData/Tests/GraphData/GraphDataBehaviorTests.cpp
  12. 27 23
      Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerateComponent.cpp
  13. 4 3
      Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerateComponent.h
  14. 41 13
      Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerators/BlendShapeMikkTGenerator.cpp
  15. 4 1
      Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerators/BlendShapeMikkTGenerator.h
  16. 18 3
      Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerators/MikkTGenerator.cpp
  17. 3 1
      Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerators/MikkTGenerator.h

+ 1 - 1
Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpBitangentStreamImporter.cpp

@@ -87,7 +87,7 @@ namespace AZ
                 // AssImp only has one bitangentStream per mesh.
                 // AssImp only has one bitangentStream per mesh.
                 bitangentStream->SetBitangentSetIndex(0);
                 bitangentStream->SetBitangentSetIndex(0);
 
 
-                bitangentStream->SetTangentSpace(AZ::SceneAPI::DataTypes::TangentSpace::FromSourceScene);
+                bitangentStream->SetGenerationMethod(AZ::SceneAPI::DataTypes::TangentGenerationMethod::FromSourceScene);
                 bitangentStream->ReserveContainerSpace(vertexCount);
                 bitangentStream->ReserveContainerSpace(vertexCount);
                 for (int sdkMeshIndex = 0; sdkMeshIndex < currentNode->mNumMeshes; ++sdkMeshIndex)
                 for (int sdkMeshIndex = 0; sdkMeshIndex < currentNode->mNumMeshes; ++sdkMeshIndex)
                 {
                 {

+ 1 - 1
Code/Tools/SceneAPI/SceneBuilder/Importers/AssImpTangentStreamImporter.cpp

@@ -89,7 +89,7 @@ namespace AZ
                 // AssImp only has one tangentStream per mesh.
                 // AssImp only has one tangentStream per mesh.
                 tangentStream->SetTangentSetIndex(0);
                 tangentStream->SetTangentSetIndex(0);
 
 
-                tangentStream->SetTangentSpace(AZ::SceneAPI::DataTypes::TangentSpace::FromSourceScene);
+                tangentStream->SetGenerationMethod(AZ::SceneAPI::DataTypes::TangentGenerationMethod::FromSourceScene);
                 tangentStream->ReserveContainerSpace(vertexCount);
                 tangentStream->ReserveContainerSpace(vertexCount);
                 for (int sdkMeshIndex = 0; sdkMeshIndex < currentNode->mNumMeshes; ++sdkMeshIndex)
                 for (int sdkMeshIndex = 0; sdkMeshIndex < currentNode->mNumMeshes; ++sdkMeshIndex)
                 {
                 {

+ 19 - 27
Code/Tools/SceneAPI/SceneCore/DataTypes/GraphData/IMeshVertexBitangentData.h

@@ -17,32 +17,24 @@ namespace AZ
     class Vector3;
     class Vector3;
 }
 }
 
 
-namespace AZ
+namespace AZ::SceneAPI::DataTypes
 {
 {
-    namespace SceneAPI
+    class IMeshVertexBitangentData
+        : public IGraphObject
     {
     {
-        namespace DataTypes
-        {
-
-            class IMeshVertexBitangentData
-                : public IGraphObject
-            {
-            public:                                
-                AZ_RTTI(IMeshVertexBitangentData, "{6C8F6109-B0BD-49D1-A998-4A4946557DF9}", IGraphObject);
-
-                virtual ~IMeshVertexBitangentData() override = default;
-
-                void CloneAttributesFrom([[maybe_unused]] const IGraphObject* sourceObject) override {}
-
-                virtual size_t GetCount() const = 0;
-                virtual const AZ::Vector3& GetBitangent(size_t index) const = 0;
-                virtual void SetBitangent(size_t vertexIndex, const AZ::Vector3& bitangent) = 0;
-                virtual void SetBitangentSetIndex(size_t setIndex) = 0;
-                virtual size_t GetBitangentSetIndex() const = 0;
-                virtual TangentSpace GetTangentSpace() const = 0;
-                virtual void SetTangentSpace(TangentSpace space) = 0;
-            };
-
-        }  // DataTypes
-    }  // SceneAPI
-}  // AZ
+    public:                                
+        AZ_RTTI(IMeshVertexBitangentData, "{6C8F6109-B0BD-49D1-A998-4A4946557DF9}", IGraphObject);
+
+        virtual ~IMeshVertexBitangentData() override = default;
+
+        void CloneAttributesFrom([[maybe_unused]] const IGraphObject* sourceObject) override {}
+
+        virtual size_t GetCount() const = 0;
+        virtual const AZ::Vector3& GetBitangent(size_t index) const = 0;
+        virtual void SetBitangent(size_t vertexIndex, const AZ::Vector3& bitangent) = 0;
+        virtual void SetBitangentSetIndex(size_t setIndex) = 0;
+        virtual size_t GetBitangentSetIndex() const = 0;
+        virtual TangentGenerationMethod GetGenerationMethod() const = 0;
+        virtual void SetGenerationMethod(TangentGenerationMethod method) = 0;
+    };
+}  // AZ::SceneAPI::DataTypes

+ 31 - 37
Code/Tools/SceneAPI/SceneCore/DataTypes/GraphData/IMeshVertexTangentData.h

@@ -16,42 +16,36 @@ namespace AZ
     class Vector4;
     class Vector4;
 }
 }
 
 
-namespace AZ
+namespace AZ::SceneAPI::DataTypes
 {
 {
-    namespace SceneAPI
+    enum class TangentGenerationMethod
+    {
+        FromSourceScene = 0,
+        MikkT = 1
+    };
+
+    enum class MikkTSpaceMethod
+    {
+        TSpace = 0,
+        TSpaceBasic = 1
+    };
+
+    class IMeshVertexTangentData
+        : public IGraphObject
     {
     {
-        namespace DataTypes
-        {
-            enum class TangentSpace
-            {
-                FromSourceScene = 0,
-                MikkT           = 1
-            };
-
-            enum class BitangentMethod
-            {
-                UseFromTangentSpace = 0,
-                Orthogonal          = 1
-            };
-
-            class IMeshVertexTangentData
-                : public IGraphObject
-            {
-            public:
-                AZ_RTTI(IMeshVertexTangentData, "{B24084FF-09B1-4EE5-BA5B-2D392E92ECC1}", IGraphObject);
-
-                virtual ~IMeshVertexTangentData() override = default;
-
-                void CloneAttributesFrom([[maybe_unused]] const IGraphObject* sourceObject) override {}
-
-                virtual size_t GetCount() const = 0;
-                virtual const AZ::Vector4& GetTangent(size_t index) const = 0;
-                virtual void SetTangent(size_t vertexIndex, const AZ::Vector4& tangent) = 0;
-                virtual void SetTangentSetIndex(size_t setIndex) = 0;
-                virtual size_t GetTangentSetIndex() const = 0;
-                virtual TangentSpace GetTangentSpace() const = 0;
-                virtual void SetTangentSpace(TangentSpace space) = 0;
-            };
-        }  // DataTypes
-    }  // SceneAPI
-}  // AZ
+    public:
+        AZ_RTTI(IMeshVertexTangentData, "{B24084FF-09B1-4EE5-BA5B-2D392E92ECC1}", IGraphObject);
+
+        virtual ~IMeshVertexTangentData() override = default;
+
+        void CloneAttributesFrom([[maybe_unused]] const IGraphObject* sourceObject) override {}
+
+        virtual size_t GetCount() const = 0;
+        virtual const AZ::Vector4& GetTangent(size_t index) const = 0;
+        virtual void SetTangent(size_t vertexIndex, const AZ::Vector4& tangent) = 0;
+        virtual void SetTangentSetIndex(size_t setIndex) = 0;
+        virtual size_t GetTangentSetIndex() const = 0;
+        virtual TangentGenerationMethod GetGenerationMethod() const = 0;
+        virtual void SetGenerationMethod(TangentGenerationMethod method) = 0;
+    };
+}  // AZ::SceneAPI::DataTypes

+ 77 - 92
Code/Tools/SceneAPI/SceneData/GraphData/MeshVertexBitangentData.cpp

@@ -10,110 +10,95 @@
 #include <AzCore/Serialization/SerializeContext.h>
 #include <AzCore/Serialization/SerializeContext.h>
 #include <AzCore/RTTI/BehaviorContext.h>
 #include <AzCore/RTTI/BehaviorContext.h>
 
 
-namespace AZ
+namespace AZ::SceneData::GraphData
 {
 {
-    namespace SceneData
+    void MeshVertexBitangentData::Reflect(ReflectContext* context)
     {
     {
-        namespace GraphData
+        SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
+        if (serializeContext)
         {
         {
-            void MeshVertexBitangentData::Reflect(ReflectContext* context)
-            {
-                SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
-                if (serializeContext)
-                {
-                    serializeContext->Class<MeshVertexBitangentData>()->Version(2);
-                }
+            serializeContext->Class<MeshVertexBitangentData>()->Version(2);
+        }
 
 
-                BehaviorContext* behaviorContext = azrtti_cast<BehaviorContext*>(context);
-                if (behaviorContext)
-                {
-                    behaviorContext->Class<MeshVertexBitangentData>()
-                        ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
-                        ->Attribute(AZ::Script::Attributes::Module, "scene")
-                        ->Method("GetCount", &MeshVertexBitangentData::GetCount)
-                        ->Method("GetBitangent", &MeshVertexBitangentData::GetBitangent)
-                        ->Method("GetBitangentSetIndex", &MeshVertexBitangentData::GetBitangentSetIndex)
-                        ->Method("GetTangentSpace", &MeshVertexBitangentData::GetTangentSpace)
-                        ->Enum<(int)SceneAPI::DataTypes::TangentSpace::FromSourceScene>("FromSourceScene")
-                        ->Enum<(int)SceneAPI::DataTypes::TangentSpace::MikkT>("MikkT");
-                }
-            }
-
-            void MeshVertexBitangentData::CloneAttributesFrom(const IGraphObject* sourceObject)
-            {
-                IMeshVertexBitangentData::CloneAttributesFrom(sourceObject);
-                if (const auto* typedSource = azrtti_cast<const MeshVertexBitangentData*>(sourceObject))
-                {
-                    SetTangentSpace(typedSource->GetTangentSpace());
-                    SetBitangentSetIndex(typedSource->GetBitangentSetIndex());
-                }
-            }
-
-            size_t MeshVertexBitangentData::GetCount() const
-            {
-                return m_bitangents.size();
-            }
-
-
-            const AZ::Vector3& MeshVertexBitangentData::GetBitangent(size_t index) const
-            {
-                AZ_Assert(index < m_bitangents.size(), "Invalid index %i for mesh bitangents.", index);
-                return m_bitangents[index];
-            }
-
-
-            void MeshVertexBitangentData::ReserveContainerSpace(size_t numVerts)
-            {
-                m_bitangents.reserve(numVerts);
-            }
-
-
-            void MeshVertexBitangentData::Resize(size_t numVerts)
-            {
-                m_bitangents.resize(numVerts);
-            }
-
-
-            void MeshVertexBitangentData::AppendBitangent(const AZ::Vector3& bitangent)
-            {
-                m_bitangents.push_back(bitangent);
-            }
+        BehaviorContext* behaviorContext = azrtti_cast<BehaviorContext*>(context);
+        if (behaviorContext)
+        {
+            behaviorContext->Class<MeshVertexBitangentData>()
+                ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
+                ->Attribute(AZ::Script::Attributes::Module, "scene")
+                ->Method("GetCount", &MeshVertexBitangentData::GetCount)
+                ->Method("GetBitangent", &MeshVertexBitangentData::GetBitangent)
+                ->Method("GetBitangentSetIndex", &MeshVertexBitangentData::GetBitangentSetIndex)
+                ->Method("GetGenerationMethod", &MeshVertexBitangentData::GetGenerationMethod)
+                ->Enum<(int)SceneAPI::DataTypes::TangentGenerationMethod::FromSourceScene>("FromSourceScene")
+                ->Enum<(int)SceneAPI::DataTypes::TangentGenerationMethod::MikkT>("MikkT");
+        }
+    }
+
+    void MeshVertexBitangentData::CloneAttributesFrom(const IGraphObject* sourceObject)
+    {
+        IMeshVertexBitangentData::CloneAttributesFrom(sourceObject);
+        if (const auto* typedSource = azrtti_cast<const MeshVertexBitangentData*>(sourceObject))
+        {
+            SetGenerationMethod(typedSource->GetGenerationMethod());
+            SetBitangentSetIndex(typedSource->GetBitangentSetIndex());
+        }
+    }
 
 
+    size_t MeshVertexBitangentData::GetCount() const
+    {
+        return m_bitangents.size();
+    }
 
 
-            void MeshVertexBitangentData::SetBitangent(size_t vertexIndex, const AZ::Vector3& bitangent)
-            {
-                m_bitangents[vertexIndex] = bitangent;
-            }
+    const AZ::Vector3& MeshVertexBitangentData::GetBitangent(size_t index) const
+    {
+        AZ_Assert(index < m_bitangents.size(), "Invalid index %i for mesh bitangents.", index);
+        return m_bitangents[index];
+    }
 
 
+    void MeshVertexBitangentData::ReserveContainerSpace(size_t numVerts)
+    {
+        m_bitangents.reserve(numVerts);
+    }
 
 
-            void MeshVertexBitangentData::SetBitangentSetIndex(size_t setIndex)
-            {
-                m_setIndex = setIndex;
-            }
+    void MeshVertexBitangentData::Resize(size_t numVerts)
+    {
+        m_bitangents.resize(numVerts);
+    }
 
 
+    void MeshVertexBitangentData::AppendBitangent(const AZ::Vector3& bitangent)
+    {
+        m_bitangents.push_back(bitangent);
+    }
 
 
-            size_t MeshVertexBitangentData::GetBitangentSetIndex() const
-            {
-                return m_setIndex;
-            }
+    void MeshVertexBitangentData::SetBitangent(size_t vertexIndex, const AZ::Vector3& bitangent)
+    {
+        m_bitangents[vertexIndex] = bitangent;
+    }
 
 
+    void MeshVertexBitangentData::SetBitangentSetIndex(size_t setIndex)
+    {
+        m_setIndex = setIndex;
+    }
 
 
-            AZ::SceneAPI::DataTypes::TangentSpace MeshVertexBitangentData::GetTangentSpace() const
-            { 
-                return m_tangentSpace;
-            }
+    size_t MeshVertexBitangentData::GetBitangentSetIndex() const
+    {
+        return m_setIndex;
+    }
 
 
+    AZ::SceneAPI::DataTypes::TangentGenerationMethod MeshVertexBitangentData::GetGenerationMethod() const
+    { 
+        return m_generationMethod;
+    }
 
 
-            void MeshVertexBitangentData::SetTangentSpace(AZ::SceneAPI::DataTypes::TangentSpace space)
-            {
-                m_tangentSpace = space;
-            }
+    void MeshVertexBitangentData::SetGenerationMethod(AZ::SceneAPI::DataTypes::TangentGenerationMethod method)
+    { 
+        m_generationMethod = method;
+    }
 
 
-            void MeshVertexBitangentData::GetDebugOutput(AZ::SceneAPI::Utilities::DebugOutput& output) const
-            {
-                output.Write("Bitangents", m_bitangents);
-                output.Write("TangentSpace", aznumeric_cast<int64_t>(m_tangentSpace));
-            }
-        } // GraphData
-    } // SceneData
-} // AZ
+    void MeshVertexBitangentData::GetDebugOutput(AZ::SceneAPI::Utilities::DebugOutput& output) const
+    {
+        output.Write("Bitangents", m_bitangents);
+        output.Write("GenerationMethod", aznumeric_cast<int64_t>(m_generationMethod));
+    }
+} // AZ::SceneData::GraphData

+ 25 - 35
Code/Tools/SceneAPI/SceneData/GraphData/MeshVertexBitangentData.h

@@ -10,51 +10,41 @@
 
 
 #include <AzCore/Math/Vector3.h>
 #include <AzCore/Math/Vector3.h>
 #include <AzCore/std/containers/vector.h>
 #include <AzCore/std/containers/vector.h>
-
 #include <SceneAPI/SceneData/SceneDataConfiguration.h>
 #include <SceneAPI/SceneData/SceneDataConfiguration.h>
 #include <SceneAPI/SceneCore/DataTypes/GraphData/IMeshVertexBitangentData.h>
 #include <SceneAPI/SceneCore/DataTypes/GraphData/IMeshVertexBitangentData.h>
 
 
-
-namespace AZ
+namespace AZ::SceneData::GraphData
 {
 {
-    namespace SceneData
+    class SCENE_DATA_CLASS MeshVertexBitangentData
+        : public AZ::SceneAPI::DataTypes::IMeshVertexBitangentData
     {
     {
-        namespace GraphData
-        {
-
-            class SCENE_DATA_CLASS MeshVertexBitangentData
-                : public AZ::SceneAPI::DataTypes::IMeshVertexBitangentData
-            {
-            public:                
-                AZ_RTTI(MeshVertexBitangentData, "{F56FB088-4C92-4453-AFE9-4E820F03FA90}", AZ::SceneAPI::DataTypes::IMeshVertexBitangentData);
-
-                static void Reflect(ReflectContext* context);
+    public:                
+        AZ_RTTI(MeshVertexBitangentData, "{F56FB088-4C92-4453-AFE9-4E820F03FA90}", AZ::SceneAPI::DataTypes::IMeshVertexBitangentData);
 
 
-                SCENE_DATA_API ~MeshVertexBitangentData() override = default;
+        static void Reflect(ReflectContext* context);
 
 
-                SCENE_DATA_API void CloneAttributesFrom(const IGraphObject* sourceObject) override;
+        SCENE_DATA_API ~MeshVertexBitangentData() override = default;
 
 
-                SCENE_DATA_API size_t GetCount() const override;
-                SCENE_DATA_API const AZ::Vector3& GetBitangent(size_t index) const override;
-                SCENE_DATA_API void SetBitangent(size_t vertexIndex, const AZ::Vector3& bitangent) override;
+        SCENE_DATA_API void CloneAttributesFrom(const IGraphObject* sourceObject) override;
 
 
-                SCENE_DATA_API void SetBitangentSetIndex(size_t setIndex) override;
-                SCENE_DATA_API size_t GetBitangentSetIndex() const override;
+        SCENE_DATA_API size_t GetCount() const override;
+        SCENE_DATA_API const AZ::Vector3& GetBitangent(size_t index) const override;
+        SCENE_DATA_API void SetBitangent(size_t vertexIndex, const AZ::Vector3& bitangent) override;
 
 
-                SCENE_DATA_API void Resize(size_t numVerts);
-                SCENE_DATA_API void ReserveContainerSpace(size_t numVerts);
-                SCENE_DATA_API void AppendBitangent(const AZ::Vector3& bitangent);
+        SCENE_DATA_API void SetBitangentSetIndex(size_t setIndex) override;
+        SCENE_DATA_API size_t GetBitangentSetIndex() const override;
 
 
-                SCENE_DATA_API AZ::SceneAPI::DataTypes::TangentSpace GetTangentSpace() const override;
-                SCENE_DATA_API void SetTangentSpace(AZ::SceneAPI::DataTypes::TangentSpace space) override;
+        SCENE_DATA_API void Resize(size_t numVerts);
+        SCENE_DATA_API void ReserveContainerSpace(size_t numVerts);
+        SCENE_DATA_API void AppendBitangent(const AZ::Vector3& bitangent);
 
 
-                SCENE_DATA_API void GetDebugOutput(AZ::SceneAPI::Utilities::DebugOutput& output) const override;
-            protected:
-                AZStd::vector<AZ::Vector3>              m_bitangents;
-                AZ::SceneAPI::DataTypes::TangentSpace   m_tangentSpace = AZ::SceneAPI::DataTypes::TangentSpace::FromSourceScene;
-                size_t                                  m_setIndex = 0;
-            };
+        SCENE_DATA_API AZ::SceneAPI::DataTypes::TangentGenerationMethod GetGenerationMethod() const override;
+        SCENE_DATA_API void SetGenerationMethod(AZ::SceneAPI::DataTypes::TangentGenerationMethod method) override;
 
 
-        } // GraphData
-    } // SceneData
-} // AZ
+        SCENE_DATA_API void GetDebugOutput(AZ::SceneAPI::Utilities::DebugOutput& output) const override;
+    protected:
+        AZStd::vector<AZ::Vector3> m_bitangents;
+        AZ::SceneAPI::DataTypes::TangentGenerationMethod m_generationMethod = AZ::SceneAPI::DataTypes::TangentGenerationMethod::FromSourceScene;
+        size_t m_setIndex = 0;
+    };
+} // AZ::SceneData::GraphData

+ 80 - 96
Code/Tools/SceneAPI/SceneData/GraphData/MeshVertexTangentData.cpp

@@ -10,112 +10,96 @@
 #include <AzCore/Serialization/SerializeContext.h>
 #include <AzCore/Serialization/SerializeContext.h>
 #include <AzCore/RTTI/BehaviorContext.h>
 #include <AzCore/RTTI/BehaviorContext.h>
 
 
-namespace AZ
+namespace AZ::SceneData::GraphData
 {
 {
-    namespace SceneData
+    void MeshVertexTangentData::Reflect(ReflectContext* context)
     {
     {
-        namespace GraphData
+        SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
+        if (serializeContext)
         {
         {
-            void MeshVertexTangentData::Reflect(ReflectContext* context)
-            {
-                SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
-                if (serializeContext)
-                {
-                    serializeContext->Class<MeshVertexTangentData>()->Version(2);
-                }
+            serializeContext->Class<MeshVertexTangentData>()->Version(2);
+        }
 
 
-                BehaviorContext* behaviorContext = azrtti_cast<BehaviorContext*>(context);
-                if (behaviorContext)
-                {
-                    behaviorContext->Class<MeshVertexTangentData>()
-                        ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
-                        ->Attribute(AZ::Script::Attributes::Module, "scene")
-                        ->Method("GetCount", &MeshVertexTangentData::GetCount)
-                        ->Method("GetTangent", &MeshVertexTangentData::GetTangent)
-                        ->Method("GetTangentSetIndex", &MeshVertexTangentData::GetTangentSetIndex)
-                        ->Method("GetTangentSpace", &MeshVertexTangentData::GetTangentSpace)
-                        ->Enum<(int)SceneAPI::DataTypes::TangentSpace::FromSourceScene>("FromSourceScene")
-                        ->Enum<(int)SceneAPI::DataTypes::TangentSpace::MikkT>("MikkT");
-                }
-            }
-
-            void MeshVertexTangentData::CloneAttributesFrom(const IGraphObject* sourceObject)
-            {
-                IMeshVertexTangentData::CloneAttributesFrom(sourceObject);
-                if (const auto* typedSource = azrtti_cast<const MeshVertexTangentData*>(sourceObject))
-                {
-                    SetTangentSpace(typedSource->GetTangentSpace());
-                    SetTangentSetIndex(typedSource->GetTangentSetIndex());
-                }
-            }
-
-            size_t MeshVertexTangentData::GetCount() const
-            {
-                return m_tangents.size();
-            }
-
-
-            const AZ::Vector4& MeshVertexTangentData::GetTangent(size_t index) const
-            {
-                AZ_Assert(index < m_tangents.size(), "Invalid index %i for mesh tangents.", index);
-                return m_tangents[index];
-            }
-
-
-            void MeshVertexTangentData::ReserveContainerSpace(size_t numVerts)
-            {
-                m_tangents.reserve(numVerts);
-            }
-
-
-            void MeshVertexTangentData::Resize(size_t numVerts)
-            {
-                m_tangents.resize(numVerts);
-            }
-
-
-            void MeshVertexTangentData::AppendTangent(const AZ::Vector4& tangent)
-            {
-                m_tangents.push_back(tangent);
-            }
-
-            void MeshVertexTangentData::GetDebugOutput(AZ::SceneAPI::Utilities::DebugOutput& output) const
-            {
-                output.Write("Tangents", m_tangents);
-                output.Write("TangentSpace", aznumeric_cast<int64_t>(m_tangentSpace));
-                output.Write("SetIndex", aznumeric_cast<uint64_t>(m_setIndex));
-            }
-
-
-            void MeshVertexTangentData::SetTangent(size_t vertexIndex, const AZ::Vector4& tangent)
-            {
-                m_tangents[vertexIndex] = tangent;
-            }
+        BehaviorContext* behaviorContext = azrtti_cast<BehaviorContext*>(context);
+        if (behaviorContext)
+        {
+            behaviorContext->Class<MeshVertexTangentData>()
+                ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
+                ->Attribute(AZ::Script::Attributes::Module, "scene")
+                ->Method("GetCount", &MeshVertexTangentData::GetCount)
+                ->Method("GetTangent", &MeshVertexTangentData::GetTangent)
+                ->Method("GetTangentSetIndex", &MeshVertexTangentData::GetTangentSetIndex)
+                ->Method("GetGenerationMethod", &MeshVertexTangentData::GetGenerationMethod)
+                ->Enum<(int)SceneAPI::DataTypes::TangentGenerationMethod::FromSourceScene>("FromSourceScene")
+                ->Enum<(int)SceneAPI::DataTypes::TangentGenerationMethod::MikkT>("MikkT");
+        }
+    }
+
+    void MeshVertexTangentData::CloneAttributesFrom(const IGraphObject* sourceObject)
+    {
+        IMeshVertexTangentData::CloneAttributesFrom(sourceObject);
+        if (const auto* typedSource = azrtti_cast<const MeshVertexTangentData*>(sourceObject))
+        {
+            SetGenerationMethod(typedSource->GetGenerationMethod());
+            SetTangentSetIndex(typedSource->GetTangentSetIndex());
+        }
+    }
 
 
+    size_t MeshVertexTangentData::GetCount() const
+    {
+        return m_tangents.size();
+    }
 
 
-            void MeshVertexTangentData::SetTangentSetIndex(size_t setIndex)
-            {
-                m_setIndex = setIndex;
-            }
+    const AZ::Vector4& MeshVertexTangentData::GetTangent(size_t index) const
+    {
+        AZ_Assert(index < m_tangents.size(), "Invalid index %i for mesh tangents.", index);
+        return m_tangents[index];
+    }
 
 
+    void MeshVertexTangentData::ReserveContainerSpace(size_t numVerts)
+    {
+        m_tangents.reserve(numVerts);
+    }
 
 
-            size_t MeshVertexTangentData::GetTangentSetIndex() const
-            {
-                return m_setIndex;
-            }
+    void MeshVertexTangentData::Resize(size_t numVerts)
+    {
+        m_tangents.resize(numVerts);
+    }
 
 
+    void MeshVertexTangentData::AppendTangent(const AZ::Vector4& tangent)
+    {
+        m_tangents.push_back(tangent);
+    }
 
 
-            AZ::SceneAPI::DataTypes::TangentSpace MeshVertexTangentData::GetTangentSpace() const
-            { 
-                return m_tangentSpace;
-            }
+    void MeshVertexTangentData::GetDebugOutput(AZ::SceneAPI::Utilities::DebugOutput& output) const
+    {
+        output.Write("Tangents", m_tangents);
+        output.Write("GenerationMethod", aznumeric_cast<int64_t>(m_generationMethod));
+        output.Write("SetIndex", aznumeric_cast<uint64_t>(m_setIndex));
+    }
 
 
+    void MeshVertexTangentData::SetTangent(size_t vertexIndex, const AZ::Vector4& tangent)
+    {
+        m_tangents[vertexIndex] = tangent;
+    }
 
 
-            void MeshVertexTangentData::SetTangentSpace(AZ::SceneAPI::DataTypes::TangentSpace space)
-            { 
-                m_tangentSpace = space;
-            }
+    void MeshVertexTangentData::SetTangentSetIndex(size_t setIndex)
+    {
+        m_setIndex = setIndex;
+    }
 
 
-        } // GraphData
-    } // SceneData
-} // AZ
+    size_t MeshVertexTangentData::GetTangentSetIndex() const
+    {
+        return m_setIndex;
+    }
+
+    AZ::SceneAPI::DataTypes::TangentGenerationMethod MeshVertexTangentData::GetGenerationMethod() const
+    { 
+        return m_generationMethod;
+    }
+
+    void MeshVertexTangentData::SetGenerationMethod(AZ::SceneAPI::DataTypes::TangentGenerationMethod method)
+    { 
+        m_generationMethod = method;
+    }
+} // AZ::SceneData::GraphData

+ 25 - 32
Code/Tools/SceneAPI/SceneData/GraphData/MeshVertexTangentData.h

@@ -14,46 +14,39 @@
 #include <SceneAPI/SceneData/SceneDataConfiguration.h>
 #include <SceneAPI/SceneData/SceneDataConfiguration.h>
 #include <SceneAPI/SceneCore/DataTypes/GraphData/IMeshVertexTangentData.h>
 #include <SceneAPI/SceneCore/DataTypes/GraphData/IMeshVertexTangentData.h>
 
 
-namespace AZ
+namespace AZ::SceneData::GraphData
 {
 {
-    namespace SceneData
+    class SCENE_DATA_CLASS MeshVertexTangentData
+        : public AZ::SceneAPI::DataTypes::IMeshVertexTangentData
     {
     {
-        namespace GraphData
-        {
+    public:
+        AZ_RTTI(MeshVertexTangentData, "{C16F0F38-8F8F-45A2-A33B-F2758922A7C4}", AZ::SceneAPI::DataTypes::IMeshVertexTangentData);
 
 
-            class SCENE_DATA_CLASS MeshVertexTangentData
-                : public AZ::SceneAPI::DataTypes::IMeshVertexTangentData
-            {
-            public:                
-                AZ_RTTI(MeshVertexTangentData, "{C16F0F38-8F8F-45A2-A33B-F2758922A7C4}", AZ::SceneAPI::DataTypes::IMeshVertexTangentData);
+        static void Reflect(ReflectContext* context);
 
 
-                static void Reflect(ReflectContext* context);
+        SCENE_DATA_API ~MeshVertexTangentData() override = default;
 
 
-                SCENE_DATA_API ~MeshVertexTangentData() override = default;
+        SCENE_DATA_API void CloneAttributesFrom(const IGraphObject* sourceObject) override;
 
 
-                SCENE_DATA_API void CloneAttributesFrom(const IGraphObject* sourceObject) override;
+        SCENE_DATA_API size_t GetCount() const override;
+        SCENE_DATA_API const AZ::Vector4& GetTangent(size_t index) const override;
+        SCENE_DATA_API void SetTangent(size_t vertexIndex, const AZ::Vector4& tangent) override;
 
 
-                SCENE_DATA_API size_t GetCount() const override;
-                SCENE_DATA_API const AZ::Vector4& GetTangent(size_t index) const override;
-                SCENE_DATA_API void SetTangent(size_t vertexIndex, const AZ::Vector4& tangent) override;
+        SCENE_DATA_API void SetTangentSetIndex(size_t setIndex) override;
+        SCENE_DATA_API size_t GetTangentSetIndex() const override;
 
 
-                SCENE_DATA_API void SetTangentSetIndex(size_t setIndex) override;
-                SCENE_DATA_API size_t GetTangentSetIndex() const override;
+        SCENE_DATA_API AZ::SceneAPI::DataTypes::TangentGenerationMethod GetGenerationMethod() const override;
+        SCENE_DATA_API void SetGenerationMethod(AZ::SceneAPI::DataTypes::TangentGenerationMethod method) override;
 
 
-                SCENE_DATA_API AZ::SceneAPI::DataTypes::TangentSpace GetTangentSpace() const override;
-                SCENE_DATA_API void SetTangentSpace(AZ::SceneAPI::DataTypes::TangentSpace space) override;
+        SCENE_DATA_API void Resize(size_t numVerts);
+        SCENE_DATA_API void ReserveContainerSpace(size_t numVerts);
+        SCENE_DATA_API void AppendTangent(const AZ::Vector4& tangent);
 
 
-                SCENE_DATA_API void Resize(size_t numVerts);
-                SCENE_DATA_API void ReserveContainerSpace(size_t numVerts);
-                SCENE_DATA_API void AppendTangent(const AZ::Vector4& tangent);
+        SCENE_DATA_API void GetDebugOutput(AZ::SceneAPI::Utilities::DebugOutput& output) const override;
 
 
-                SCENE_DATA_API void GetDebugOutput(AZ::SceneAPI::Utilities::DebugOutput& output) const override;
-            protected:
-                AZStd::vector<AZ::Vector4>              m_tangents;
-                AZ::SceneAPI::DataTypes::TangentSpace   m_tangentSpace = AZ::SceneAPI::DataTypes::TangentSpace::FromSourceScene;
-                size_t                                  m_setIndex = 0;
-            };
-
-        } // GraphData
-    } // SceneData
-} // AZ
+    protected:
+        AZStd::vector<AZ::Vector4> m_tangents;
+        AZ::SceneAPI::DataTypes::TangentGenerationMethod m_generationMethod = AZ::SceneAPI::DataTypes::TangentGenerationMethod::FromSourceScene;
+        size_t m_setIndex = 0;
+    };
+} // AZ::SceneData::GraphData

+ 29 - 11
Code/Tools/SceneAPI/SceneData/Rules/TangentsRule.cpp

@@ -26,13 +26,22 @@ namespace AZ
         {
         {
             TangentsRule::TangentsRule()
             TangentsRule::TangentsRule()
                 : DataTypes::IRule()
                 : DataTypes::IRule()
-                , m_tangentSpace(AZ::SceneAPI::DataTypes::TangentSpace::MikkT)
             {
             {
             }
             }
 
 
-            AZ::SceneAPI::DataTypes::TangentSpace TangentsRule::GetTangentSpace() const
+            AZ::SceneAPI::DataTypes::TangentGenerationMethod TangentsRule::GetGenerationMethod() const
             {
             {
-                return m_tangentSpace;
+                return m_generationMethod;
+            }
+
+            AZ::SceneAPI::DataTypes::MikkTSpaceMethod TangentsRule::GetMikkTSpaceMethod() const
+            {
+                return m_tSpaceMethod;
+            }
+
+            AZ::Crc32 TangentsRule::GetSpaceMethodVisibility() const
+            {
+                return (m_generationMethod == AZ::SceneAPI::DataTypes::TangentGenerationMethod::MikkT) ? AZ::Edit::PropertyVisibility::Show : AZ::Edit::PropertyVisibility::Hide;
             }
             }
 
 
             void TangentsRule::Reflect(AZ::ReflectContext* context)
             void TangentsRule::Reflect(AZ::ReflectContext* context)
@@ -43,20 +52,29 @@ namespace AZ
                     return;
                     return;
                 }
                 }
 
 
-                serializeContext->Class<TangentsRule, DataTypes::IRule>()->Version(3)
-                    ->Field("tangentSpace", &TangentsRule::m_tangentSpace);
+                serializeContext->Class<TangentsRule, DataTypes::IRule>()->Version(4)
+                    ->Field("tangentSpace", &TangentsRule::m_generationMethod)
+                    ->Field("tSpaceMethod", &TangentsRule::m_tSpaceMethod);
 
 
                 AZ::EditContext* editContext = serializeContext->GetEditContext();
                 AZ::EditContext* editContext = serializeContext->GetEditContext();
                 if (editContext)
                 if (editContext)
                 {
                 {
                     editContext->Class<TangentsRule>("Tangents", "Specify how tangents are imported or generated.")
                     editContext->Class<TangentsRule>("Tangents", "Specify how tangents are imported or generated.")
                         ->ClassElement(Edit::ClassElements::EditorData, "")
                         ->ClassElement(Edit::ClassElements::EditorData, "")
-                        ->Attribute("AutoExpand", true)
-                        ->Attribute(AZ::Edit::Attributes::NameLabelOverride, "")
-                        ->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")
-                        ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::EntireTree)
+                            ->Attribute("AutoExpand", true)
+                            ->Attribute(AZ::Edit::Attributes::NameLabelOverride, "")
+                        ->DataElement(AZ::Edit::UIHandlers::ComboBox, &AZ::SceneAPI::SceneData::TangentsRule::m_generationMethod, "Generation Method", "Specify the tangent generation method. Choose 'From Source Scene' to extract the tangents and bitangents directly from the source scene file. When there is no tangents rule or the source scene has no tangents stored inside it, the 'MikkT' option will be used.")
+                            ->EnumAttribute(AZ::SceneAPI::DataTypes::TangentGenerationMethod::FromSourceScene, "From Source Scene")
+                            ->EnumAttribute(AZ::SceneAPI::DataTypes::TangentGenerationMethod::MikkT, "MikkT")
+                            ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::EntireTree)
+                        ->DataElement(AZ::Edit::UIHandlers::ComboBox, &AZ::SceneAPI::SceneData::TangentsRule::m_tSpaceMethod, "TSpace Method",
+                            "TSpace generates the tangents and bitangents with their true magnitudes which can be used for relief mapping effects. "
+                            " It calculates the 'real' bitangent which may not be perpendicular to the tangent. "
+                            "However, both, the tangent and bitangent are perpendicular to the vertex normal. "
+                            "TSpaceBasic calculates unit vector tangents and bitangents at pixel/vertex level which are sufficient for basic normal mapping.")
+                            ->EnumAttribute(AZ::SceneAPI::DataTypes::MikkTSpaceMethod::TSpace, "TSpace")
+                            ->EnumAttribute(AZ::SceneAPI::DataTypes::MikkTSpaceMethod::TSpaceBasic, "TSpaceBasic")
+                            ->Attribute(AZ::Edit::Attributes::Visibility, &TangentsRule::GetSpaceMethodVisibility);
                     ;
                     ;
                 }
                 }
             }
             }

+ 7 - 2
Code/Tools/SceneAPI/SceneData/Rules/TangentsRule.h

@@ -45,12 +45,17 @@ namespace AZ
                 SCENE_DATA_API TangentsRule();
                 SCENE_DATA_API TangentsRule();
                 SCENE_DATA_API ~TangentsRule() override = default;
                 SCENE_DATA_API ~TangentsRule() override = default;
 
 
-                SCENE_DATA_API AZ::SceneAPI::DataTypes::TangentSpace GetTangentSpace() const;
+                SCENE_DATA_API AZ::SceneAPI::DataTypes::TangentGenerationMethod GetGenerationMethod() const;
+                SCENE_DATA_API AZ::SceneAPI::DataTypes::MikkTSpaceMethod GetMikkTSpaceMethod() const;
 
 
                 static void Reflect(ReflectContext* context);
                 static void Reflect(ReflectContext* context);
 
 
             protected:
             protected:
-                AZ::SceneAPI::DataTypes::TangentSpace m_tangentSpace;     /**< Specifies how to handle tangents. Either generate them, or import them. */
+                AZ::SceneAPI::DataTypes::TangentGenerationMethod m_generationMethod = AZ::SceneAPI::DataTypes::TangentGenerationMethod::MikkT; /**< Specifies how to handle tangents. Either generate them, or import them. */
+
+                // MikkT specific settings
+                AZ::Crc32 GetSpaceMethodVisibility() const;
+                AZ::SceneAPI::DataTypes::MikkTSpaceMethod m_tSpaceMethod = AZ::SceneAPI::DataTypes::MikkTSpaceMethod::TSpace;
             };
             };
         } // SceneData
         } // SceneData
     } // SceneAPI
     } // SceneAPI

+ 4 - 4
Code/Tools/SceneAPI/SceneData/Tests/GraphData/GraphDataBehaviorTests.cpp

@@ -84,7 +84,7 @@ namespace AZ
                         auto* bitangentData = AZStd::any_cast<AZ::SceneData::GraphData::MeshVertexBitangentData>(&data);
                         auto* bitangentData = AZStd::any_cast<AZ::SceneData::GraphData::MeshVertexBitangentData>(&data);
                         bitangentData->AppendBitangent(AZ::Vector3{0.12f, 0.34f, 0.56f});
                         bitangentData->AppendBitangent(AZ::Vector3{0.12f, 0.34f, 0.56f});
                         bitangentData->AppendBitangent(AZ::Vector3{0.77f, 0.88f, 0.99f});
                         bitangentData->AppendBitangent(AZ::Vector3{0.77f, 0.88f, 0.99f});
-                        bitangentData->SetTangentSpace(AZ::SceneAPI::DataTypes::TangentSpace::FromSourceScene);
+                        bitangentData->SetGenerationMethod(AZ::SceneAPI::DataTypes::TangentGenerationMethod::FromSourceScene);
                         bitangentData->SetBitangentSetIndex(1);
                         bitangentData->SetBitangentSetIndex(1);
                         return true;
                         return true;
                     }
                     }
@@ -94,7 +94,7 @@ namespace AZ
                         tangentData->AppendTangent(AZ::Vector4{0.12f, 0.34f, 0.56f, 0.78f});
                         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.18f, 0.28f, 0.19f, 0.29f});
                         tangentData->AppendTangent(AZ::Vector4{0.21f, 0.43f, 0.65f, 0.87f});
                         tangentData->AppendTangent(AZ::Vector4{0.21f, 0.43f, 0.65f, 0.87f});
-                        tangentData->SetTangentSpace(AZ::SceneAPI::DataTypes::TangentSpace::MikkT);
+                        tangentData->SetGenerationMethod(AZ::SceneAPI::DataTypes::TangentGenerationMethod::MikkT);
                         tangentData->SetTangentSetIndex(2);
                         tangentData->SetTangentSetIndex(2);
                         return true;
                         return true;
                     }
                     }
@@ -318,7 +318,7 @@ namespace AZ
                 ExpectExecute("TestExpectFloatEquals(bitangentData.y, 0.88)");
                 ExpectExecute("TestExpectFloatEquals(bitangentData.y, 0.88)");
                 ExpectExecute("TestExpectFloatEquals(bitangentData.z, 0.99)");
                 ExpectExecute("TestExpectFloatEquals(bitangentData.z, 0.99)");
                 ExpectExecute("TestExpectIntegerEquals(meshVertexBitangentData:GetBitangentSetIndex(), 1)");
                 ExpectExecute("TestExpectIntegerEquals(meshVertexBitangentData:GetBitangentSetIndex(), 1)");
-                ExpectExecute("TestExpectTrue(meshVertexBitangentData:GetTangentSpace(), MeshVertexBitangentData.FromSourceScene)");
+                ExpectExecute("TestExpectTrue(meshVertexBitangentData:GetGenerationMethod(), MeshVertexBitangentData.FromSourceScene)");
             }
             }
 
 
             TEST_F(GrapDatahBehaviorScriptTest, SceneGraph_MeshVertexTangentData_AccessWorks)
             TEST_F(GrapDatahBehaviorScriptTest, SceneGraph_MeshVertexTangentData_AccessWorks)
@@ -337,7 +337,7 @@ namespace AZ
                 ExpectExecute("TestExpectFloatEquals(tangentData.z, 0.19)");
                 ExpectExecute("TestExpectFloatEquals(tangentData.z, 0.19)");
                 ExpectExecute("TestExpectFloatEquals(tangentData.w, 0.29)");
                 ExpectExecute("TestExpectFloatEquals(tangentData.w, 0.29)");
                 ExpectExecute("TestExpectIntegerEquals(meshVertexTangentData:GetTangentSetIndex(), 2)");
                 ExpectExecute("TestExpectIntegerEquals(meshVertexTangentData:GetTangentSetIndex(), 2)");
-                ExpectExecute("TestExpectTrue(meshVertexTangentData:GetTangentSpace(), MeshVertexTangentData.EMotionFX)");
+                ExpectExecute("TestExpectTrue(meshVertexTangentData:GetGenerationMethod(), MeshVertexTangentData.EMotionFX)");
             }
             }
 
 
             TEST_F(GrapDatahBehaviorScriptTest, SceneGraph_AnimationData_AccessWorks)
             TEST_F(GrapDatahBehaviorScriptTest, SceneGraph_AnimationData_AccessWorks)

+ 27 - 23
Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerateComponent.cpp

@@ -15,8 +15,6 @@
 #include <SceneAPI/SceneCore/DataTypes/GraphData/IMeshVertexTangentData.h>
 #include <SceneAPI/SceneCore/DataTypes/GraphData/IMeshVertexTangentData.h>
 #include <SceneAPI/SceneCore/DataTypes/GraphData/IMeshVertexBitangentData.h>
 #include <SceneAPI/SceneCore/DataTypes/GraphData/IMeshVertexBitangentData.h>
 
 
-#include <SceneAPI/SceneData/Rules/TangentsRule.h>
-
 #include <SceneAPI/SceneCore/Containers/Views/PairIterator.h>
 #include <SceneAPI/SceneCore/Containers/Views/PairIterator.h>
 #include <SceneAPI/SceneCore/Containers/Views/SceneGraphDownwardsIterator.h>
 #include <SceneAPI/SceneCore/Containers/Views/SceneGraphDownwardsIterator.h>
 #include <SceneAPI/SceneCore/Containers/Views/SceneGraphChildIterator.h>
 #include <SceneAPI/SceneCore/Containers/Views/SceneGraphChildIterator.h>
@@ -52,7 +50,7 @@ namespace AZ::SceneGenerationComponents
         }
         }
     }
     }
 
 
-    AZ::SceneAPI::DataTypes::TangentSpace TangentGenerateComponent::GetTangentSpaceFromRule(const AZ::SceneAPI::Containers::Scene& scene) const
+    const AZ::SceneAPI::SceneData::TangentsRule* TangentGenerateComponent::GetTangentRule(const AZ::SceneAPI::Containers::Scene& scene) const
     {
     {
         for (const auto& object : scene.GetManifest().GetValueStorage())
         for (const auto& object : scene.GetManifest().GetValueStorage())
         {
         {
@@ -62,12 +60,12 @@ namespace AZ::SceneGenerationComponents
                 const AZ::SceneAPI::SceneData::TangentsRule* rule = group->GetRuleContainerConst().FindFirstByType<AZ::SceneAPI::SceneData::TangentsRule>().get();
                 const AZ::SceneAPI::SceneData::TangentsRule* rule = group->GetRuleContainerConst().FindFirstByType<AZ::SceneAPI::SceneData::TangentsRule>().get();
                 if (rule)
                 if (rule)
                 {
                 {
-                    return rule->GetTangentSpace();
+                    return rule;
                 }
                 }
             }
             }
         }
         }
 
 
-        return AZ::SceneAPI::DataTypes::TangentSpace::FromSourceScene;
+        return nullptr;
     }
     }
 
 
     AZ::SceneAPI::Events::ProcessingResult TangentGenerateComponent::GenerateTangentData(TangentGenerateContext& context)
     AZ::SceneAPI::Events::ProcessingResult TangentGenerateComponent::GenerateTangentData(TangentGenerateContext& context)
@@ -189,8 +187,8 @@ namespace AZ::SceneGenerationComponents
             return true; // No fatal error
             return true; // No fatal error
         }
         }
 
 
-        // Check what tangent spaces we need.
-        const AZ::SceneAPI::DataTypes::TangentSpace ruleTangentSpace = GetTangentSpaceFromRule(scene);
+        const AZ::SceneAPI::SceneData::TangentsRule* tangentsRule = GetTangentRule(scene);
+        const AZ::SceneAPI::DataTypes::TangentGenerationMethod ruleGenerationMethod = tangentsRule ? tangentsRule->GetGenerationMethod() : AZ::SceneAPI::DataTypes::TangentGenerationMethod::FromSourceScene;
 
 
         // Find all blend shape data under the mesh. We need to generate the tangent and bitangent for blend shape as well.
         // Find all blend shape data under the mesh. We need to generate the tangent and bitangent for blend shape as well.
         AZStd::vector<AZ::SceneData::GraphData::BlendShapeData*> blendShapes;
         AZStd::vector<AZ::SceneData::GraphData::BlendShapeData*> blendShapes;
@@ -208,12 +206,12 @@ namespace AZ::SceneGenerationComponents
             }
             }
 
 
             // Check if we had tangents inside the source scene file.
             // Check if we had tangents inside the source scene file.
-            AZ::SceneAPI::DataTypes::TangentSpace tangentSpace = ruleTangentSpace;
+            AZ::SceneAPI::DataTypes::TangentGenerationMethod generationMethod = ruleGenerationMethod;
             AZ::SceneAPI::DataTypes::IMeshVertexTangentData* tangentData = FindTangentData(graph, nodeIndex, uvSetIndex);
             AZ::SceneAPI::DataTypes::IMeshVertexTangentData* tangentData = FindTangentData(graph, nodeIndex, uvSetIndex);
             AZ::SceneAPI::DataTypes::IMeshVertexBitangentData* bitangentData = FindBitangentData(graph, nodeIndex, uvSetIndex);
             AZ::SceneAPI::DataTypes::IMeshVertexBitangentData* bitangentData = FindBitangentData(graph, nodeIndex, uvSetIndex);
 
 
             // If all we need is import from the source scene, and we have tangent data from the source scene already, then skip generating.
             // 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 ((generationMethod == AZ::SceneAPI::DataTypes::TangentGenerationMethod::FromSourceScene))
             {
             {
                 if (tangentData && bitangentData)
                 if (tangentData && bitangentData)
                 {
                 {
@@ -226,50 +224,56 @@ namespace AZ::SceneGenerationComponents
                     // In case there are no tangents/bitangents while the user selected to use the source ones, default to MikkT.
                     // 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",
                     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);
                         scene.GetGraph().GetNodeName(nodeIndex).GetName(), uvSetIndex);
-                    tangentSpace = AZ::SceneAPI::DataTypes::TangentSpace::MikkT;
+                    generationMethod = AZ::SceneAPI::DataTypes::TangentGenerationMethod::MikkT;
                 }
                 }
             }
             }
 
 
             if (!tangentData)
             if (!tangentData)
             {
             {
                 if (!AZ::SceneGenerationComponents::TangentGenerateComponent::CreateTangentLayer(scene.GetManifest(), nodeIndex, meshData->GetVertexCount(), uvSetIndex,
                 if (!AZ::SceneGenerationComponents::TangentGenerateComponent::CreateTangentLayer(scene.GetManifest(), nodeIndex, meshData->GetVertexCount(), uvSetIndex,
-                    tangentSpace, graph, &tangentData))
+                    generationMethod, graph, &tangentData))
                 {
                 {
                     AZ_Error(AZ::SceneAPI::Utilities::ErrorWindow, false, "Failed to create tangents data set for mesh %s for uv set %zu.\n",
                     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);
                         scene.GetGraph().GetNodeName(nodeIndex).GetName(), uvSetIndex);
                     continue;
                     continue;
                 }
                 }
             }
             }
+            AZ_Assert(tangentData == FindTangentData(graph, nodeIndex, uvSetIndex), "Used tangent data is not the same as the graph returns.");
+
             if (!bitangentData)
             if (!bitangentData)
             {
             {
                 if (!AZ::SceneGenerationComponents::TangentGenerateComponent::CreateBitangentLayer(scene.GetManifest(), nodeIndex, meshData->GetVertexCount(), uvSetIndex,
                 if (!AZ::SceneGenerationComponents::TangentGenerateComponent::CreateBitangentLayer(scene.GetManifest(), nodeIndex, meshData->GetVertexCount(), uvSetIndex,
-                    tangentSpace, graph, &bitangentData))
+                    generationMethod, graph, &bitangentData))
                 {
                 {
                     AZ_Error(AZ::SceneAPI::Utilities::ErrorWindow, false, "Failed to create bitangents data set for mesh %s for uv set %zu.\n",
                     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);
                         scene.GetGraph().GetNodeName(nodeIndex).GetName(), uvSetIndex);
                     continue;
                     continue;
                 }
                 }
             }
             }
-            tangentData->SetTangentSpace(tangentSpace);
-            bitangentData->SetTangentSpace(tangentSpace);
+            AZ_Assert(bitangentData == FindBitangentData(graph, nodeIndex, uvSetIndex), "Used bitangent data is not the same as the graph returns.");
 
 
-            switch (tangentSpace)
+            tangentData->SetGenerationMethod(generationMethod);
+            bitangentData->SetGenerationMethod(generationMethod);
+
+            switch (generationMethod)
             {
             {
             // Generate using MikkT space.
             // Generate using MikkT space.
-            case AZ::SceneAPI::DataTypes::TangentSpace::MikkT:
+            case AZ::SceneAPI::DataTypes::TangentGenerationMethod::MikkT:
             {
             {
-                allSuccess &= AZ::TangentGeneration::Mesh::MikkT::GenerateTangents(meshData, uvData, tangentData, bitangentData);
+                const AZ::SceneAPI::DataTypes::MikkTSpaceMethod tSpaceMethod = tangentsRule ? tangentsRule->GetMikkTSpaceMethod() : AZ::SceneAPI::DataTypes::MikkTSpaceMethod::TSpace;
+
+                allSuccess &= AZ::TangentGeneration::Mesh::MikkT::GenerateTangents(meshData, uvData, tangentData, bitangentData, tSpaceMethod);
 
 
                 for (AZ::SceneData::GraphData::BlendShapeData* blendShape : blendShapes)
                 for (AZ::SceneData::GraphData::BlendShapeData* blendShape : blendShapes)
                 {
                 {
-                    allSuccess &= AZ::TangentGeneration::BlendShape::MikkT::GenerateTangents(blendShape, uvSetIndex);
+                    allSuccess &= AZ::TangentGeneration::BlendShape::MikkT::GenerateTangents(blendShape, uvSetIndex, tSpaceMethod);
                 }
                 }
             }
             }
             break;
             break;
 
 
             default:
             default:
             {
             {
-                AZ_Assert(false, "Unknown tangent space selected (spaceID=%d) for UV set %d, cannot generate tangents!\n", static_cast<AZ::u32>(tangentSpace), uvSetIndex);
+                AZ_Assert(false, "Unknown tangent generation method selected (%d) for UV set %d, cannot generate tangents.\n", static_cast<AZ::u32>(generationMethod), uvSetIndex);
                 allSuccess = false;
                 allSuccess = false;
             }
             }
             }
             }
@@ -339,7 +343,7 @@ namespace AZ::SceneGenerationComponents
         const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex,
         const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex,
         size_t numVerts,
         size_t numVerts,
         size_t uvSetIndex,
         size_t uvSetIndex,
-        AZ::SceneAPI::DataTypes::TangentSpace tangentSpace,
+        AZ::SceneAPI::DataTypes::TangentGenerationMethod generationMethod,
         AZ::SceneAPI::Containers::SceneGraph& graph,
         AZ::SceneAPI::Containers::SceneGraph& graph,
         AZ::SceneAPI::DataTypes::IMeshVertexTangentData** outTangentData)
         AZ::SceneAPI::DataTypes::IMeshVertexTangentData** outTangentData)
     {
     {
@@ -356,7 +360,7 @@ namespace AZ::SceneGenerationComponents
         }
         }
 
 
         tangentData->SetTangentSetIndex(uvSetIndex);
         tangentData->SetTangentSetIndex(uvSetIndex);
-        tangentData->SetTangentSpace(tangentSpace);
+        tangentData->SetGenerationMethod(generationMethod);
 
 
         const AZStd::string tangentGeneratedName = AZStd::string::format("TangentSet_%zu", uvSetIndex);
         const AZStd::string tangentGeneratedName = AZStd::string::format("TangentSet_%zu", uvSetIndex);
         const AZStd::string tangentSetName = AZ::SceneAPI::DataTypes::Utilities::CreateUniqueName<SceneData::GraphData::MeshVertexBitangentData>(tangentGeneratedName, manifest);
         const AZStd::string tangentSetName = AZ::SceneAPI::DataTypes::Utilities::CreateUniqueName<SceneData::GraphData::MeshVertexBitangentData>(tangentGeneratedName, manifest);
@@ -394,7 +398,7 @@ namespace AZ::SceneGenerationComponents
         const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex,
         const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex,
         size_t numVerts,
         size_t numVerts,
         size_t uvSetIndex,
         size_t uvSetIndex,
-        AZ::SceneAPI::DataTypes::TangentSpace tangentSpace,
+        AZ::SceneAPI::DataTypes::TangentGenerationMethod generationMethod,
         AZ::SceneAPI::Containers::SceneGraph& graph,
         AZ::SceneAPI::Containers::SceneGraph& graph,
         AZ::SceneAPI::DataTypes::IMeshVertexBitangentData** outBitangentData)
         AZ::SceneAPI::DataTypes::IMeshVertexBitangentData** outBitangentData)
     {
     {
@@ -411,7 +415,7 @@ namespace AZ::SceneGenerationComponents
         }
         }
 
 
         bitangentData->SetBitangentSetIndex(uvSetIndex);
         bitangentData->SetBitangentSetIndex(uvSetIndex);
-        bitangentData->SetTangentSpace(tangentSpace);
+        bitangentData->SetGenerationMethod(generationMethod);
 
 
         const AZStd::string bitangentGeneratedName = AZStd::string::format("BitangentSet_%zu", uvSetIndex);
         const AZStd::string bitangentGeneratedName = AZStd::string::format("BitangentSet_%zu", uvSetIndex);
         const AZStd::string bitangentSetName = AZ::SceneAPI::DataTypes::Utilities::CreateUniqueName<SceneData::GraphData::MeshVertexBitangentData>(bitangentGeneratedName, manifest);
         const AZStd::string bitangentSetName = AZ::SceneAPI::DataTypes::Utilities::CreateUniqueName<SceneData::GraphData::MeshVertexBitangentData>(bitangentGeneratedName, manifest);

+ 4 - 3
Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerateComponent.h

@@ -10,6 +10,7 @@
 
 
 #include <SceneAPI/SceneCore/Components/GenerationComponent.h>
 #include <SceneAPI/SceneCore/Components/GenerationComponent.h>
 #include <SceneAPI/SceneCore/Containers/Scene.h>
 #include <SceneAPI/SceneCore/Containers/Scene.h>
+#include <SceneAPI/SceneData/Rules/TangentsRule.h>
 #include <AzCore/RTTI/RTTI.h>
 #include <AzCore/RTTI/RTTI.h>
 
 
 namespace AZ::SceneAPI::DataTypes { class IMeshData; }
 namespace AZ::SceneAPI::DataTypes { class IMeshData; }
@@ -59,7 +60,7 @@ namespace AZ::SceneGenerationComponents
             AZStd::vector<AZ::SceneData::GraphData::BlendShapeData*>& outBlendShapes) const;
             AZStd::vector<AZ::SceneData::GraphData::BlendShapeData*>& outBlendShapes) const;
         bool GenerateTangentsForMesh(AZ::SceneAPI::Containers::Scene& scene, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, AZ::SceneAPI::DataTypes::IMeshData* meshData);
         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);
         void UpdateFbxTangentWValues(AZ::SceneAPI::Containers::SceneGraph& graph, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, const AZ::SceneAPI::DataTypes::IMeshData* meshData);
-        AZ::SceneAPI::DataTypes::TangentSpace GetTangentSpaceFromRule(const AZ::SceneAPI::Containers::Scene& scene) const;
+        const AZ::SceneAPI::SceneData::TangentsRule* GetTangentRule(const AZ::SceneAPI::Containers::Scene& scene) const;
 
 
         size_t CalcUvSetCount(AZ::SceneAPI::Containers::SceneGraph& graph, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex) 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::IMeshVertexUVData* FindUvData(AZ::SceneAPI::Containers::SceneGraph& graph, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, AZ::u64 uvSet) const;
@@ -69,7 +70,7 @@ namespace AZ::SceneGenerationComponents
             const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex,
             const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex,
             size_t numVerts,
             size_t numVerts,
             size_t uvSetIndex,
             size_t uvSetIndex,
-            AZ::SceneAPI::DataTypes::TangentSpace tangentSpace,
+            AZ::SceneAPI::DataTypes::TangentGenerationMethod generationMethod,
             AZ::SceneAPI::Containers::SceneGraph& graph,
             AZ::SceneAPI::Containers::SceneGraph& graph,
             AZ::SceneAPI::DataTypes::IMeshVertexTangentData** outTangentData);
             AZ::SceneAPI::DataTypes::IMeshVertexTangentData** outTangentData);
 
 
@@ -78,7 +79,7 @@ namespace AZ::SceneGenerationComponents
             const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex,
             const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex,
             size_t numVerts,
             size_t numVerts,
             size_t uvSetIndex,
             size_t uvSetIndex,
-            AZ::SceneAPI::DataTypes::TangentSpace tangentSpace,
+            AZ::SceneAPI::DataTypes::TangentGenerationMethod generationMethod,
             AZ::SceneAPI::Containers::SceneGraph& graph,
             AZ::SceneAPI::Containers::SceneGraph& graph,
             AZ::SceneAPI::DataTypes::IMeshVertexBitangentData** outBitangentData);
             AZ::SceneAPI::DataTypes::IMeshVertexBitangentData** outBitangentData);
     };
     };

+ 41 - 13
Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerators/BlendShapeMikkTGenerator.cpp

@@ -76,33 +76,47 @@ namespace AZ::TangentGeneration::BlendShape::MikkT
         const AZ::Vector4 tangentVec(tangent[0]*magS, tangent[1]*magS, tangent[2]*magS, flipSign);
         const AZ::Vector4 tangentVec(tangent[0]*magS, tangent[1]*magS, tangent[2]*magS, flipSign);
         const AZ::Vector3 bitangentVec(bitangent[0]*magT, bitangent[1]*magT, bitangent[2]*magT);
         const AZ::Vector3 bitangentVec(bitangent[0]*magT, bitangent[1]*magT, bitangent[2]*magT);
 
 
-        // Set the tangent and bitangent back to the blendshape
+        // Set the tangent and bitangent back to the blend shape
         AZStd::vector<AZ::Vector4>& tangents = customData->m_blendShapeData->GetTangents();
         AZStd::vector<AZ::Vector4>& tangents = customData->m_blendShapeData->GetTangents();
         AZStd::vector<AZ::Vector3>& bitangents = customData->m_blendShapeData->GetBitangents();
         AZStd::vector<AZ::Vector3>& bitangents = customData->m_blendShapeData->GetBitangents();
         tangents[vertexIndex] = tangentVec;
         tangents[vertexIndex] = tangentVec;
         bitangents[vertexIndex] = bitangentVec;
         bitangents[vertexIndex] = bitangentVec;
     }
     }
 
 
-    bool GenerateTangents(AZ::SceneData::GraphData::BlendShapeData* blendShapeData, size_t uvSetIndex)
+    void SetTSpaceBasic(const SMikkTSpaceContext* context, const float tangent[], const float signValue, const int face, const int vert)
+    {
+        MikktCustomData* customData = static_cast<MikktCustomData*>(context->m_pUserData);
+        const AZ::u32 vertexIndex = customData->m_blendShapeData->GetFaceVertexIndex(face, vert);
+        AZ::Vector3 tangentVec3(tangent[0], tangent[1], tangent[2]);
+        tangentVec3.NormalizeSafe();
+        AZ::Vector3 normal = customData->m_blendShapeData->GetNormal(vertexIndex);
+        normal.NormalizeSafe();
+        const AZ::Vector3 bitangent = normal.Cross(tangentVec3) * signValue;
+
+        // Set the tangent and bitangent back to the blend shape
+        AZStd::vector<AZ::Vector4>& tangents = customData->m_blendShapeData->GetTangents();
+        AZStd::vector<AZ::Vector3>& bitangents = customData->m_blendShapeData->GetBitangents();
+        tangents[vertexIndex] = AZ::Vector4(tangentVec3.GetX(), tangentVec3.GetY(), tangentVec3.GetZ(), signValue);
+        bitangents[vertexIndex] = bitangent;
+    }
+
+    bool GenerateTangents(AZ::SceneData::GraphData::BlendShapeData* blendShapeData,
+        size_t uvSetIndex,
+        AZ::SceneAPI::DataTypes::MikkTSpaceMethod tSpaceMethod)
     {
     {
         // Create tangent and bitangent data sets and relate them to the given UV set.
         // Create tangent and bitangent data sets and relate them to the given UV set.
         const AZStd::vector<AZ::Vector2>& uvSet = blendShapeData->GetUVs(uvSetIndex);
         const AZStd::vector<AZ::Vector2>& uvSet = blendShapeData->GetUVs(uvSetIndex);
         if (uvSet.empty())
         if (uvSet.empty())
         {
         {
-            AZ_TracePrintf(AZ::SceneAPI::Utilities::ErrorWindow, "Cannot find UV data (set index=%d) to generate tangents and bitangents from in MikkT generator!\n", uvSetIndex);
+            AZ_Error(AZ::SceneAPI::Utilities::ErrorWindow, false,
+                "Cannot find UV data (set index=%d) to generate tangents and bitangents from in MikkT generator.\n",
+                uvSetIndex);
             return false;
             return false;
         }
         }
 
 
+        // Pre-allocate the tangent and bitangent data.
         AZStd::vector<AZ::Vector4>& tangents = blendShapeData->GetTangents();
         AZStd::vector<AZ::Vector4>& tangents = blendShapeData->GetTangents();
         AZStd::vector<AZ::Vector3>& bitangents = blendShapeData->GetBitangents();
         AZStd::vector<AZ::Vector3>& bitangents = blendShapeData->GetBitangents();
-        if (!tangents.empty() || !bitangents.empty())
-        {
-            AZ_TracePrintf(
-                AZ::SceneAPI::Utilities::WarningWindow, "Cannot generate tangents and bitangents because existing tangent or bitangent data has been found.\n");
-            return false;
-        }
-
-        // Pre-allocate the tangent and bitangent data.
         tangents.resize(blendShapeData->GetVertexCount());
         tangents.resize(blendShapeData->GetVertexCount());
         bitangents.resize(blendShapeData->GetVertexCount());
         bitangents.resize(blendShapeData->GetVertexCount());
 
 
@@ -114,10 +128,24 @@ namespace AZ::TangentGeneration::BlendShape::MikkT
         mikkInterface.m_getNormal           = GetNormal;
         mikkInterface.m_getNormal           = GetNormal;
         mikkInterface.m_getPosition         = GetPosition;
         mikkInterface.m_getPosition         = GetPosition;
         mikkInterface.m_getTexCoord         = GetTexCoord;
         mikkInterface.m_getTexCoord         = GetTexCoord;
-        mikkInterface.m_setTSpace           = SetTSpace;
-        mikkInterface.m_setTSpaceBasic      = nullptr;
         mikkInterface.m_getNumVerticesOfFace= GetNumVerticesOfFace;
         mikkInterface.m_getNumVerticesOfFace= GetNumVerticesOfFace;
 
 
+        switch (tSpaceMethod)
+        {
+            case AZ::SceneAPI::DataTypes::MikkTSpaceMethod::TSpaceBasic:
+            {
+                mikkInterface.m_setTSpace = nullptr;
+                mikkInterface.m_setTSpaceBasic = SetTSpaceBasic;
+                break;
+            }
+            default:
+            {
+                mikkInterface.m_setTSpace = SetTSpace;
+                mikkInterface.m_setTSpaceBasic = nullptr;
+                break;
+            }
+        }
+
         // Set the MikkT custom data.
         // Set the MikkT custom data.
         MikktCustomData customData;
         MikktCustomData customData;
         customData.m_blendShapeData = blendShapeData;
         customData.m_blendShapeData = blendShapeData;

+ 4 - 1
Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerators/BlendShapeMikkTGenerator.h

@@ -9,6 +9,7 @@
 #pragma once
 #pragma once
 
 
 #include <SceneAPI/SceneCore/Containers/Scene.h>
 #include <SceneAPI/SceneCore/Containers/Scene.h>
+#include <SceneAPI/SceneCore/DataTypes/GraphData/IMeshVertexBitangentData.h>
 
 
 namespace AZ::SceneData::GraphData
 namespace AZ::SceneData::GraphData
 {
 {
@@ -24,5 +25,7 @@ namespace AZ::TangentGeneration::BlendShape::MikkT
     };
     };
 
 
     // The main generation method.
     // The main generation method.
-    bool GenerateTangents(AZ::SceneData::GraphData::BlendShapeData* blendShapeData, size_t uvSetIndex);
+    bool GenerateTangents(AZ::SceneData::GraphData::BlendShapeData* blendShapeData,
+        size_t uvSetIndex,
+        AZ::SceneAPI::DataTypes::MikkTSpaceMethod tSpaceMethod = AZ::SceneAPI::DataTypes::MikkTSpaceMethod::TSpace);
 } // namespace AZ::TangentGeneration::MikkT
 } // namespace AZ::TangentGeneration::MikkT

+ 18 - 3
Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerators/MikkTGenerator.cpp

@@ -108,7 +108,8 @@ namespace AZ::TangentGeneration::Mesh::MikkT
     bool GenerateTangents(const AZ::SceneAPI::DataTypes::IMeshData* meshData,
     bool GenerateTangents(const AZ::SceneAPI::DataTypes::IMeshData* meshData,
         const AZ::SceneAPI::DataTypes::IMeshVertexUVData* uvData,
         const AZ::SceneAPI::DataTypes::IMeshVertexUVData* uvData,
         AZ::SceneAPI::DataTypes::IMeshVertexTangentData* outTangentData,
         AZ::SceneAPI::DataTypes::IMeshVertexTangentData* outTangentData,
-        AZ::SceneAPI::DataTypes::IMeshVertexBitangentData* outBitangentData)
+        AZ::SceneAPI::DataTypes::IMeshVertexBitangentData* outBitangentData,
+        AZ::SceneAPI::DataTypes::MikkTSpaceMethod tSpaceMethod)
     {
     {
         // Provide the MikkT interface.
         // Provide the MikkT interface.
         SMikkTSpaceInterface mikkInterface;
         SMikkTSpaceInterface mikkInterface;
@@ -116,10 +117,24 @@ namespace AZ::TangentGeneration::Mesh::MikkT
         mikkInterface.m_getNormal           = GetNormal;
         mikkInterface.m_getNormal           = GetNormal;
         mikkInterface.m_getPosition         = GetPosition;
         mikkInterface.m_getPosition         = GetPosition;
         mikkInterface.m_getTexCoord         = GetTexCoord;
         mikkInterface.m_getTexCoord         = GetTexCoord;
-        mikkInterface.m_setTSpace           = SetTSpace;
-        mikkInterface.m_setTSpaceBasic      = nullptr;//SetTSpaceBasic;
         mikkInterface.m_getNumVerticesOfFace= GetNumVerticesOfFace;
         mikkInterface.m_getNumVerticesOfFace= GetNumVerticesOfFace;
 
 
+        switch (tSpaceMethod)
+        {
+        case AZ::SceneAPI::DataTypes::MikkTSpaceMethod::TSpaceBasic:
+        {
+            mikkInterface.m_setTSpace = nullptr;
+            mikkInterface.m_setTSpaceBasic = SetTSpaceBasic;
+            break;
+        }
+        default:
+        {
+            mikkInterface.m_setTSpace = SetTSpace;
+            mikkInterface.m_setTSpaceBasic = nullptr;
+            break;
+        }
+        }
+
         // Set the MikkT custom data.
         // Set the MikkT custom data.
         MikktCustomData customData;
         MikktCustomData customData;
         customData.m_meshData       = meshData;
         customData.m_meshData       = meshData;

+ 3 - 1
Gems/SceneProcessing/Code/Source/Generation/Components/TangentGenerator/TangentGenerators/MikkTGenerator.h

@@ -8,6 +8,7 @@
 
 
 #pragma once
 #pragma once
 
 
+#include <SceneAPI/SceneCore/DataTypes/GraphData/IMeshVertexBitangentData.h>
 #include <SceneAPI/SceneCore/Containers/Scene.h>
 #include <SceneAPI/SceneCore/Containers/Scene.h>
 
 
 namespace AZ::SceneAPI::DataTypes { class IMeshData; }
 namespace AZ::SceneAPI::DataTypes { class IMeshData; }
@@ -28,5 +29,6 @@ namespace AZ::TangentGeneration::Mesh::MikkT
     bool GenerateTangents(const AZ::SceneAPI::DataTypes::IMeshData* meshData,
     bool GenerateTangents(const AZ::SceneAPI::DataTypes::IMeshData* meshData,
         const AZ::SceneAPI::DataTypes::IMeshVertexUVData* uvData,
         const AZ::SceneAPI::DataTypes::IMeshVertexUVData* uvData,
         AZ::SceneAPI::DataTypes::IMeshVertexTangentData* outTangentData,
         AZ::SceneAPI::DataTypes::IMeshVertexTangentData* outTangentData,
-        AZ::SceneAPI::DataTypes::IMeshVertexBitangentData* outBitangentData);
+        AZ::SceneAPI::DataTypes::IMeshVertexBitangentData* outBitangentData,
+        AZ::SceneAPI::DataTypes::MikkTSpaceMethod tSpaceMethod = AZ::SceneAPI::DataTypes::MikkTSpaceMethod::TSpace);
 } // namespace AZ::TangentGeneration::MikkT
 } // namespace AZ::TangentGeneration::MikkT