Merge pull request #1382 from aws-lumberyard-dev/Helios_TransformImporterFixV2_stabilization_2106
AssImp: Transform Importer Fix V2
This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user