Integrating up through commit 90f050496

This commit is contained in:
alexpete
2021-04-07 14:03:29 -07:00
parent 8f2ed080a9
commit c2cbd430fe
2694 changed files with 285622 additions and 176874 deletions
@@ -12,6 +12,7 @@
#include <Generation/Components/TangentGenerator/TangentGenerateComponent.h>
#include <Generation/Components/TangentGenerator/TangentGenerators/MikkTGenerator.h>
#include <Generation/Components/TangentGenerator/TangentGenerators/BlendShapeMikkTGenerator.h>
#include <SceneAPI/SceneCore/DataTypes/Groups/IGroup.h>
#include <SceneAPI/SceneCore/DataTypes/GraphData/IMeshVertexUVData.h>
@@ -28,6 +29,7 @@
#include <SceneAPI/SceneCore/Utilities/Reporting.h>
#include <SceneAPI/SceneCore/DataTypes/DataTypeUtilities.h>
#include <SceneAPI/SceneCore/DataTypes/GraphData/IMeshData.h>
#include <SceneAPI/SceneData/GraphData/BlendShapeData.h>
#include <SceneAPI/SceneData/GraphData/MeshVertexBitangentData.h>
#include <SceneAPI/SceneData/GraphData/MeshVertexTangentData.h>
@@ -169,6 +171,24 @@ namespace AZ::SceneGenerationComponents
}
}
void TangentGenerateComponent::FindBlendShapes(
AZ::SceneAPI::Containers::SceneGraph& graph, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex,
AZStd::vector<AZ::SceneData::GraphData::BlendShapeData*>& outBlendShapes) const
{
const auto nameContentView = AZ::SceneAPI::Containers::Views::MakePairView(graph.GetNameStorage(), graph.GetContentStorage());
auto meshChildView = AZ::SceneAPI::Containers::Views::MakeSceneGraphChildView<AZ::SceneAPI::Containers::Views::AcceptEndPointsOnly>(
graph, nodeIndex, nameContentView.begin(), true);
for (auto child = meshChildView.begin(); child != meshChildView.end(); ++child)
{
AZ::SceneData::GraphData::BlendShapeData* blendShape =
azrtti_cast<AZ::SceneData::GraphData::BlendShapeData*>(child->second.get());
if (blendShape)
{
outBlendShapes.emplace_back(blendShape);
}
}
}
bool TangentGenerateComponent::GenerateTangentsForMesh(AZ::SceneAPI::Containers::Scene& scene, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, AZ::SceneAPI::DataTypes::IMeshData* meshData)
{
@@ -202,6 +222,10 @@ namespace AZ::SceneGenerationComponents
return true;
}
// 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;
FindBlendShapes(graph, nodeIndex, blendShapes);
// Generate all the tangent spaces we need.
// Do this for every UV set.
bool allSuccess = true;
@@ -222,7 +246,12 @@ namespace AZ::SceneGenerationComponents
// Generate using MikkT space.
case AZ::SceneAPI::DataTypes::TangentSpace::MikkT:
{
allSuccess &= AZ::TangentGeneration::MikkT::GenerateTangents(scene.GetManifest(), graph, nodeIndex, const_cast<AZ::SceneAPI::DataTypes::IMeshData*>(meshData), uvSetIndex);
allSuccess &= AZ::TangentGeneration::Mesh::MikkT::GenerateTangents(
scene.GetManifest(), graph, nodeIndex, const_cast<AZ::SceneAPI::DataTypes::IMeshData*>(meshData), uvSetIndex);
for (AZ::SceneData::GraphData::BlendShapeData* blendShape : blendShapes)
{
allSuccess &= AZ::TangentGeneration::BlendShape::MikkT::GenerateTangents(blendShape, uvSetIndex);
}
}
break;
@@ -21,6 +21,10 @@ namespace AZ::SceneAPI::DataTypes { class IMeshVertexUVData; }
namespace AZ::SceneAPI::DataTypes { class IMeshVertexTangentData; }
namespace AZ::SceneAPI::DataTypes { class IMeshVertexBitangentData; }
namespace AZ::SceneAPI::DataTypes { enum class TangentSpace; }
namespace AZ::SceneData::GraphData
{
class BlendShapeData;
}
namespace AZ::SceneGenerationComponents
{
@@ -56,6 +60,9 @@ namespace AZ::SceneGenerationComponents
AZ::SceneAPI::Events::ProcessingResult GenerateTangentData(TangentGenerateContext& context);
private:
void FindBlendShapes(
AZ::SceneAPI::Containers::SceneGraph& graph, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex,
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);
void UpdateFbxTangentWValues(AZ::SceneAPI::Containers::SceneGraph& graph, const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& nodeIndex, const AZ::SceneAPI::DataTypes::IMeshData* meshData);
AZStd::vector<AZ::SceneAPI::DataTypes::TangentSpace> CollectRequiredTangentSpaces(const AZ::SceneAPI::Containers::Scene& scene) const;
@@ -0,0 +1,142 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <Generation/Components/TangentGenerator/TangentGenerators/BlendShapeMikkTGenerator.h>
#include <Generation/Components/TangentGenerator/TangentGenerateComponent.h>
#include <SceneAPI/SceneCore/Utilities/Reporting.h>
#include <SceneAPI/SceneData/GraphData/BlendShapeData.h>
#include <AzCore/Math/Vector3.h>
#include <AzCore/Math/Vector4.h>
#include <mikkelsen/mikktspace.h>
namespace AZ::TangentGeneration::BlendShape::MikkT
{
// Returns the number of triangles in the mesh.
int GetNumFaces(const SMikkTSpaceContext* context)
{
MikktCustomData* customData = static_cast<MikktCustomData*>(context->m_pUserData);
return customData->m_blendShapeData->GetFaceCount();
}
int GetNumVerticesOfFace([[maybe_unused]] const SMikkTSpaceContext* context, [[maybe_unused]] const int face)
{
return 3;
}
void GetPosition(const SMikkTSpaceContext* context, float posOut[], const int face, const int vert)
{
MikktCustomData* customData = static_cast<MikktCustomData*>(context->m_pUserData);
const AZ::u32 vertexIndex = customData->m_blendShapeData->GetFaceVertexIndex(face, vert);
const AZ::Vector3& pos = customData->m_blendShapeData->GetPosition(vertexIndex);
posOut[0] = pos.GetX();
posOut[1] = pos.GetY();
posOut[2] = pos.GetZ();
}
void GetNormal(const SMikkTSpaceContext* context, float normOut[], const int face, const int vert)
{
MikktCustomData* customData = static_cast<MikktCustomData*>(context->m_pUserData);
const AZ::u32 vertexIndex = customData->m_blendShapeData->GetFaceVertexIndex(face, vert);
const AZ::Vector3 normal = customData->m_blendShapeData->GetNormal(vertexIndex).GetNormalizedSafe();
normOut[0] = normal.GetX();
normOut[1] = normal.GetY();
normOut[2] = normal.GetZ();
}
void GetTexCoord(const SMikkTSpaceContext* context, float texOut[], const int face, const int vert)
{
MikktCustomData* customData = static_cast<MikktCustomData*>(context->m_pUserData);
const AZ::u32 vertexIndex = customData->m_blendShapeData->GetFaceVertexIndex(face, vert);
const AZ::Vector2& uv = customData->m_blendShapeData->GetUV(vertexIndex, customData->m_uvSetIndex);
texOut[0] = uv.GetX();
texOut[1] = uv.GetY();
}
// 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.
// bitangent is the "real" bitangent and thus may not be perpendicular to tangent.
// However, both are perpendicular to the vertex normal.
// For normal maps it is sufficient to use the following simplified version of the bitangent which is generated at pixel/vertex level.
// signValue = isOrientationPreserving ? 1.0f : -1.0f;
// bitangent = signValue * cross(vN, tangent);
void SetTSpace(const SMikkTSpaceContext* context, const float tangent[], const float bitangent[], const float magS, const float magT, const tbool isOrientationPreserving, const int face, const int vert)
{
MikktCustomData* customData = static_cast<MikktCustomData*>(context->m_pUserData);
const AZ::u32 vertexIndex = customData->m_blendShapeData->GetFaceVertexIndex(face, vert);
const float flipSign = isOrientationPreserving ? 1.0f : -1.0f;
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);
// Set the tangent and bitangent back to the blendshape
AZStd::vector<AZ::Vector4>& tangents = customData->m_blendShapeData->GetTangents();
AZStd::vector<AZ::Vector3>& bitangents = customData->m_blendShapeData->GetBitangents();
tangents[vertexIndex] = tangentVec;
bitangents[vertexIndex] = bitangentVec;
}
bool GenerateTangents(AZ::SceneData::GraphData::BlendShapeData* blendShapeData, size_t uvSetIndex)
{
// Create tangent and bitangent data sets and relate them to the given UV set.
const AZStd::vector<AZ::Vector2>& uvSet = blendShapeData->GetUVs(uvSetIndex);
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);
return false;
}
AZStd::vector<AZ::Vector4>& tangents = blendShapeData->GetTangents();
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());
bitangents.resize(blendShapeData->GetVertexCount());
//----------------------------------
// Provide the MikkT interface.
SMikkTSpaceInterface mikkInterface;
mikkInterface.m_getNumFaces = GetNumFaces;
mikkInterface.m_getNormal = GetNormal;
mikkInterface.m_getPosition = GetPosition;
mikkInterface.m_getTexCoord = GetTexCoord;
mikkInterface.m_setTSpace = SetTSpace;
mikkInterface.m_setTSpaceBasic = nullptr;
mikkInterface.m_getNumVerticesOfFace= GetNumVerticesOfFace;
// Set the MikkT custom data.
MikktCustomData customData;
customData.m_blendShapeData = blendShapeData;
customData.m_uvSetIndex = uvSetIndex;
// Generate the tangents.
SMikkTSpaceContext mikkContext;
mikkContext.m_pInterface = &mikkInterface;
mikkContext.m_pUserData = &customData;
if (genTangSpaceDefault(&mikkContext) == 0)
{
AZ_TracePrintf(AZ::SceneAPI::Utilities::ErrorWindow, "Failed to generate tangents and bitangents using MikkT for blend shape, because MikkT reported failure!\n");
return false;
}
return true;
}
} // namespace AZ::TangentGeneration::MikkT
@@ -0,0 +1,32 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <SceneAPI/SceneCore/Containers/Scene.h>
namespace AZ::SceneData::GraphData
{
class BlendShapeData;
}
namespace AZ::TangentGeneration::BlendShape::MikkT
{
struct MikktCustomData
{
AZ::SceneData::GraphData::BlendShapeData* m_blendShapeData;
size_t m_uvSetIndex;
};
// The main generation method.
bool GenerateTangents(AZ::SceneData::GraphData::BlendShapeData* blendShapeData, size_t uvSetIndex);
} // namespace AZ::TangentGeneration::MikkT
@@ -27,7 +27,7 @@
#include <mikkelsen/mikktspace.h>
namespace AZ::TangentGeneration::MikkT
namespace AZ::TangentGeneration::Mesh::MikkT
{
// Returns the number of triangles in the mesh.
int GetNumFaces(const SMikkTSpaceContext* context)
@@ -19,7 +19,7 @@ namespace AZ::SceneAPI::DataTypes { class IMeshVertexUVData; }
namespace AZ::SceneAPI::DataTypes { class IMeshVertexTangentData; }
namespace AZ::SceneAPI::DataTypes { class IMeshVertexBitangentData; }
namespace AZ::TangentGeneration::MikkT
namespace AZ::TangentGeneration::Mesh::MikkT
{
struct MikktCustomData
{
@@ -48,7 +48,7 @@ namespace SceneBuilder
builderDescriptor.m_createJobFunction = AZStd::bind(&SceneBuilderWorker::CreateJobs, &m_sceneBuilder, AZStd::placeholders::_1, AZStd::placeholders::_2);
builderDescriptor.m_processJobFunction = AZStd::bind(&SceneBuilderWorker::ProcessJob, &m_sceneBuilder, AZStd::placeholders::_1, AZStd::placeholders::_2);
builderDescriptor.m_version = 4; // bump this to rebuild everything.
builderDescriptor.m_version = 5; // bump this to rebuild everything.
builderDescriptor.m_analysisFingerprint = m_sceneBuilder.GetFingerprint(); // bump this to at least re-analyze everything.
m_sceneBuilder.BusConnect(builderDescriptor.m_busId);