Download

About UE4 import bvh file and play

I am currently studying the function of importing BVH files into UE4 and playing. The BVH files are exported from MotionBuilder. I used C++ to customize an animation node in the UE4 animation blueprint, and assign the BVH data to the bone points for each frame pair. , But the arms and legs are always restored incorrectly. MotionBuilder is a right-handed coordinate system, with the Y-axis facing upwards and the Z-axis facing outwards. I went through the following spatial transformations. Please tell me which link is the problem? Many thanks!

This is My Code
AnimNode_PlayBVH.h (2.3 KB)
AnimNode_PlayBVH.cpp (11.7 KB)
the result:
pose
BVH File:
KAKA_MB.bvh (107.3 KB)

I don’t know why only the arms and legs are wrong.
reference:[c++ - How to convert Euler Rotations from one Coordinate System to another? Right Handed Y-up to Left handed Z-up - Stack Overflow]

void FAnimNode_PlayBVH::EvaluateComponentSpace_AnyThread(FComponentSpacePoseContext& Output)
{
	BasePose.EvaluateComponentSpace(Output);

	Output.ResetToRefPose();
	check(Output.AnimInstanceProxy->GetSkeleton() != nullptr);

	const FBoneContainer& BoneContainer = Output.Pose.GetPose().GetBoneContainer();
	FTransform ComponentTransform = Output.AnimInstanceProxy->GetComponentTransform();
	for (int32 i = 0; i < FrameData.Num(); i++)
	{
		GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, FString::Printf(TEXT("BoneName: %s"), *FrameData[i].BoneName.ToString()));
		int32 index = BoneContainer.GetPoseBoneIndexForBoneName(FrameData[i].BoneName);

		if (index != -1)
		{

			FCompactPoseBoneIndex CompactPoseBoneToModify(index);
			FTransform NewBoneTM = Output.Pose.GetComponentSpaceTransform(CompactPoseBoneToModify);

			//Convert to Bone Space.
			if (FrameData[i].TranslationMode == VF_Additive)
			{
				//Convert to Bone Space.
				FAnimationRuntime::ConvertCSTransformToBoneSpace(ComponentTransform, Output.Pose, NewBoneTM, CompactPoseBoneToModify, BCS_ComponentSpace);
				NewBoneTM.SetTranslation(FrameData[i].bvhPos);
				//Convert back to Component Space.
				FAnimationRuntime::ConvertBoneSpaceTransformToCS(ComponentTransform, Output.Pose, NewBoneTM, CompactPoseBoneToModify, BCS_ComponentSpace);

			}

			FAnimationRuntime::ConvertCSTransformToBoneSpace(ComponentTransform, Output.Pose, NewBoneTM, CompactPoseBoneToModify, BCS_ComponentSpace);
			
			FQuat qx(FVector(1, 0, 0), -FMath::DegreesToRadians(FrameData[i].Xrotation));
			FQuat qz(FVector(0, 0, 1), -FMath::DegreesToRadians(FrameData[i].Yrotation));
			FQuat qy(FVector(0, 1, 0), -FMath::DegreesToRadians(FrameData[i].Zrotation));
			
			FQuat qu = qy * qz * qx;	
			
			NewBoneTM.SetRotation(qu * NewBoneTM.GetRotation());	
			
			//Convert back to Component Space.
			FAnimationRuntime::ConvertBoneSpaceTransformToCS(ComponentTransform, Output.Pose, NewBoneTM, CompactPoseBoneToModify, BCS_ComponentSpace);
			
			Output.Pose.SetComponentSpaceTransform(CompactPoseBoneToModify, NewBoneTM);
		}
	}
}