Apply delta world rotation in custom SkelControl

Hi,

I’m trying to apply a world rotation (mocap data) to a bone in a custom SkelControl as a rotation away from a known pose (in this case the A-Pose). The problem I’m having is that as the first SkelControl is updated the ComponentPose updates so I can no longer get access to the original A-Pose.

Here is the code:

void FAnimNode_SynBoneTransform::EvaluateBoneTransforms(USkeletalMeshComponent* SkelComp, FCSPose<FCompactPose>& MeshBases, TArray<FBoneTransform>& OutBoneTransforms)
{
	checkSlow(OutBoneTransforms.Num() == 0);

	// Get the anim instance
	USynertialAnimInstance * Animation = Cast<USynertialAnimInstance>(SkelComp->GetAnimInstance());
	if (!Animation) return;

	// Get mocap quat
	FQuat synQuat = Animation->mocapQuats[SynBoneID];
	if (synQuat.IsNormalized() == false) return;

	// Get Bone
	const FBoneContainer BoneContainer = MeshBases.GetPose().GetBoneContainer();
	FCompactPoseBoneIndex compactBoneIndex = TargetBone.GetCompactPoseIndex(BoneContainer);
	FTransform OutBoneTM = MeshBases.GetComponentSpaceTransform(compactBoneIndex);
	
	// Get ref rot
	FQuat finalRot = synQuat * OutBoneTM.GetRotation();

	// Update rot
	OutBoneTM.SetRotation(finalRot);

	// Output
	OutBoneTransforms.Add(FBoneTransform(compactBoneIndex, OutBoneTM));
}

This results in delta rotations for each bone adding together in a commutative way (so this 15 degree rotation in the legs):

Is there anyway to get access to the original ComponentPose before any previous SkelControl updates? Or is there a way to get access to a secondary InputPose as the reference Pose to use?

I attempted updating all bones in a single SkelControl update but the positions of each bone wasn’t updated. Perhaps there is a solution there where each bone position is updated to take into account the rotation of its parent bone. Using single SkelControl for each bone is preferable as provides greater control.

Thanks!

This is possible by changing a little how you apply your transforms inside EvaluateSkeletalControl_AnyThread

In essence you change the line at the end from

OutBoneTransforms.Add(FBoneTransform(compactbone, NewBoneTM));

to:

TempTransforms.Add(FBoneTransform(compactbone, NewBoneTM));
Output.Pose.LocalBlendCSBoneTransforms(TempTransforms, BlendWeight);
TempTransforms.Reset();

Which applies each transform before processing the next transform if it’s placed inside a loop going over each of your bones.