Feature.h 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  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. #pragma once
  9. #include <AzCore/Math/Color.h>
  10. #include <AzCore/Memory/Memory.h>
  11. #include <AzCore/RTTI/RTTI.h>
  12. #include <EMotionFX/Source/EMotionFXConfig.h>
  13. #include <EMotionFX/Source/AnimGraphPosePool.h>
  14. #include <EMotionFX/Source/Node.h>
  15. #include <EMotionFX/Source/Skeleton.h>
  16. #include <AzFramework/Entity/EntityDebugDisplayBus.h>
  17. #include <FeatureMatrix.h>
  18. #include <QueryVector.h>
  19. namespace EMotionFX
  20. {
  21. class ActorInstance;
  22. class MotionInstance;
  23. class Pose;
  24. class Motion;
  25. };
  26. namespace EMotionFX::MotionMatching
  27. {
  28. class Frame;
  29. class FrameDatabase;
  30. class MotionMatchingInstance;
  31. class TrajectoryQuery;
  32. class FeatureMatrixTransformer;
  33. //! A feature is a property extracted from the animation data and is used by the motion matching algorithm to find the next best matching frame.
  34. //! Examples of features are the position of the feet joints, the linear or angular velocity of the knee joints or the trajectory history and future
  35. //! trajectory of the root joint. We can also encode environment sensations like obstacle positions and height, the location of the sword of an enemy
  36. //! character or a football's position and velocity. Their purpose is to describe a frame of the animation by their key characteristics and sometimes
  37. //! enhance the actual keyframe data (pos/rot/scale per joint) by e.g. taking the time domain into account and calculate the velocity or acceleration,
  38. //! or a whole trajectory to describe where the given joint came from to reach the frame and the path it moves along in the near future.
  39. //! @Note: Features are extracted and stored relative to a given joint, in most cases the motion extraction or root joint, and thus are in model-space.
  40. //! This makes the search algorithm invariant to the character location and orientation and the extracted features, like e.g. a joint position or velocity,
  41. //! translate and rotate along with the character.
  42. class EMFX_API Feature
  43. {
  44. public:
  45. AZ_RTTI(Feature, "{DE9CBC48-9176-4DF1-8306-4B1E621F0E76}")
  46. AZ_CLASS_ALLOCATOR_DECL
  47. Feature() = default;
  48. virtual ~Feature() = default;
  49. ////////////////////////////////////////////////////////////////////////
  50. // Initialization
  51. struct EMFX_API InitSettings
  52. {
  53. ActorInstance* m_actorInstance = nullptr;
  54. FeatureMatrix::Index m_featureColumnStartOffset = 0;
  55. };
  56. virtual bool Init(const InitSettings& settings);
  57. ////////////////////////////////////////////////////////////////////////
  58. // Feature extraction
  59. struct EMFX_API ExtractFeatureContext
  60. {
  61. ExtractFeatureContext(FeatureMatrix& featureMatrix, AnimGraphPosePool& posePool);
  62. FrameDatabase* m_frameDatabase = nullptr;
  63. FeatureMatrix& m_featureMatrix;
  64. size_t m_frameIndex = InvalidIndex;
  65. const Pose* m_framePose = nullptr; //!< Pre-sampled pose for the given frame.
  66. AnimGraphPosePool& m_posePool;
  67. ActorInstance* m_actorInstance = nullptr;
  68. };
  69. virtual void ExtractFeatureValues(const ExtractFeatureContext& context) = 0;
  70. ////////////////////////////////////////////////////////////////////////
  71. // Fill query vector
  72. struct EMFX_API QueryVectorContext
  73. {
  74. QueryVectorContext(const Pose& currentPose, const TrajectoryQuery& trajectoryQuery);
  75. const Pose& m_currentPose; //!< Current actor instance pose.
  76. const TrajectoryQuery& m_trajectoryQuery;
  77. FeatureMatrixTransformer* m_featureTransformer = nullptr;
  78. };
  79. virtual void FillQueryVector([[maybe_unused]] QueryVector& queryVector,
  80. [[maybe_unused]] const QueryVectorContext& context) = 0;
  81. ////////////////////////////////////////////////////////////////////////
  82. // Feature cost
  83. struct EMFX_API FrameCostContext
  84. {
  85. FrameCostContext(const QueryVector& queryVector, const FeatureMatrix& featureMatrix);
  86. const QueryVector& m_queryVector; //!< Input query feature values.
  87. const FeatureMatrix& m_featureMatrix;
  88. };
  89. virtual float CalculateFrameCost(size_t frameIndex, const FrameCostContext& context) const;
  90. //! Specifies how the feature value differences (residuals), between the input query values
  91. //! and the frames in the motion database that sum up the feature cost, are calculated.
  92. enum ResidualType
  93. {
  94. Absolute,
  95. Squared
  96. };
  97. void SetCostFactor(float costFactor) { m_costFactor = costFactor; }
  98. float GetCostFactor() const { return m_costFactor; }
  99. virtual void DebugDraw([[maybe_unused]] AzFramework::DebugDisplayRequests& debugDisplay,
  100. [[maybe_unused]] const Pose& currentPose,
  101. [[maybe_unused]] const FeatureMatrix& featureMatrix,
  102. [[maybe_unused]] const FeatureMatrixTransformer* featureTransformer,
  103. [[maybe_unused]] size_t frameIndex) {}
  104. void SetDebugDrawColor(const AZ::Color& color);
  105. const AZ::Color& GetDebugDrawColor() const;
  106. void SetDebugDrawEnabled(bool enabled);
  107. bool GetDebugDrawEnabled() const;
  108. void SetJointName(const AZStd::string& jointName) { m_jointName = jointName; }
  109. const AZStd::string& GetJointName() const { return m_jointName; }
  110. void SetRelativeToJointName(const AZStd::string& jointName) { m_relativeToJointName = jointName; }
  111. const AZStd::string& GetRelativeToJointName() const { return m_relativeToJointName; }
  112. void SetName(const AZStd::string& name) { m_name = name; }
  113. const AZStd::string& GetName() const { return m_name; }
  114. // Column offset for the first value for the given feature inside the feature matrix.
  115. virtual size_t GetNumDimensions() const = 0;
  116. virtual AZStd::string GetDimensionName([[maybe_unused]] size_t index) const { return "Unknown"; }
  117. FeatureMatrix::Index GetColumnOffset() const { return m_featureColumnOffset; }
  118. void SetColumnOffset(FeatureMatrix::Index offset) { m_featureColumnOffset = offset; }
  119. const AZ::TypeId& GetId() const { return m_id; }
  120. size_t GetRelativeToNodeIndex() const { return m_relativeToNodeIndex; }
  121. void SetRelativeToNodeIndex(size_t nodeIndex);
  122. static void Reflect(AZ::ReflectContext* context);
  123. protected:
  124. //! Calculate a normalized direction vector difference between the two given vectors.
  125. //! A dot product of the two vectors is taken and the result in range [-1, 1] is scaled to [0, 1].
  126. //! @result Normalized, absolute difference between the vectors.
  127. //! Angle difference dot result cost
  128. //! 0.0 degrees 1.0 0.0
  129. //! 90.0 degrees 0.0 0.5
  130. //! 180.0 degrees -1.0 1.0
  131. //! 270.0 degrees 0.0 0.5
  132. float GetNormalizedDirectionDifference(const AZ::Vector2& directionA, const AZ::Vector2& directionB) const;
  133. float GetNormalizedDirectionDifference(const AZ::Vector3& directionA, const AZ::Vector3& directionB) const;
  134. float CalcResidual(float value) const;
  135. float CalcResidual(const AZ::Vector3& a, const AZ::Vector3& b) const;
  136. virtual AZ::Crc32 GetCostFactorVisibility() const;
  137. // Shared and reflected data.
  138. AZ::TypeId m_id = AZ::TypeId::CreateRandom(); //< The feature identification number. Use this instead of the RTTI class ID so that we can have multiple of the same type.
  139. AZStd::string m_name; //< Display name used for feature identification and debug visualizations.
  140. AZStd::string m_jointName; //< Joint name to extract the data from.
  141. AZStd::string m_relativeToJointName; //< When extracting feature data, convert it to relative-space to the given joint.
  142. AZ::Color m_debugColor = AZ::Colors::Green; //< Color used for debug visualizations to identify the feature.
  143. bool m_debugDrawEnabled = false; //< Are debug visualizations enabled for this feature?
  144. float m_costFactor = 1.0f; //< The cost factor for the feature is multiplied with the actual and can be used to change a feature's influence in the motion matching search.
  145. ResidualType m_residualType = ResidualType::Absolute; //< How do we calculate the differences (residuals) between the input query values and the frames in the motion database that sum up the feature cost.
  146. // Instance data (depends on the feature schema or actor instance).
  147. FeatureMatrix::Index m_featureColumnOffset; //< Float/Value offset, starting column for where the feature should be places at.
  148. size_t m_relativeToNodeIndex = InvalidIndex;
  149. size_t m_jointIndex = InvalidIndex;
  150. };
  151. } // namespace EMotionFX::MotionMatching