Merge pull request #1382 from aws-lumberyard-dev/Helios_TransformImporterFixV2_stabilization_2106

AssImp: Transform Importer Fix V2
This commit is contained in:
amzn-mike
2021-06-21 15:46:10 -05:00
committed by GitHub
4 changed files with 75 additions and 46 deletions
@@ -255,7 +255,6 @@ namespace AZ
{
return AZStd::make_pair(animation, anim);
}
Events::ProcessingResult AssImpAnimationImporter::ImportAnimation(AssImpSceneNodeAppendedContext& context)
{
AZ_TraceContext("Importer", "Animation");
@@ -447,7 +446,22 @@ namespace AZ
return combinedAnimationResult.GetResult();
}
decltype(boneAnimations) parentFillerAnimations;
AZStd::unordered_set<AZStd::string> boneList;
for (int meshIndex = 0; meshIndex < scene->mNumMeshes; ++meshIndex)
{
aiMesh* mesh = scene->mMeshes[meshIndex];
for (int boneIndex = 0; boneIndex < mesh->mNumBones; ++boneIndex)
{
aiBone* bone = mesh->mBones[boneIndex];
boneList.insert(bone->mName.C_Str());
}
}
decltype(boneAnimations) fillerAnimations;
// Go through all the animations and make sure we create animations for bones who's parents don't have an animation
for (auto&& anim : boneAnimations)
@@ -459,8 +473,8 @@ namespace AZ
{
if (!IsPivotNode(parent->mName))
{
if (boneAnimations.find(parent->mName.C_Str()) == boneAnimations.end() &&
parentFillerAnimations.find(parent->mName.C_Str()) == parentFillerAnimations.end())
if (!boneAnimations.contains(parent->mName.C_Str()) &&
!fillerAnimations.contains(parent->mName.C_Str()))
{
// Create 1 key for each type that just copies the current transform
ConsolidatedNodeAnim emptyAnimation;
@@ -472,7 +486,7 @@ namespace AZ
globalTransform.Decompose(scale, rotation, position);
emptyAnimation.mNumRotationKeys = emptyAnimation.mNumPositionKeys = emptyAnimation.mNumScalingKeys = 1;
emptyAnimation.m_ownedPositionKeys.emplace_back(0, position);
emptyAnimation.mPositionKeys = emptyAnimation.m_ownedPositionKeys.data();
@@ -481,9 +495,9 @@ namespace AZ
emptyAnimation.m_ownedScalingKeys.emplace_back(0, scale);
emptyAnimation.mScalingKeys = emptyAnimation.m_ownedScalingKeys.data();
parentFillerAnimations.insert(
AZStd::make_pair(parent->mName.C_Str(), AZStd::make_pair(anim.second.first, AZStd::move(emptyAnimation))));
fillerAnimations.insert(AZStd::make_pair(
parent->mName.C_Str(), AZStd::make_pair(anim.second.first, AZStd::move(emptyAnimation))));
}
}
@@ -491,7 +505,7 @@ namespace AZ
}
}
boneAnimations.insert(AZStd::make_move_iterator(parentFillerAnimations.begin()), AZStd::make_move_iterator(parentFillerAnimations.end()));
boneAnimations.insert(AZStd::make_move_iterator(fillerAnimations.begin()), AZStd::make_move_iterator(fillerAnimations.end()));
auto animItr = boneAnimations.equal_range(currentNode->mName.C_Str());
@@ -98,6 +98,20 @@ namespace AZ
}
}
aiMatrix4x4 CalculateWorldTransform(const aiNode* currentNode)
{
aiMatrix4x4 transform = {};
const aiNode* iteratingNode = currentNode;
while (iteratingNode)
{
transform = iteratingNode->mTransformation * transform;
iteratingNode = iteratingNode->mParent;
}
return transform;
}
Events::ProcessingResult AssImpBoneImporter::ImportBone(AssImpNodeEncounteredContext& context)
{
AZ_TraceContext("Importer", "Bone");
@@ -111,12 +125,7 @@ namespace AZ
}
bool isBone = false;
if (NodeParentIsOfType(context.m_scene.GetGraph(), context.m_currentGraphPosition, DataTypes::IBoneData::TYPEINFO_Uuid()))
{
isBone = true;
}
else
{
AZStd::unordered_map<AZStd::string, const aiNode*> mainBoneList;
AZStd::unordered_map<AZStd::string, const aiBone*> boneLookup;
@@ -170,15 +179,8 @@ namespace AZ
{
createdBoneData = AZStd::make_shared<SceneData::GraphData::RootBoneData>();
}
aiMatrix4x4 transform = currentNode->mTransformation;
const aiNode* parent = currentNode->mParent;
while (parent)
{
transform = parent->mTransformation * transform;
parent = parent->mParent;
}
aiMatrix4x4 transform = CalculateWorldTransform(currentNode);
SceneAPI::DataTypes::MatrixType globalTransform = AssImpSDKWrapper::AssImpTypeConverter::ToTransform(transform);
@@ -31,7 +31,7 @@ namespace AZ
~AssImpBoneImporter() override = default;
static void Reflect(ReflectContext* context);
Events::ProcessingResult ImportBone(AssImpNodeEncounteredContext& context);
};
} // namespace FbxSceneBuilder
@@ -46,8 +46,9 @@ namespace AZ
serializeContext->Class<AssImpTransformImporter, SceneCore::LoadingComponent>()->Version(1);
}
}
void GetAllBones(const aiScene* scene, AZStd::unordered_map<AZStd::string, const aiBone*>& boneLookup)
void GetAllBones(
const aiScene* scene, AZStd::unordered_multimap<AZStd::string, const aiBone*>& boneLookup)
{
for (unsigned meshIndex = 0; meshIndex < scene->mNumMeshes; ++meshIndex)
{
@@ -57,7 +58,7 @@ namespace AZ
{
const aiBone* bone = mesh->mBones[boneIndex];
boneLookup[bone->mName.C_Str()] = bone;
boneLookup.emplace(bone->mName.C_Str(), bone);
}
}
}
@@ -73,41 +74,53 @@ namespace AZ
return Events::ProcessingResult::Ignored;
}
AZStd::unordered_map<AZStd::string, const aiBone*> boneLookup;
AZStd::unordered_multimap<AZStd::string, const aiBone*> boneLookup;
GetAllBones(scene, boneLookup);
auto boneIterator = boneLookup.find(currentNode->mName.C_Str());
const bool isBone = boneIterator != boneLookup.end();
aiMatrix4x4 combinedTransform;
DataTypes::MatrixType localTransform;
if (isBone)
{
auto parentNode = currentNode->mParent;
AZStd::vector<DataTypes::MatrixType> offsets, inverseOffsets;
auto iteratingNode = currentNode;
aiMatrix4x4 offsetMatrix = boneIterator->second->mOffsetMatrix;
aiMatrix4x4 parentOffset {};
auto parentBoneIterator = boneLookup.find(parentNode->mName.C_Str());
if (parentNode && parentBoneIterator != boneLookup.end())
while (iteratingNode && boneLookup.count(iteratingNode->mName.C_Str()))
{
const auto& parentBone = parentBoneIterator->second;
AZStd::string name = iteratingNode->mName.C_Str();
parentOffset = parentBone->mOffsetMatrix;
auto range = boneLookup.equal_range(name);
if (range.first != range.second)
{
// There can be multiple offsetMatrices for a given bone, we're only interested in grabbing the first one
auto boneFirstOffsetMatrix = range.first->second->mOffsetMatrix;
auto azMat = AssImpSDKWrapper::AssImpTypeConverter::ToTransform(boneFirstOffsetMatrix);
offsets.push_back(azMat);
inverseOffsets.push_back(azMat.GetInverseFull());
}
iteratingNode = iteratingNode->mParent;
}
auto inverseOffset = offsetMatrix;
inverseOffset.Inverse();
combinedTransform = parentOffset * inverseOffset;
localTransform =
offsets.at(AZ::GetMin(offsets.size()-1, static_cast<decltype(offsets.size())>(1))) // parent bone offset, or if there is no parent, then current node offset
* inverseOffsets.at(inverseOffsets.size() - 1) // Inverse of root bone offset
* offsets.at(offsets.size() - 1) // Root bone offset
* inverseOffsets.at(0); // Inverse of current node offset
}
else
{
combinedTransform = GetConcatenatedLocalTransform(currentNode);
localTransform = AssImpSDKWrapper::AssImpTypeConverter::ToTransform(GetConcatenatedLocalTransform(currentNode));
}
DataTypes::MatrixType localTransform = AssImpSDKWrapper::AssImpTypeConverter::ToTransform(combinedTransform);
// Don't bother adding a node with the identity matrix
if (localTransform == DataTypes::MatrixType::Identity())
{
return Events::ProcessingResult::Ignored;
}
context.m_sourceSceneSystem.SwapTransformForUpAxis(localTransform);
context.m_sourceSceneSystem.ConvertUnit(localTransform);