Transform node animations ignored (#2160)

* Fixing user asset issue having a transform node as root rather than a bone making the whole character not animate.
* Enabled the ability to export animations for transform nodes.

Signed-off-by: Benjamin Jillich <jillich@amazon.com>
This commit is contained in:
Benjamin Jillich
2021-07-16 04:47:47 -07:00
committed by GitHub
parent 18eba48429
commit d16b810075
2 changed files with 45 additions and 16 deletions
@@ -11,7 +11,6 @@
#include <SceneAPI/SceneCore/Containers/Utilities/Filters.h>
#include <SceneAPI/SceneCore/Utilities/Reporting.h>
#include <SceneAPI/SceneCore/DataTypes/DataTypeUtilities.h>
#include <SceneAPI/SceneCore/DataTypes/GraphData/IBoneData.h>
#include <SceneAPI/SceneCore/DataTypes/GraphData/IAnimationData.h>
#include <SceneAPI/SceneData/Rules/CoordinateSystemRule.h>
@@ -166,6 +165,34 @@ namespace EMotionFX
return finalMotionData;
}
AZ::SceneAPI::DataTypes::MatrixType MotionDataBuilder::GetLocalSpaceBindPose(const SceneContainers::SceneGraph& sceneGraph,
const SceneContainers::SceneGraph::NodeIndex rootBoneNodeIndex,
const SceneContainers::SceneGraph::NodeIndex nodeIndex,
const SceneDataTypes::ITransform* transform,
const SceneDataTypes::IBoneData* bone) const
{
if (nodeIndex != rootBoneNodeIndex)
{
const SceneContainers::SceneGraph::NodeIndex parentNodeIndex = sceneGraph.GetNodeParent(nodeIndex);
const SceneDataTypes::IGraphObject* parentNode = sceneGraph.GetNodeContent(parentNodeIndex).get();
if (const SceneDataTypes::IBoneData* parentBone = azrtti_cast<const SceneDataTypes::IBoneData*>(parentNode))
{
return parentBone->GetWorldTransform().GetInverseFull() * bone->GetWorldTransform();
}
}
if (bone)
{
return bone->GetWorldTransform();
}
else if (transform)
{
return transform->GetMatrix();
}
return AZ::SceneAPI::DataTypes::MatrixType::CreateIdentity();
}
AZ::SceneAPI::Events::ProcessingResult MotionDataBuilder::BuildMotionData(MotionDataBuilderContext& context)
{
if (context.m_phase != AZ::RC::Phase::Filling)
@@ -220,8 +247,10 @@ namespace EMotionFX
continue;
}
AZStd::shared_ptr<const SceneDataTypes::IBoneData> nodeBone = azrtti_cast<const SceneDataTypes::IBoneData*>(it->second);
if (!nodeBone)
// Check if we are dealing with a transform node or a bone and only recurse down the node hierarchy in this case.
const SceneDataTypes::IBoneData* nodeBone = azrtti_cast<const SceneDataTypes::IBoneData*>(it->second.get());
const SceneDataTypes::ITransform* nodeTransform = azrtti_cast<const SceneDataTypes::ITransform*>(it->second.get());
if (!nodeBone && !nodeTransform)
{
it.IgnoreNodeDescendants();
continue;
@@ -289,24 +318,13 @@ namespace EMotionFX
// Get the bind pose transform in local space.
using SceneAPIMatrixType = AZ::SceneAPI::DataTypes::MatrixType;
SceneAPIMatrixType bindSpaceLocalTransform;
const SceneContainers::SceneGraph::NodeIndex parentIndex = graph.GetNodeParent(boneNodeIndex);
if (boneNodeIndex != rootBoneNodeIndex)
{
auto parentNode = graph.GetNodeContent(parentIndex);
AZStd::shared_ptr<const SceneDataTypes::IBoneData> parentNodeBone = azrtti_cast<const SceneDataTypes::IBoneData*>(parentNode);
bindSpaceLocalTransform = parentNodeBone->GetWorldTransform().GetInverseFull() * nodeBone->GetWorldTransform();
}
else
{
bindSpaceLocalTransform = nodeBone->GetWorldTransform();
}
const SceneAPIMatrixType bindSpaceLocalTransform = GetLocalSpaceBindPose(graph, rootBoneNodeIndex, boneNodeIndex, nodeTransform, nodeBone);
// Get the time step and make sure it didn't change compared to other joint animations.
const double timeStep = animation->GetTimeStepBetweenFrames();
lowestTimeStep = AZ::GetMin<double>(timeStep, lowestTimeStep);
SceneAPIMatrixType sampleFrameTransformInverse;
AZ::SceneAPI::DataTypes::MatrixType sampleFrameTransformInverse;
if (additiveRule)
{
size_t sampleFrameIndex = additiveRule->GetSampleFrameIndex();
@@ -9,6 +9,9 @@
#include <SceneAPI/SceneCore/Components/ExportingComponent.h>
#include <SceneAPI/SceneCore/Containers/Scene.h>
#include <SceneAPI/SceneCore/Containers/SceneGraph.h>
#include <SceneAPI/SceneCore/DataTypes/GraphData/IBoneData.h>
#include <SceneAPI/SceneCore/DataTypes/GraphData/ITransform.h>
namespace EMotionFX
{
@@ -28,6 +31,14 @@ namespace EMotionFX
static void Reflect(AZ::ReflectContext* context);
AZ::SceneAPI::Events::ProcessingResult BuildMotionData(MotionDataBuilderContext& context);
private:
//! Get the bind pose transform in local space.
AZ::SceneAPI::DataTypes::MatrixType GetLocalSpaceBindPose(const AZ::SceneAPI::Containers::SceneGraph& sceneGraph,
const AZ::SceneAPI::Containers::SceneGraph::NodeIndex rootBoneNodeIndex,
const AZ::SceneAPI::Containers::SceneGraph::NodeIndex nodeIndex,
const AZ::SceneAPI::DataTypes::ITransform* transform,
const AZ::SceneAPI::DataTypes::IBoneData* bone) const;
};
} // namespace Pipeline
} // namespace EMotionFX