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:
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);
}
}
}