AnimGraphFixture.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  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 <AzCore/Math/MathUtils.h>
  9. #include <AzCore/Math/Random.h>
  10. #include <AzCore/std/smart_ptr/unique_ptr.h>
  11. #include <MCore/Source/ReflectionSerializer.h>
  12. #include "AnimGraphFixture.h"
  13. #include <EMotionFX/Source/Actor.h>
  14. #include <EMotionFX/Source/ActorInstance.h>
  15. #include <EMotionFX/Source/AnimGraph.h>
  16. #include <EMotionFX/Source/AnimGraphInstance.h>
  17. #include <EMotionFX/Source/AnimGraphStateMachine.h>
  18. #include <EMotionFX/Source/AnimGraphStateTransition.h>
  19. #include <EMotionFX/Source/AnimGraphTimeCondition.h>
  20. #include <EMotionFX/Source/Node.h>
  21. #include <EMotionFX/Source/Motion.h>
  22. #include <EMotionFX/Source/MotionData/NonUniformMotionData.h>
  23. #include <EMotionFX/Source/Transform.h>
  24. #include <EMotionFX/Source/TransformData.h>
  25. #include <EMotionFX/Source/Parameter/ParameterFactory.h>
  26. #include <Tests/TestAssetCode/SimpleActors.h>
  27. #include <Tests/TestAssetCode/ActorFactory.h>
  28. #include <Tests/TestAssetCode/AnimGraphFactory.h>
  29. namespace EMotionFX
  30. {
  31. void AnimGraphFixture::SetUp()
  32. {
  33. AZ::Debug::TraceMessageBus::Handler::BusConnect();
  34. SystemComponentFixture::SetUp();
  35. AnimGraphFactory::ReflectTestTypes(GetSerializeContext());
  36. // This fixture sets up the basic pieces to test animation graphs:
  37. // 1) will create an actor with a root node (joint) at the origin
  38. // 2) will create an empty animation graph
  39. // 3) will create an empty motion set
  40. // 4) will instantiate the actor and animation graph
  41. {
  42. ConstructActor();
  43. ASSERT_TRUE(m_actor) << "Construct actor did not build a valid actor.";
  44. m_actor->ResizeTransformData();
  45. m_actor->PostCreateInit(/*makeGeomLodsCompatibleWithSkeletalLODs=*/ false, /*convertUnitType=*/ false);
  46. }
  47. {
  48. m_motionSet = aznew MotionSet("testMotionSet");
  49. }
  50. {
  51. ConstructGraph();
  52. m_animGraph->InitAfterLoading();
  53. }
  54. {
  55. m_actorInstance = ActorInstance::Create(m_actor.get());
  56. m_animGraphInstance = AnimGraphInstance::Create(m_animGraph.get(), m_actorInstance, m_motionSet);
  57. m_actorInstance->SetAnimGraphInstance(m_animGraphInstance);
  58. m_animGraphInstance->IncreaseReferenceCount(); // Two owners now, the test and the actor instance
  59. m_animGraphInstance->RecursiveInvalidateUniqueDatas();
  60. }
  61. }
  62. void AnimGraphFixture::ConstructGraph()
  63. {
  64. m_animGraph = AnimGraphFactory::Create<EmptyAnimGraph>();
  65. m_rootStateMachine = m_animGraph->GetRootStateMachine();
  66. }
  67. void AnimGraphFixture::ConstructActor()
  68. {
  69. m_actor = ActorFactory::CreateAndInit<SimpleJointChainActor>(1);
  70. }
  71. AZStd::string AnimGraphFixture::SerializeAnimGraph() const
  72. {
  73. if (!m_animGraph.get())
  74. {
  75. return AZStd::string();
  76. }
  77. return MCore::ReflectionSerializer::Serialize(m_animGraph.get()).GetValue();
  78. }
  79. void AnimGraphFixture::TearDown()
  80. {
  81. if (m_animGraphInstance)
  82. {
  83. m_animGraphInstance->Destroy();
  84. m_animGraphInstance = nullptr;
  85. }
  86. if (m_actorInstance)
  87. {
  88. m_actorInstance->Destroy();
  89. m_actorInstance = nullptr;
  90. }
  91. if (m_motionSet)
  92. {
  93. delete m_motionSet;
  94. m_motionSet = nullptr;
  95. }
  96. m_blendTreeAnimGraph.reset();
  97. m_animGraph.reset();
  98. m_actor.reset();
  99. SystemComponentFixture::TearDown();
  100. AZ::Debug::TraceMessageBus::Handler::BusDisconnect();
  101. }
  102. void AnimGraphFixture::Evaluate()
  103. {
  104. m_actorInstance->UpdateTransformations(0.0);
  105. }
  106. const Transform& AnimGraphFixture::GetOutputTransform(uint32 nodeIndex)
  107. {
  108. const Pose* pose = m_actorInstance->GetTransformData()->GetCurrentPose();
  109. return pose->GetModelSpaceTransform(nodeIndex);
  110. }
  111. void AnimGraphFixture::AddValueParameter(const AZ::TypeId& typeId, const AZStd::string& name)
  112. {
  113. Parameter* parameter = ParameterFactory::Create(typeId);
  114. parameter->SetName(name);
  115. m_animGraph->AddParameter(parameter);
  116. m_animGraphInstance->AddMissingParameterValues();
  117. }
  118. AnimGraphStateTransition* AnimGraphFixture::AddTransition(AnimGraphNode* source, AnimGraphNode* target, float time)
  119. {
  120. AnimGraphStateMachine* parentSM = azdynamic_cast<AnimGraphStateMachine*>(target->GetParentNode());
  121. if (!parentSM)
  122. {
  123. return nullptr;
  124. }
  125. AnimGraphStateTransition* transition = aznew AnimGraphStateTransition();
  126. transition->SetSourceNode(source);
  127. transition->SetTargetNode(target);
  128. transition->SetBlendTime(time);
  129. parentSM->AddTransition(transition);
  130. return transition;
  131. }
  132. AnimGraphTimeCondition* AnimGraphFixture::AddTimeCondition(AnimGraphStateTransition* transition, float countDownTime)
  133. {
  134. AnimGraphTimeCondition* condition = aznew AnimGraphTimeCondition();
  135. condition->SetCountDownTime(countDownTime);
  136. transition->AddCondition(condition);
  137. return condition;
  138. }
  139. AnimGraphStateTransition* AnimGraphFixture::AddTransitionWithTimeCondition(AnimGraphNode* source, AnimGraphNode* target, float blendTime, float countDownTime)
  140. {
  141. AnimGraphStateTransition* transition = AddTransition(source, target, blendTime);
  142. AddTimeCondition(transition, countDownTime);
  143. return transition;
  144. }
  145. MotionSet::MotionEntry* AnimGraphFixture::AddMotionEntry(const AZStd::string& motionId, float motionMaxTime)
  146. {
  147. Motion* motion = aznew Motion(motionId.c_str());
  148. motion->SetMotionData(aznew NonUniformMotionData());
  149. motion->GetMotionData()->SetDuration(motionMaxTime);
  150. MotionSet::MotionEntry* motionEntry = aznew MotionSet::MotionEntry(motion->GetName(), motion->GetName(), motion);
  151. m_motionSet->AddMotionEntry(motionEntry);
  152. return motionEntry;
  153. }
  154. void AnimGraphFixture::Simulate(float simulationTime, float expectedFps, float fpsVariance,
  155. SimulateCallback preCallback,
  156. SimulateCallback postCallback,
  157. SimulateFrameCallback preUpdateCallback,
  158. SimulateFrameCallback postUpdateCallback)
  159. {
  160. AZ::SimpleLcgRandom random;
  161. random.SetSeed(875960);
  162. const float minFps = expectedFps - fpsVariance / 2.0f;
  163. const float maxFps = expectedFps + fpsVariance / 2.0f;
  164. int frame = 0;
  165. float time = 0.0f;
  166. preCallback(m_animGraphInstance);
  167. // Make sure to update at least once and to have a valid internal state and everything is initialized on the first frame.
  168. preUpdateCallback(m_animGraphInstance, time, 0.0f, frame);
  169. GetEMotionFX().Update(0.0f);
  170. postUpdateCallback(m_animGraphInstance, time, 0.0f, frame);
  171. while (time < simulationTime)
  172. {
  173. const float randomFps = fabs(minFps + random.GetRandomFloat() * (maxFps - minFps));
  174. float timeDelta = 0.0f;
  175. if (randomFps > 0.1f)
  176. {
  177. timeDelta = 1.0f / randomFps;
  178. }
  179. time += timeDelta;
  180. frame++;
  181. preUpdateCallback(m_animGraphInstance, time, timeDelta, frame);
  182. GetEMotionFX().Update(timeDelta);
  183. postUpdateCallback(m_animGraphInstance, time, timeDelta, frame);
  184. }
  185. postCallback(m_animGraphInstance);
  186. }
  187. }