MorphSkinAttachmentTests.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <EMotionFX/Source/AnimGraph.h>
  9. #include <EMotionFX/Source/AnimGraphNode.h>
  10. #include <EMotionFX/Source/AnimGraphMotionNode.h>
  11. #include <EMotionFX/Source/AnimGraphStateMachine.h>
  12. #include <EMotionFX/Source/BlendTree.h>
  13. #include <EMotionFX/Source/BlendTreeFloatConstantNode.h>
  14. #include <EMotionFX/Source/EMotionFXManager.h>
  15. #include <EMotionFX/Source/Importer/Importer.h>
  16. #include <EMotionFX/Source/Motion.h>
  17. #include <EMotionFX/Source/MotionInstance.h>
  18. #include <EMotionFX/Source/MotionSet.h>
  19. #include <EMotionFX/Source/Node.h>
  20. #include <EMotionFX/Source/Skeleton.h>
  21. #include <EMotionFX/Source/TransformData.h>
  22. #include <EMotionFX/Source/MorphSetup.h>
  23. #include <EMotionFX/Source/MorphTargetStandard.h>
  24. #include <EMotionFX/Source/AttachmentSkin.h>
  25. #include <EMotionFX/Source/MotionData/NonUniformMotionData.h>
  26. #include <Tests/JackGraphFixture.h>
  27. #include <Tests/TestAssetCode/TestMotionAssets.h>
  28. namespace EMotionFX
  29. {
  30. class MorphSkinAttachmentFixture
  31. : public JackGraphFixture
  32. {
  33. public:
  34. void AddMotionData(Motion* newMotion, const AZStd::string& motionId)
  35. {
  36. auto motionData = newMotion->GetMotionData();
  37. // Create some morph sub motions.
  38. const AZStd::vector<AZStd::string> morphNames { "morph1", "morph2", "morph3", "morph4", "newmorph1", "newmorph2" };
  39. for (size_t i = 0; i < morphNames.size(); ++i)
  40. {
  41. motionData->AddMorph(morphNames[i], static_cast<float>(i + 1) / 10.0f);
  42. }
  43. // Add the motion to the motion set.
  44. EMotionFX::MotionSet::MotionEntry* newMotionEntry = aznew EMotionFX::MotionSet::MotionEntry();
  45. newMotionEntry->SetMotion(newMotion);
  46. m_motionSet->AddMotionEntry(newMotionEntry);
  47. m_motionSet->SetMotionEntryId(newMotionEntry, motionId);
  48. }
  49. void ConstructGraph() override
  50. {
  51. JackGraphFixture::ConstructGraph();
  52. // Motion of Jack walking forward (Y-axis change) with right arm aiming towards front.
  53. AddMotionData(TestMotionAssets::GetJackWalkForward(), "jack_walk_forward_aim_zup");
  54. // Anim graph:
  55. //
  56. // +-----------------+ +------------+ +---------+
  57. // |m_floatConstNode |------>|m_motionNode|------>|finalNode|
  58. // +-----------------+ |------------+ +---------+
  59. BlendTreeFinalNode* finalNode = aznew BlendTreeFinalNode();
  60. m_floatConstNode = aznew BlendTreeFloatConstantNode();
  61. m_motionNode = aznew AnimGraphMotionNode();
  62. // Control motion and effects to be used.
  63. m_motionNode->AddMotionId("jack_walk_forward_aim_zup");
  64. m_motionNode->SetLoop(true);
  65. m_blendTree = aznew BlendTree();
  66. m_blendTree->AddChildNode(m_motionNode);
  67. m_blendTree->AddChildNode(m_floatConstNode);
  68. m_blendTree->AddChildNode(finalNode);
  69. m_animGraph->GetRootStateMachine()->AddChildNode(m_blendTree);
  70. m_animGraph->GetRootStateMachine()->SetEntryState(m_blendTree);
  71. finalNode->AddConnection(m_motionNode, AnimGraphMotionNode::OUTPUTPORT_POSE, BlendTreeFinalNode::INPUTPORT_POSE);
  72. }
  73. void OnPostActorCreated() override
  74. {
  75. m_attachmentActor = m_actor->Clone();
  76. // Create a few morph targets in the main actor.
  77. MorphSetup* morphSetup = MorphSetup::Create();
  78. m_actor->SetMorphSetup(0, morphSetup);
  79. morphSetup->AddMorphTarget(MorphTargetStandard::Create("morph1"));
  80. morphSetup->AddMorphTarget(MorphTargetStandard::Create("morph2"));
  81. morphSetup->AddMorphTarget(MorphTargetStandard::Create("morph3"));
  82. morphSetup->AddMorphTarget(MorphTargetStandard::Create("morph4"));
  83. // Create a few other morphs in our attachment.
  84. MorphSetup* attachMorphSetup = MorphSetup::Create();
  85. m_attachmentActor->SetMorphSetup(0, attachMorphSetup);
  86. attachMorphSetup->AddMorphTarget(MorphTargetStandard::Create("newmorph1"));
  87. attachMorphSetup->AddMorphTarget(MorphTargetStandard::Create("newmorph2"));
  88. attachMorphSetup->AddMorphTarget(MorphTargetStandard::Create("morph1"));
  89. attachMorphSetup->AddMorphTarget(MorphTargetStandard::Create("morph2"));
  90. // Make sure our morphs are registered in the transform data poses.
  91. m_actor->ResizeTransformData();
  92. m_attachmentActor->ResizeTransformData();
  93. m_attachmentActorInstance = ActorInstance::Create(m_attachmentActor.get());
  94. }
  95. void TearDown() override
  96. {
  97. m_attachmentActorInstance->Destroy();
  98. m_attachmentActor.reset();
  99. JackGraphFixture::TearDown();
  100. }
  101. protected:
  102. AnimGraphMotionNode* m_motionNode = nullptr;
  103. BlendTree* m_blendTree = nullptr;
  104. BlendTreeFloatConstantNode* m_floatConstNode = nullptr;
  105. AZStd::unique_ptr<Actor> m_attachmentActor = nullptr;
  106. ActorInstance* m_attachmentActorInstance = nullptr;
  107. };
  108. TEST_F(MorphSkinAttachmentFixture, TransferTestUnattached)
  109. {
  110. GetEMotionFX().Update(1.0f / 60.0f);
  111. // The main actor instance should receive the morph sub motion values.
  112. const Pose& curPose = *m_actorInstance->GetTransformData()->GetCurrentPose();
  113. ASSERT_EQ(curPose.GetNumMorphWeights(), 4);
  114. EXPECT_FLOAT_EQ(curPose.GetMorphWeight(0), 0.1f);
  115. EXPECT_FLOAT_EQ(curPose.GetMorphWeight(1), 0.2f);
  116. EXPECT_FLOAT_EQ(curPose.GetMorphWeight(2), 0.3f);
  117. EXPECT_FLOAT_EQ(curPose.GetMorphWeight(3), 0.4f);
  118. // We expect no transfer of morph weights, since we aren't attached.
  119. const Pose& attachPose = *m_attachmentActorInstance->GetTransformData()->GetCurrentPose();
  120. ASSERT_EQ(attachPose.GetNumMorphWeights(), 4);
  121. EXPECT_FLOAT_EQ(attachPose.GetMorphWeight(0), 0.0f);
  122. EXPECT_FLOAT_EQ(attachPose.GetMorphWeight(1), 0.0f);
  123. EXPECT_FLOAT_EQ(attachPose.GetMorphWeight(2), 0.0f);
  124. EXPECT_FLOAT_EQ(attachPose.GetMorphWeight(3), 0.0f);
  125. };
  126. TEST_F(MorphSkinAttachmentFixture, TransferTestAttached)
  127. {
  128. // Create the attachment.
  129. AttachmentSkin* skinAttachment = AttachmentSkin::Create(m_actorInstance, m_attachmentActorInstance);
  130. m_actorInstance->AddAttachment(skinAttachment);
  131. GetEMotionFX().Update(1.0f / 60.0f);
  132. // The main actor instance should receive the morph sub motion values.
  133. const Pose& curPose = *m_actorInstance->GetTransformData()->GetCurrentPose();
  134. ASSERT_EQ(curPose.GetNumMorphWeights(), 4);
  135. EXPECT_FLOAT_EQ(curPose.GetMorphWeight(0), 0.1f);
  136. EXPECT_FLOAT_EQ(curPose.GetMorphWeight(1), 0.2f);
  137. EXPECT_FLOAT_EQ(curPose.GetMorphWeight(2), 0.3f);
  138. EXPECT_FLOAT_EQ(curPose.GetMorphWeight(3), 0.4f);
  139. // The skin attachment should now receive morph values from the main actor.
  140. const Pose& attachPose = *m_attachmentActorInstance->GetTransformData()->GetCurrentPose();
  141. ASSERT_EQ(attachPose.GetNumMorphWeights(), 4);
  142. EXPECT_FLOAT_EQ(attachPose.GetMorphWeight(0), 0.0f); // Once we auto register missing morphs this should be 0.5. See LY-100212
  143. EXPECT_FLOAT_EQ(attachPose.GetMorphWeight(1), 0.0f); // Once we auto register missing morphs this should be 0.6. See LY-100212
  144. EXPECT_FLOAT_EQ(attachPose.GetMorphWeight(2), 0.1f);
  145. EXPECT_FLOAT_EQ(attachPose.GetMorphWeight(3), 0.2f);
  146. };
  147. } // end namespace EMotionFX