3
0

BlendTreeRagdollNodeTests.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  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/AnimGraphStateMachine.h>
  10. #include <EMotionFX/Source/BlendTree.h>
  11. #include <EMotionFX/Source/BlendTreeFinalNode.h>
  12. #include <EMotionFX/Source/BlendTreeFloatConstantNode.h>
  13. #include <EMotionFX/Source/BlendTreeRagdollNode.h>
  14. #include <EMotionFX/Source/EMotionFXManager.h>
  15. #include <EMotionFX/Source/Node.h>
  16. #include <EMotionFX/Source/RagdollInstance.h>
  17. #include <Tests/ActorFixture.h>
  18. #include <Tests/AnimGraphFixture.h>
  19. #include <Tests/Mocks/PhysicsRagdoll.h>
  20. namespace EMotionFX
  21. {
  22. // Tests if the activation input port can be controlled with a non-boolean/float values from a const float node.
  23. class BlendTreeRagdollNode_ConstFloatActivateInputTest
  24. : public AnimGraphFixture
  25. , public ::testing::WithParamInterface<float>
  26. {
  27. public:
  28. void ConstructGraph() override
  29. {
  30. AnimGraphFixture::ConstructGraph();
  31. m_blendTreeAnimGraph = AnimGraphFactory::Create<OneBlendTreeNodeAnimGraph>();
  32. m_rootStateMachine = m_blendTreeAnimGraph->GetRootStateMachine();
  33. BlendTree* blendTree = m_blendTreeAnimGraph->GetBlendTreeNode();
  34. /*
  35. +-------------+ +---------+ +------------+
  36. | Const Float |--->| Ragdoll |--->| Final Node |
  37. +-------------+ +---------+ +------------+
  38. */
  39. BlendTreeFloatConstantNode* floatConstNode = aznew BlendTreeFloatConstantNode();
  40. floatConstNode->SetValue(GetParam());
  41. blendTree->AddChildNode(floatConstNode);
  42. m_ragdollNode = aznew BlendTreeRagdollNode();
  43. blendTree->AddChildNode(m_ragdollNode);
  44. BlendTreeFinalNode* finalNode = aznew BlendTreeFinalNode();
  45. blendTree->AddChildNode(finalNode);
  46. m_ragdollNode->AddUnitializedConnection(floatConstNode, BlendTreeFloatConstantNode::PORTID_OUTPUT_RESULT, BlendTreeRagdollNode::PORTID_ACTIVATE);
  47. finalNode->AddUnitializedConnection(m_ragdollNode, BlendTreeRagdollNode::PORTID_OUTPUT_POSE, BlendTreeFinalNode::PORTID_INPUT_POSE);
  48. m_blendTreeAnimGraph->InitAfterLoading();
  49. }
  50. void SetUp() override
  51. {
  52. AnimGraphFixture::SetUp();
  53. m_animGraphInstance->Destroy();
  54. m_animGraphInstance = m_blendTreeAnimGraph->GetAnimGraphInstance(m_actorInstance, m_motionSet);
  55. }
  56. BlendTreeRagdollNode* m_ragdollNode = nullptr;
  57. };
  58. TEST_P(BlendTreeRagdollNode_ConstFloatActivateInputTest, BlendTreeRagdollNode_ConstFloatActivateInputTest)
  59. {
  60. GetEMotionFX().Update(0.0f);
  61. const float constFloatValue = GetParam();
  62. const bool isActivated = m_ragdollNode->IsActivated(m_animGraphInstance);
  63. EXPECT_EQ(!MCore::Math::IsFloatZero(constFloatValue), isActivated)
  64. << "Activation expected in case const float value is not zero.";
  65. }
  66. INSTANTIATE_TEST_CASE_P(BlendTreeRagdollNode_ConstFloatActivateInputTest,
  67. BlendTreeRagdollNode_ConstFloatActivateInputTest,
  68. ::testing::ValuesIn({ -1.0f, 0.0f, 0.1f, 1.0f }));
  69. ///////////////////////////////////////////////////////////////////////////
  70. struct RagdollRootNodeParam
  71. {
  72. std::string m_ragdollRootNode;
  73. bool m_ragdollRootNodeSimulated;
  74. std::vector<std::string> m_ragdollConfigNodeNames;
  75. std::vector<std::string> m_simulatedJointNames;
  76. };
  77. class RagdollRootNodeFixture
  78. : public ActorFixture
  79. , public ::testing::WithParamInterface<RagdollRootNodeParam>
  80. {
  81. public:
  82. void AddRagdollNodeConfig(AZStd::vector<Physics::RagdollNodeConfiguration>& ragdollNodes, const AZStd::string& jointName)
  83. {
  84. Physics::RagdollNodeConfiguration nodeConfig;
  85. nodeConfig.m_debugName = jointName;
  86. ragdollNodes.emplace_back(nodeConfig);
  87. }
  88. };
  89. TEST_P(RagdollRootNodeFixture, RagdollRootNodeIsSimulatedTests)
  90. {
  91. Physics::RagdollConfiguration& ragdollConfig = GetActor()->GetPhysicsSetup()->GetRagdollConfig();
  92. AZStd::vector<Physics::RagdollNodeConfiguration>& ragdollNodes = ragdollConfig.m_nodes;
  93. const RagdollRootNodeParam& param = GetParam();
  94. const AZStd::string ragdollRootNodeName = param.m_ragdollRootNode.c_str();
  95. // Create the ragdoll config.
  96. for (const std::string& jointName : param.m_ragdollConfigNodeNames)
  97. {
  98. AddRagdollNodeConfig(ragdollNodes, jointName.c_str());
  99. }
  100. // Create the ragdoll instance and check if the ragdoll root node is set correctly.
  101. TestRagdoll testRagdoll;
  102. EXPECT_CALL(testRagdoll, GetState(::testing::_)).Times(::testing::AnyNumber());
  103. EXPECT_CALL(testRagdoll, GetNumNodes()).WillRepeatedly(::testing::Return(1));
  104. EXPECT_CALL(testRagdoll, IsSimulated()).WillRepeatedly(::testing::Return(true));
  105. EXPECT_CALL(testRagdoll, GetPosition()).WillRepeatedly(::testing::Return(AZ::Vector3::CreateZero()));
  106. EXPECT_CALL(testRagdoll, GetOrientation()).WillRepeatedly(::testing::Return(AZ::Quaternion::CreateIdentity()));
  107. m_actorInstance->SetRagdoll(&testRagdoll);
  108. RagdollInstance* ragdollInstance = m_actorInstance->GetRagdollInstance();
  109. const AZ::Outcome<size_t> rootNodeIndex = ragdollInstance->GetRootRagdollNodeIndex();
  110. ASSERT_TRUE(rootNodeIndex.IsSuccess()) << "No root node for the ragdoll found.";
  111. EXPECT_EQ(ragdollInstance->GetRagdollRootNode()->GetNameString(), ragdollRootNodeName) << "Wrong ragdoll root node.";
  112. // Create an anim graph with a ragdoll node.
  113. AZStd::unique_ptr<MotionSet> motionSet = AZStd::make_unique<MotionSet>("testMotionSet");
  114. AZStd::unique_ptr<AnimGraph> animGraph = AnimGraphFactory::Create<EmptyAnimGraph>();
  115. BlendTree* blendTree = aznew BlendTree();
  116. animGraph->GetRootStateMachine()->AddChildNode(blendTree);
  117. animGraph->GetRootStateMachine()->SetEntryState(blendTree);
  118. BlendTreeRagdollNode* ragdollNode = aznew BlendTreeRagdollNode();
  119. // Set the simulated joints.
  120. AZStd::vector<AZStd::string> simulatedJointNames;
  121. for (const std::string& jointName : param.m_simulatedJointNames)
  122. {
  123. simulatedJointNames.emplace_back(jointName.c_str());
  124. }
  125. ragdollNode->SetSimulatedJointNames(simulatedJointNames);
  126. blendTree->AddChildNode(ragdollNode);
  127. EXPECT_TRUE(animGraph->InitAfterLoading());
  128. AnimGraphInstance* animGraphInstance = AnimGraphInstance::Create(animGraph.get(), m_actorInstance, motionSet.get());
  129. m_actorInstance->SetAnimGraphInstance(animGraphInstance);
  130. BlendTreeRagdollNode::UniqueData* uniqueData = static_cast<BlendTreeRagdollNode::UniqueData*>(animGraphInstance->FindOrCreateUniqueObjectData(ragdollNode));
  131. ASSERT_TRUE(uniqueData) << "Cannot find unique data for ragdoll node.";
  132. // Check if the ragdoll root node is simulated or if the ragdoll is partial.
  133. EXPECT_EQ(uniqueData->m_isRagdollRootNodeSimulated, param.m_ragdollRootNodeSimulated) << "Ragdoll root node should not be simulated.";
  134. }
  135. std::vector<RagdollRootNodeParam> ragdollRootNodeIsSimulatedTestValues =
  136. {
  137. // Simulated root node, in skeleton hierarchy order
  138. {
  139. "Bip01__pelvis",
  140. true,
  141. {
  142. "Bip01__pelvis",
  143. "l_upLeg",
  144. "l_loLeg"
  145. },
  146. {
  147. "Bip01__pelvis",
  148. "l_upLeg",
  149. "l_loLeg"
  150. }
  151. },
  152. // Simulated root node, reordered
  153. {
  154. "Bip01__pelvis",
  155. true,
  156. {
  157. "l_upLeg",
  158. "l_loLeg",
  159. "Bip01__pelvis"
  160. },
  161. {
  162. "l_upLeg",
  163. "Bip01__pelvis",
  164. "l_loLeg"
  165. }
  166. },
  167. // Partial ragdoll, root node not simulated, reordered
  168. {
  169. "Bip01__pelvis",
  170. false,
  171. {
  172. "l_upLeg",
  173. "l_loLeg",
  174. "Bip01__pelvis"
  175. },
  176. {
  177. "l_upLeg",
  178. "l_loLeg"
  179. }
  180. }
  181. };
  182. INSTANTIATE_TEST_CASE_P(RagdollRootNodeIsSimulatedTests,
  183. RagdollRootNodeFixture,
  184. ::testing::ValuesIn(ragdollRootNodeIsSimulatedTestValues));
  185. } // namespace EMotionFX