Helios - LYN-3250 - Fixed morph targets for meshes that had multiple … (#696)

* Helios - LYN-3250 - Fixed morph targets for meshes that had multiple materials (#374)

Fixed morph targets for meshes that had multiple materials and were split by AssImp: Recombined them into one mesh in the O3DE scene graph, so the behavior would match FBX SDK.
This commit is contained in:
AMZN-stankowi
2021-05-19 13:02:31 -07:00
committed by GitHub
parent 25e811ff6c
commit f779821ac0
25 changed files with 457 additions and 281 deletions
@@ -13,6 +13,7 @@
#include <assimp/mesh.h>
#include <assimp/scene.h>
#include <AzCore/Casting/numeric_cast.h>
#include <AzCore/std/numeric.h>
#include <AzCore/std/smart_ptr/make_shared.h>
#include <SceneAPI/FbxSceneBuilder/FbxSceneSystem.h>
#include <SceneAPI/FbxSceneBuilder/ImportContexts/AssImpImportContexts.h>
@@ -24,7 +25,7 @@
namespace AZ::SceneAPI::FbxSceneBuilder
{
bool BuildSceneMeshFromAssImpMesh(aiNode* currentNode, const aiScene* scene, const FbxSceneSystem& sceneSystem, AZStd::vector<AZStd::shared_ptr<DataTypes::IGraphObject>>& meshes,
bool BuildSceneMeshFromAssImpMesh(const aiNode* currentNode, const aiScene* scene, const FbxSceneSystem& sceneSystem, AZStd::vector<AZStd::shared_ptr<DataTypes::IGraphObject>>& meshes,
const AZStd::function<AZStd::shared_ptr<SceneData::GraphData::MeshData>()>& makeMeshFunc)
{
AZStd::unordered_map<int, int> assImpMatIndexToLYIndex;
@@ -34,17 +35,18 @@ namespace AZ::SceneAPI::FbxSceneBuilder
{
return false;
}
auto newMesh = makeMeshFunc();
newMesh->SetUnitSizeInMeters(sceneSystem.GetUnitSizeInMeters());
newMesh->SetOriginalUnitSizeInMeters(sceneSystem.GetOriginalUnitSizeInMeters());
// AssImp separates meshes that have multiple materials.
// This code re-combines them to match previous FBX SDK behavior,
// so they can be separated by engine code instead.
int vertOffset = 0;
for (int m = 0; m < currentNode->mNumMeshes; ++m)
{
auto newMesh = makeMeshFunc();
newMesh->SetUnitSizeInMeters(sceneSystem.GetUnitSizeInMeters());
newMesh->SetOriginalUnitSizeInMeters(sceneSystem.GetOriginalUnitSizeInMeters());
newMesh->SetSdkMeshIndex(m);
aiMesh* mesh = scene->mMeshes[currentNode->mMeshes[m]];
const aiMesh* mesh = scene->mMeshes[currentNode->mMeshes[m]];
// Lumberyard materials are created in order based on mesh references in the scene
if (assImpMatIndexToLYIndex.find(mesh->mMaterialIndex) == assImpMatIndexToLYIndex.end())
@@ -59,7 +61,7 @@ namespace AZ::SceneAPI::FbxSceneBuilder
sceneSystem.SwapVec3ForUpAxis(vertex);
sceneSystem.ConvertUnit(vertex);
newMesh->AddPosition(vertex);
newMesh->SetVertexIndexToControlPointIndexMap(vertIdx, vertIdx);
newMesh->SetVertexIndexToControlPointIndexMap(vertIdx + vertOffset, vertIdx + vertOffset);
if (mesh->HasNormals())
{
@@ -86,14 +88,15 @@ namespace AZ::SceneAPI::FbxSceneBuilder
}
for (int idx = 0; idx < face.mNumIndices; ++idx)
{
meshFace.vertexIndex[idx] = face.mIndices[idx];
meshFace.vertexIndex[idx] = face.mIndices[idx] + vertOffset;
}
newMesh->AddFace(meshFace, assImpMatIndexToLYIndex[mesh->mMaterialIndex]);
}
vertOffset += mesh->mNumVertices;
meshes.push_back(newMesh);
}
meshes.push_back(newMesh);
return true;
}
@@ -127,4 +130,13 @@ namespace AZ::SceneAPI::FbxSceneBuilder
azrtti_cast<const SceneData::GraphData::MeshData* const>(parentData);
return AZ::Success(parentMeshData);
}
uint64_t GetVertexCountForAllMeshesOnNode(const aiNode& node, const aiScene& scene)
{
return AZStd::accumulate(node.mMeshes, node.mMeshes + node.mNumMeshes, uint64_t{ 0u },
[&scene](auto runningTotal, unsigned int meshIndex)
{
return runningTotal + scene.mMeshes[meshIndex]->mNumVertices;
});
}
}