From 0603fee04e29b6c09c7bf632b38a074f38f6c308 Mon Sep 17 00:00:00 2001 From: Benjamin Jillich <43751992+amzn-jillich@users.noreply.github.com> Date: Thu, 29 Apr 2021 12:20:20 +0200 Subject: [PATCH] [LYN-3072] TQO Animation: "Retarget Motion" on Simple Motion sends Asserts (#358) * Added a check to only apply retargeting to animated joints. Joints that the motion does not animate won't have a valid motion data link and thus retargeting can't be applied. * The check cannot be applied at a level above as we still need to adjust the translation for root nodes, even for the ones that the motion does not animate. --- .../Source/MotionData/MotionData.cpp | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/MotionData.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/MotionData.cpp index 834f4f6ef4..8c5083e8e9 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/MotionData.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/MotionData.cpp @@ -461,16 +461,17 @@ namespace EMotionFX { AZ_Assert(motionLinkData, "Expecting valid motionLinkData pointer."); + const Pose* bindPose = actorInstance->GetTransformData()->GetBindPose(); + const AZStd::vector& jointLinks = motionLinkData->GetJointDataLinks(); + // Special case handling on translation of root nodes. // Scale the translation amount based on the height difference between the bind pose height of the // retarget root node and the bind pose of that node stored in the motion. // All other nodes get their translation data displaced based on the position difference between the // parent relative space positions in the actor instance's bind pose and the motion bind pose. - const Pose* bindPose = actorInstance->GetTransformData()->GetBindPose(); const Actor* actor = actorInstance->GetActor(); const AZ::u32 retargetRootIndex = actor->GetRetargetRootNodeIndex(); const Node* joint = actor->GetSkeleton()->GetNode(jointIndex); - const AZStd::vector& jointLinks = motionLinkData->GetJointDataLinks(); bool needsDisplacement = true; if ((retargetRootIndex == jointIndex || joint->GetIsRootNode()) && retargetRootIndex != InvalidIndex32) { @@ -487,20 +488,23 @@ namespace EMotionFX } } - const Transform& bindPoseTransform = bindPose->GetLocalSpaceTransform(jointIndex); const AZ::u16 jointDataIndex = jointLinks[jointIndex]; - const Transform& motionBindPose = m_staticJointData[jointDataIndex].m_bindTransform; - if (needsDisplacement) + if (jointDataIndex != InvalidIndex16) { - const AZ::Vector3 displacement = bindPoseTransform.mPosition - motionBindPose.mPosition; - inOutTransform.mPosition += displacement; - } + const Transform& bindPoseTransform = bindPose->GetLocalSpaceTransform(jointIndex); + const Transform& motionBindPose = m_staticJointData[jointDataIndex].m_bindTransform; + if (needsDisplacement) + { + const AZ::Vector3 displacement = bindPoseTransform.mPosition - motionBindPose.mPosition; + inOutTransform.mPosition += displacement; + } - EMFX_SCALECODE - ( - const AZ::Vector3 scaleOffset = bindPoseTransform.mScale - motionBindPose.mScale; - inOutTransform.mScale += scaleOffset; - ) + EMFX_SCALECODE + ( + const AZ::Vector3 scaleOffset = bindPoseTransform.mScale - motionBindPose.mScale; + inOutTransform.mScale += scaleOffset; + ) + } } // Based on a given time value, find the two keyframes to interpolate between, and calculate the t value, which is the interpolation weight between 0 and 1.