BsAnimationClip.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #pragma once
  4. #include "BsCorePrerequisites.h"
  5. #include "BsResource.h"
  6. #include "BsVector3.h"
  7. #include "BsQuaternion.h"
  8. #include "BsAnimationCurve.h"
  9. namespace BansheeEngine
  10. {
  11. /** @addtogroup Animation
  12. * @{
  13. */
  14. struct AnimationCurveMapping;
  15. /** A set of animation curves representing translation/rotation/scale and generic animation. */
  16. struct AnimationCurves
  17. {
  18. /**
  19. * Registers a new curve used for animating position.
  20. *
  21. * @param[in] name Unique name of the curve. This name will be used mapping the curve to the relevant bone
  22. * in a skeleton, if any.
  23. * @param[in] curve Curve to add to the clip.
  24. */
  25. void addPositionCurve(const String& name, const TAnimationCurve<Vector3>& curve);
  26. /**
  27. * Registers a new curve used for animating rotation.
  28. *
  29. * @param[in] name Unique name of the curve. This name will be used mapping the curve to the relevant bone
  30. * in a skeleton, if any.
  31. * @param[in] curve Curve to add to the clip.
  32. */
  33. void addRotationCurve(const String& name, const TAnimationCurve<Quaternion>& curve);
  34. /**
  35. * Registers a new curve used for animating scale.
  36. *
  37. * @param[in] name Unique name of the curve. This name will be used mapping the curve to the relevant bone
  38. * in a skeleton, if any.
  39. * @param[in] curve Curve to add to the clip.
  40. */
  41. void addScaleCurve(const String& name, const TAnimationCurve<Vector3>& curve);
  42. /**
  43. * Registers a new curve used for generic animation.
  44. *
  45. * @param[in] name Unique name of the curve. This can be used for retrieving the value of the curve
  46. * from animation.
  47. * @param[in] curve Curve to add to the clip.
  48. */
  49. void addGenericCurve(const String& name, const TAnimationCurve<float>& curve);
  50. /** Removes an existing curve from the clip. */
  51. void removePositionCurve(const String& name);
  52. /** Removes an existing curve from the clip. */
  53. void removeRotationCurve(const String& name);
  54. /** Removes an existing curve from the clip. */
  55. void removeScaleCurve(const String& name);
  56. /** Removes an existing curve from the clip. */
  57. void removeGenericCurve(const String& name);
  58. Vector<TNamedAnimationCurve<Vector3>> position;
  59. Vector<TNamedAnimationCurve<Quaternion>> rotation;
  60. Vector<TNamedAnimationCurve<Vector3>> scale;
  61. Vector<TNamedAnimationCurve<float>> generic;
  62. };
  63. /** Contains a set of animation curves used for moving and rotating the root bone. */
  64. struct RootMotion
  65. {
  66. RootMotion() { }
  67. RootMotion(const TAnimationCurve<Vector3>& position, const TAnimationCurve<Quaternion>& rotation)
  68. :position(position), rotation(rotation)
  69. { }
  70. TAnimationCurve<Vector3> position;
  71. TAnimationCurve<Quaternion> rotation;
  72. };
  73. /** Event that is triggered when animation reaches a certain point. */
  74. struct AnimationEvent
  75. {
  76. AnimationEvent()
  77. :time(0.0f)
  78. { }
  79. AnimationEvent(const String& name, float time)
  80. :name(name), time(time)
  81. { }
  82. String name;
  83. float time;
  84. };
  85. /** Types of curves in an AnimationClip. */
  86. enum class CurveType
  87. {
  88. Position,
  89. Rotation,
  90. Scale,
  91. Generic,
  92. MorphFrame,
  93. MorphWeight,
  94. Count // Keep at end
  95. };
  96. /**
  97. * Contains animation curves for translation/rotation/scale of scene objects/skeleton bones, as well as curves for
  98. * generic property animation.
  99. */
  100. class BS_CORE_EXPORT AnimationClip : public Resource
  101. {
  102. public:
  103. virtual ~AnimationClip() { }
  104. /**
  105. * Returns all curves stored in the animation. Returned value will not be updated if the animation clip curves are
  106. * added or removed. Caller must monitor for changes and retrieve a new set of curves when that happens.
  107. */
  108. SPtr<AnimationCurves> getCurves() const { return mCurves; }
  109. /** Assigns a new set of curves to be used by the animation. The clip will store a copy of this object.*/
  110. void setCurves(const AnimationCurves& curves);
  111. /** Returns all events that will be triggered by the animation. */
  112. const Vector<AnimationEvent>& getEvents() const { return mEvents; }
  113. /** Sets events that will be triggered as the animation is playing. */
  114. void setEvents(const Vector<AnimationEvent>& events) { mEvents = events; }
  115. /**
  116. * Returns a set of curves containing motion of the root bone. This allows the user to evaluate the root bone
  117. * animation curves manually, instead of through the normal animation process. This property is only available
  118. * if animation clip was imported with root motion import enabled.
  119. */
  120. SPtr<RootMotion> getRootMotion() const { return mRootMotion; }
  121. /** Checks if animation clip has root motion curves separate from the normal animation curves. */
  122. bool hasRootMotion() const;
  123. /**
  124. * Maps skeleton bone names to animation curve names, and returns a set of indices that can be easily used for
  125. * locating an animation curve based on the bone index.
  126. *
  127. * @param[in] skeleton Skeleton to create the mapping for.
  128. * @param[out] mapping Pre-allocated array that will receive output animation clip indices. The array must
  129. * be large enough to store an index for every bone in the @p skeleton. Bones that have
  130. * no related animation curves will be assigned value -1.
  131. */
  132. void getBoneMapping(const Skeleton& skeleton, AnimationCurveMapping* mapping) const;
  133. /**
  134. * Attempts to find translation/rotation/scale curves with the specified name and fills the mapping structure with
  135. * their indices, which can then be used for quick lookup.
  136. *
  137. * @param[in] name Name of the curves to look up.
  138. * @param[out] mapping Triple containing the translation/rotation/scale indices of the found curves. Indices
  139. * will be -1 for curves that haven't been found.
  140. */
  141. void getCurveMapping(const String& name, AnimationCurveMapping& mapping) const;
  142. /**
  143. * Attempts to find a generic curve with the specified name and fills output with found index, which can then be
  144. * used for quick lookup.
  145. *
  146. * @param[in] name Name of the curve to look up.
  147. * @param[out] frameIdx Index of the curve animating the morph shape frames, or -1 if not found.
  148. * @param[out] weightIdx Index of the curve animating the channel weight, or -1 if not found.
  149. */
  150. void getMorphMapping(const String& name, UINT32& frameIdx, UINT32& weightIdx) const;
  151. /**
  152. * Checks are the curves contained within the clip additive. Additive clips are intended to be added on top of
  153. * other clips.
  154. */
  155. bool isAdditive() const { return mIsAdditive; }
  156. /** Returns the length of the animation clip, in seconds. */
  157. float getLength() const { return mLength; }
  158. /**
  159. * Returns the number of samples per second the animation clip curves were sampled at.
  160. *
  161. * @note This value is not used by the animation clip or curves directly since unevenly spaced keyframes are
  162. * supported. But it can be of value when determining the original sample rate of an imported animation
  163. * or similar.
  164. */
  165. UINT32 getSampleRate() const { return mSampleRate; }
  166. /**
  167. * Sets the number of samples per second the animation clip curves were sampled at.
  168. *
  169. * @see getSampleRate()
  170. */
  171. void setSampleRate(UINT32 sampleRate) { mSampleRate = sampleRate; }
  172. /**
  173. * Returns a version that can be used for detecting modifications on the clip by external systems. Whenever the clip
  174. * is modified the version is increased by one.
  175. */
  176. UINT64 getVersion() const { return mVersion; }
  177. /**
  178. * Creates an animation clip with no curves. After creation make sure to register some animation curves before
  179. * using it.
  180. */
  181. static HAnimationClip create(bool isAdditive = false);
  182. /**
  183. * Creates an animation clip with specified curves.
  184. *
  185. * @param[in] curves Curves to initialize the animation with.
  186. * @param[in] isAdditive Determines does the clip contain additive curve data. This will change the behaviour
  187. * how is the clip blended with other animations.
  188. * @param[in] sampleRate If animation uses evenly spaced keyframes, number of samples per second. Not relevant
  189. * if keyframes are unevenly spaced.
  190. * @param[in] rootMotion Optional set of curves that can be used for animating the root bone. Not used by the
  191. * animation system directly but is instead provided to the user for manual evaluation.
  192. */
  193. static HAnimationClip create(const SPtr<AnimationCurves>& curves, bool isAdditive = false, UINT32 sampleRate = 1,
  194. const SPtr<RootMotion>& rootMotion = nullptr);
  195. public: // ***** INTERNAL ******
  196. /** @name Internal
  197. * @{
  198. */
  199. /** Creates a new AnimationClip without initializing it. Use create() for normal use. */
  200. static SPtr<AnimationClip> _createPtr(const SPtr<AnimationCurves>& curves, bool isAdditive = false,
  201. UINT32 sampleRate = 1, const SPtr<RootMotion>& rootMotion = nullptr);
  202. /** @} */
  203. protected:
  204. AnimationClip();
  205. AnimationClip(const SPtr<AnimationCurves>& curves, bool isAdditive, UINT32 sampleRate,
  206. const SPtr<RootMotion>& rootMotion);
  207. /** @copydoc Resource::initialize() */
  208. void initialize() override;
  209. /** Creates a name -> curve index mapping for quicker curve lookup by name. */
  210. void buildNameMapping();
  211. /** Calculate the length of the clip based on assigned curves. */
  212. void calculateLength();
  213. UINT64 mVersion;
  214. /**
  215. * Contains all the animation curves in the clip. It's important this field is immutable so it may be used on other
  216. * threads. This means any modifications to the field will require a brand new data structure to be generated and
  217. * all existing data copied (plus the modification).
  218. */
  219. SPtr<AnimationCurves> mCurves;
  220. /**
  221. * A set of curves containing motion of the root bone. If this is non-empty it should be true that mCurves does not
  222. * contain animation curves for the root bone. Root motion will not be evaluated through normal animation process
  223. * but is instead provided for the user for manual evaluation.
  224. */
  225. SPtr<RootMotion> mRootMotion;
  226. /**
  227. * Contains a map from curve name to curve index. Indices are stored as specified in CurveType enum.
  228. */
  229. UnorderedMap<String, UINT32[(int)CurveType::Count]> mNameMapping;
  230. Vector<AnimationEvent> mEvents;
  231. bool mIsAdditive;
  232. float mLength;
  233. UINT32 mSampleRate;
  234. /************************************************************************/
  235. /* SERIALIZATION */
  236. /************************************************************************/
  237. public:
  238. friend class AnimationClipRTTI;
  239. static RTTITypeBase* getRTTIStatic();
  240. RTTITypeBase* getRTTI() const override;
  241. /**
  242. * Creates an AnimationClip with no data. You must populate its data manually followed by a call to initialize().
  243. *
  244. * @note For serialization use only.
  245. */
  246. static SPtr<AnimationClip> createEmpty();
  247. };
  248. /** @} */
  249. }