SkeletonMapperTest.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  2. // SPDX-License-Identifier: MIT
  3. #include <TestFramework.h>
  4. #include <Tests/Rig/SkeletonMapperTest.h>
  5. #include <Jolt/Physics/StateRecorder.h>
  6. #include <Jolt/ObjectStream/ObjectStreamIn.h>
  7. #include <Renderer/DebugRendererImp.h>
  8. #include <Layers.h>
  9. #include <Utils/Log.h>
  10. JPH_IMPLEMENT_RTTI_VIRTUAL(SkeletonMapperTest)
  11. {
  12. JPH_ADD_BASE_CLASS(SkeletonMapperTest, Test)
  13. }
  14. SkeletonMapperTest::~SkeletonMapperTest()
  15. {
  16. mRagdoll->RemoveFromPhysicsSystem();
  17. }
  18. void SkeletonMapperTest::Initialize()
  19. {
  20. // Floor
  21. CreateFloor();
  22. // Load ragdoll
  23. mRagdollSettings = RagdollLoader::sLoad("Assets/Human.tof", EMotionType::Dynamic);
  24. // Create ragdoll
  25. mRagdoll = mRagdollSettings->CreateRagdoll(0, 0, mPhysicsSystem);
  26. mRagdoll->AddToPhysicsSystem(EActivation::Activate);
  27. // Load neutral animation for ragdoll
  28. Ref<SkeletalAnimation> neutral_ragdoll;
  29. if (!ObjectStreamIn::sReadObject("Assets/Human/neutral.tof", neutral_ragdoll))
  30. FatalError("Could not open neutral animation");
  31. // Load animation skeleton
  32. Ref<Skeleton> animation_skeleton;
  33. if (!ObjectStreamIn::sReadObject("Assets/Human/skeleton_hd.tof", animation_skeleton))
  34. FatalError("Could not open skeleton_hd");
  35. animation_skeleton->CalculateParentJointIndices();
  36. // Load neutral animation
  37. Ref<SkeletalAnimation> neutral_animation;
  38. if (!ObjectStreamIn::sReadObject("Assets/Human/neutral_hd.tof", neutral_animation))
  39. FatalError("Could not open neutral_hd animation");
  40. // Load test animation
  41. if (!ObjectStreamIn::sReadObject("Assets/Human/jog_hd.tof", mAnimation))
  42. FatalError("Could not open jog_hd animation");
  43. // Initialize pose
  44. mAnimatedPose.SetSkeleton(animation_skeleton);
  45. mRagdollPose.SetSkeleton(mRagdollSettings->GetSkeleton());
  46. // Calculate neutral poses and initialize skeleton mapper
  47. neutral_ragdoll->Sample(0.0f, mRagdollPose);
  48. mRagdollPose.CalculateJointMatrices();
  49. neutral_animation->Sample(0.0f, mAnimatedPose);
  50. mAnimatedPose.CalculateJointMatrices();
  51. mRagdollToAnimated.Initialize(mRagdollPose.GetSkeleton(), mRagdollPose.GetJointMatrices().data(), mAnimatedPose.GetSkeleton(), mAnimatedPose.GetJointMatrices().data());
  52. // Calculate initial pose and set it
  53. CalculateRagdollPose();
  54. mRagdoll->SetPose(mRagdollPose);
  55. }
  56. void SkeletonMapperTest::CalculateRagdollPose()
  57. {
  58. // Sample new animated pose
  59. mAnimation->Sample(mTime, mAnimatedPose);
  60. mAnimatedPose.CalculateJointMatrices();
  61. // Map to ragdoll pose
  62. mRagdollToAnimated.MapReverse(mAnimatedPose.GetJointMatrices().data(), mRagdollPose.GetJointMatrices().data());
  63. mRagdollPose.CalculateJointStates();
  64. }
  65. void SkeletonMapperTest::PrePhysicsUpdate(const PreUpdateParams &inParams)
  66. {
  67. // Update time
  68. mTime += inParams.mDeltaTime;
  69. // Drive the ragdoll pose and drive motors to reach it
  70. CalculateRagdollPose();
  71. mRagdoll->DriveToPoseUsingMotors(mRagdollPose);
  72. #ifdef JPH_DEBUG_RENDERER
  73. // Draw animated skeleton
  74. mAnimatedPose.Draw(*inParams.mPoseDrawSettings, mDebugRenderer);
  75. mDebugRenderer->DrawText3D(mAnimatedPose.GetJointMatrix(0).GetTranslation(), "Animated", Color::sWhite, 0.2f);
  76. // Draw mapped skeleton
  77. Mat44 offset = Mat44::sTranslation(Vec3(1.0f, 0, 0));
  78. mRagdollPose.Draw(*inParams.mPoseDrawSettings, mDebugRenderer, offset);
  79. mDebugRenderer->DrawText3D(offset * mAnimatedPose.GetJointMatrix(0).GetTranslation(), "Reverse Mapped", Color::sWhite, 0.2f);
  80. #endif // JPH_DEBUG_RENDERER
  81. // Get ragdoll pose in model space
  82. Array<Mat44> pose1_model(mRagdollPose.GetJointCount());
  83. mRagdoll->GetPose(pose1_model.data());
  84. // Get animated pose in local space
  85. Array<Mat44> pose2_local(mAnimatedPose.GetJointCount());
  86. mAnimatedPose.CalculateLocalSpaceJointMatrices(pose2_local.data());
  87. // Map ragdoll to animated pose, filling in the extra joints using the local space animated pose
  88. SkeletonPose pose2_world;
  89. pose2_world.SetSkeleton(mAnimatedPose.GetSkeleton());
  90. mRagdollToAnimated.Map(pose1_model.data(), pose2_local.data(), pose2_world.GetJointMatrices().data());
  91. #ifdef JPH_DEBUG_RENDERER
  92. // Draw mapped pose
  93. pose2_world.Draw(*inParams.mPoseDrawSettings, mDebugRenderer, offset);
  94. mDebugRenderer->DrawText3D(offset * pose2_world.GetJointMatrix(1).GetTranslation(), "Mapped", Color::sWhite, 0.2f);
  95. #endif // JPH_DEBUG_RENDERER
  96. }
  97. void SkeletonMapperTest::SaveState(StateRecorder &inStream) const
  98. {
  99. inStream.Write(mTime);
  100. }
  101. void SkeletonMapperTest::RestoreState(StateRecorder &inStream)
  102. {
  103. inStream.Read(mTime);
  104. }