RandomMotionSelectionTests.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  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 "AnimGraphFixture.h"
  9. #include <EMotionFX/Source/AnimGraph.h>
  10. #include <EMotionFX/Source/AnimGraphStateMachine.h>
  11. #include <EMotionFX/Source/AnimGraphMotionNode.h>
  12. #include <EMotionFX/Source/EMotionFXManager.h>
  13. #include <EMotionFX/Source/MotionData/NonUniformMotionData.h>
  14. #include <EMotionFX/Source/MotionSet.h>
  15. #include <EMotionFX/Source/MotionInstance.h>
  16. #include <EMotionFX/Source/Motion.h>
  17. #include <AzCore/std/containers/unordered_map.h>
  18. #include <cmath>
  19. namespace EMotionFX
  20. {
  21. class RandomMotionSelectionTests : public AnimGraphFixture
  22. {
  23. public:
  24. void TearDown() override
  25. {
  26. if (m_selectedMotionCount)
  27. {
  28. delete m_selectedMotionCount;
  29. }
  30. AnimGraphFixture::TearDown();
  31. }
  32. void ConstructGraph() override
  33. {
  34. AnimGraphFixture::ConstructGraph();
  35. m_motionNode = aznew AnimGraphMotionNode();
  36. m_animGraph->GetRootStateMachine()->AddChildNode(m_motionNode);
  37. m_animGraph->GetRootStateMachine()->SetEntryState(m_motionNode);
  38. m_motionNode->SetIndexMode(EMotionFX::AnimGraphMotionNode::EIndexMode::INDEXMODE_RANDOMIZE);
  39. }
  40. void SetUp() override
  41. {
  42. m_selectedMotionCount = new AZStd::unordered_map<uint32, uint32>();
  43. AnimGraphFixture::SetUp();
  44. const int motionCount = 3;
  45. for (int i = 0; i < motionCount; ++i)
  46. {
  47. // The motion set keeps track of motions by their name. Each motion
  48. // within the motion set must have a unique name.
  49. AZStd::string motionId = AZStd::string::format("testSkeletalMotion%i", i);
  50. Motion* motion = aznew Motion(motionId.c_str());
  51. motion->SetMotionData(aznew NonUniformMotionData());
  52. motion->GetMotionData()->SetDuration(1.0f);
  53. MotionSet::MotionEntry* motionEntry = aznew MotionSet::MotionEntry(motion->GetName(), motion->GetName(), motion);
  54. m_motionSet->AddMotionEntry(motionEntry);
  55. m_motionNode->AddMotionId(motionId.c_str());
  56. }
  57. }
  58. AZStd::unordered_map<uint32, uint32>* m_selectedMotionCount = nullptr;
  59. AnimGraphMotionNode* m_motionNode = nullptr;
  60. };
  61. TEST_F(RandomMotionSelectionTests, RandomizeMotion)
  62. {
  63. const int iterationCount = 1000;
  64. AnimGraphMotionNode::UniqueData* nodeUniqueData = static_cast<AnimGraphMotionNode::UniqueData*>(m_motionNode->FindOrCreateUniqueNodeData(m_animGraphInstance));
  65. for (int i = 0; i < iterationCount; ++i)
  66. {
  67. m_motionNode->PickNewActiveMotion(m_animGraphInstance, nodeUniqueData);
  68. auto mapIterator = m_selectedMotionCount->find(nodeUniqueData->m_activeMotionIndex);
  69. if (mapIterator != m_selectedMotionCount->end())
  70. {
  71. mapIterator->second++;
  72. }
  73. else
  74. {
  75. m_selectedMotionCount->emplace(nodeUniqueData->m_activeMotionIndex, 1);
  76. }
  77. }
  78. const double expectedUniformFrequency = 1.0 / m_selectedMotionCount->size();
  79. const double tolerance = 0.1;
  80. bool success = true;
  81. for(auto& motionCountEntry : (*m_selectedMotionCount))
  82. {
  83. double frequency = motionCountEntry.second / static_cast<double>(iterationCount);
  84. bool isInTolerance = std::fabs((frequency - expectedUniformFrequency) / expectedUniformFrequency) < tolerance;
  85. success = success && isInTolerance;
  86. }
  87. ASSERT_TRUE(success);
  88. }
  89. } // end namespace EMotionFX