BsAnimation.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  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 "BsCoreObject.h"
  6. #include "BsFlags.h"
  7. #include "BsSkeleton.h"
  8. #include "BsVector2.h"
  9. namespace BansheeEngine
  10. {
  11. /** @addtogroup Animation-Internal
  12. * @{
  13. */
  14. /** Determines how an animation clip behaves when it reaches the end. */
  15. enum class AnimWrapMode
  16. {
  17. Loop, /**< Loop around to the beginning/end when the last/first frame is reached. */
  18. Clamp /**< Clamp to end/beginning, keeping the last/first frame active. */
  19. };
  20. /** Flags that determine which portion of Animation was changed and needs to be updated. */
  21. enum class AnimDirtyStateFlag
  22. {
  23. Clean = 0,
  24. Value = 1 << 0,
  25. Layout = 1 << 1,
  26. Skeleton = 1 << 2
  27. };
  28. typedef Flags<AnimDirtyStateFlag> AnimDirtyState;
  29. BS_FLAGS_OPERATORS(AnimDirtyStateFlag)
  30. /** Contains information about a currently playing animation clip. */
  31. struct AnimationClipState
  32. {
  33. AnimationClipState() { }
  34. /** Layer the clip is playing on. Multiple clips can be played simulatenously on different layers. */
  35. UINT32 layer = 0;
  36. float time = 0.0f; /**< Current time the animation is playing from. */
  37. float speed = 1.0f; /**< Speed at which the animation is playing. */
  38. float weight = 1.0f; /**< Determines how much of an influence does the clip have on the final pose. */
  39. /** Determines what happens to other animation clips when a new clip starts playing. */
  40. AnimWrapMode wrapMode = AnimWrapMode::Loop;
  41. };
  42. /** Internal information about a single playing animation clip within Animation. */
  43. struct AnimationClipInfo
  44. {
  45. AnimationClipInfo();
  46. AnimationClipInfo(const HAnimationClip& clip);
  47. HAnimationClip clip;
  48. AnimationClipState state;
  49. float fadeDirection;
  50. float fadeTime;
  51. float fadeLength;
  52. /**
  53. * Version of the animation curves used by the AnimationProxy. Used to detecting the internal animation curves
  54. * changed.
  55. */
  56. UINT64 curveVersion;
  57. UINT32 layerIdx; /**< Layer index this clip belongs to in AnimationProxy structure. */
  58. UINT32 stateIdx; /**< State index this clip belongs to in AnimationProxy structure. */
  59. };
  60. /** Defines a single animation clip in BlendSequentialInfo. */
  61. struct BS_CORE_EXPORT BlendSequentialClipInfo
  62. {
  63. BlendSequentialClipInfo() { }
  64. HAnimationClip clip;
  65. float fadeTime = 0.0f;
  66. float startTime = 0.0f;
  67. float endTime = 0.0f;
  68. };
  69. /** Defines a sequential blend where one animation clip is played after another, with an optional fade between them. */
  70. struct BS_CORE_EXPORT BlendSequentialInfo
  71. {
  72. BlendSequentialInfo(UINT32 numClips);
  73. ~BlendSequentialInfo();
  74. BlendSequentialClipInfo* clips;
  75. UINT32 numClips;
  76. };
  77. /** Defines a 1D blend where two animation clips are blended between each other using linear interpolation. */
  78. struct Blend1DInfo
  79. {
  80. HAnimationClip leftClip;
  81. HAnimationClip rightClip;
  82. };
  83. /** Defines a 2D blend where two animation clips are blended between each other using bilinear interpolation. */
  84. struct Blend2DInfo
  85. {
  86. HAnimationClip topLeftClip;
  87. HAnimationClip topRightClip;
  88. HAnimationClip botLeftClip;
  89. HAnimationClip botRightClip;
  90. };
  91. /** Represents a copy of the Animation data for use specifically on the animation thread. */
  92. struct AnimationProxy
  93. {
  94. AnimationProxy(UINT64 id);
  95. ~AnimationProxy();
  96. /**
  97. * Rebuilds the internal proxy data according to the newly assigned skeleton and clips. This should be called
  98. * whenever the animation skeleton changes.
  99. *
  100. * @param[in] skeleton New skeleton to assign to the proxy.
  101. * @param[in, out] clipInfos Potentially new clip infos that will be used for rebuilding the proxy. Once the
  102. * method completes clip info layout and state indices will be populated for
  103. * further use in the update*() methods.
  104. *
  105. * @note Should be called from the sim thread when the caller is sure the animation thread is not using it.
  106. */
  107. void rebuild(const SPtr<Skeleton>& skeleton, Vector<AnimationClipInfo>& clipInfos);
  108. /**
  109. * Rebuilds the internal proxy data according to the newly clips. This should be called whenever clips are added
  110. * or removed, or clip layout indices change.
  111. *
  112. * @param[in, out] clipInfos New clip infos that will be used for rebuilding the proxy. Once the method completes
  113. * clip info layout and state indices will be populated for further use in the
  114. * update*() methods.
  115. *
  116. * @note Should be called from the sim thread when the caller is sure the animation thread is not using it.
  117. */
  118. void rebuild(Vector<AnimationClipInfo>& clipInfos);
  119. /**
  120. * Updates the proxy data with new information about the clips. Caller must guarantee that clip layout didn't
  121. * change since the last call to rebuild().
  122. *
  123. * @note Should be called from the sim thread when the caller is sure the animation thread is not using it.
  124. */
  125. void updateValues(const Vector<AnimationClipInfo>& clipInfos);
  126. /**
  127. * Updates the proxy data with new clip times. Caller must guarantee that clip layout didn't change since the last
  128. * call to rebuild().
  129. *
  130. * @note Should be called from the sim thread when the caller is sure the animation thread is not using it.
  131. */
  132. void updateTime(const Vector<AnimationClipInfo>& clipInfos);
  133. UINT64 id;
  134. AnimationStateLayer* layers;
  135. UINT32 numLayers;
  136. SPtr<Skeleton> skeleton;
  137. // Evaluation results
  138. LocalSkeletonPose localPose;
  139. float* genericCurveOutputs;
  140. };
  141. /**
  142. * Handles animation playback. Takes one or multiple animation clips as input and evaluates them every animation update
  143. * tick depending on set properties. The evaluated data is used by the core thread for skeletal animation, by the sim
  144. * thread for updating attached scene objects and bones (if skeleton is attached), or the data is made available for
  145. * manual queries in the case of generic animation.
  146. */
  147. class BS_CORE_EXPORT Animation : public CoreObject
  148. {
  149. public:
  150. ~Animation();
  151. /**
  152. * Changes the skeleton which will the translation/rotation/scale animation values manipulate. If no skeleton is set
  153. * the animation will only evaluate the generic curves, and the root translation/rotation/scale curves.
  154. */
  155. void setSkeleton(const SPtr<Skeleton>& skeleton);
  156. /**
  157. * Changes the wrap mode for all active animations. Wrap mode determines what happens when animation reaches the
  158. * first or last frame.
  159. *
  160. * @see AnimWrapMode
  161. */
  162. void setWrapMode(AnimWrapMode wrapMode);
  163. /** Changes the speed for all animations. The default value is 1.0f. Use negative values to play-back in reverse. */
  164. void setSpeed(float speed);
  165. /**
  166. * Plays the specified animation clip.
  167. *
  168. * @param[in] clip Clip to play.
  169. */
  170. void play(const HAnimationClip& clip);
  171. /**
  172. * Plays the specified animation clip on top of the animation currently playing in the main layer. Multiple
  173. * such clips can be playing at once, as long as you ensure each is given its own layer. Each animation can
  174. * also have a weight that determines how much it influences the main animation.
  175. *
  176. * @param[in] clip Clip to additively blend. Must contain additive animation curves.
  177. * @param[in] weight Determines how much of an effect will the blended animation have on the final output.
  178. * In range [0, 1].
  179. * @param[in] fadeLength Applies the blend over a specified time period, increasing the weight as the time
  180. * passes. Set to zero to blend immediately. In seconds.
  181. * @param[in] layer Layer to play the clip in. Multiple additive clips can be playing at once in separate
  182. * layers and each layer has its own weight.
  183. */
  184. void blendAdditive(const HAnimationClip& clip, float weight, float fadeLength = 0.0f, UINT32 layer = 0);
  185. /**
  186. * Plays a set of animation clips sequentially one after another, with an optional fade between them.
  187. *
  188. * @param[in] info Describes all animation clips to play.
  189. */
  190. void blendSequential(const BlendSequentialInfo& info);
  191. /**
  192. * Blend two animation clips between each other using linear interpolation. Unlike normal animations these
  193. * animations are not advanced with the progress of time, and is instead expected the user manually changes the
  194. * @p t parameter.
  195. *
  196. * @param[in] info Information about the clips to blend.
  197. * @param[in] t Parameter that controls the blending, in range [0, 1]. t = 0 means left animation has full
  198. * influence, t = 1 means right animation has full influence.
  199. */
  200. void blend1D(const Blend1DInfo& info, float t);
  201. /**
  202. * Blend four animation clips between each other using bilinear interpolation. Unlike normal animations these
  203. * animations are not advanced with the progress of time, and is instead expected the user manually changes the
  204. * @p t parameter.
  205. *
  206. * @param[in] info Information about the clips to blend.
  207. * @param[in] t Parameter that controls the blending, in range [(0, 0), (1, 1)]. t = (0, 0) means top left
  208. * animation has full influence, t = (0, 1) means top right animation has full influence,
  209. * t = (1, 0) means bottom left animation has full influence, t = (1, 1) means bottom right
  210. * animation has full influence.
  211. */
  212. void blend2D(const Blend2DInfo& info, const Vector2& t);
  213. /**
  214. * Fades the specified animation clip in, while fading other playing animation out, over the specified time
  215. * period.
  216. *
  217. * @param[in] clip Clip to fade in.
  218. * @param[in] fadeLength Determines the time period over which the fade occurs. In seconds.
  219. */
  220. void crossFade(const HAnimationClip& clip, float fadeLength);
  221. /**
  222. * Stops playing all animations on the provided layer. Specify -1 to stop animation on the main layer
  223. * (non-additive animations).
  224. */
  225. void stop(UINT32 layer);
  226. /** Stops playing all animations. */
  227. void stopAll();
  228. /** Checks if any animation clips are currently playing. */
  229. bool isPlaying() const;
  230. /**
  231. * Retrieves detailed information about a currently playing animation clip.
  232. *
  233. * @param[in] clip Clip to retrieve the information for.
  234. * @param[out] state Animation clip state containing the requested information. Only valid if the method returns
  235. * true.
  236. * @return True if the state was found (animation clip is playing), false otherwise.
  237. */
  238. bool getState(const HAnimationClip& clip, AnimationClipState& state);
  239. /**
  240. * Changes the state of a playing animation clip. If animation clip is not currently playing the state change is
  241. * ignored.
  242. *
  243. * @param[in] clip Clip to change the state for.
  244. * @param[in] state New state of the animation (e.g. changing the time for seeking).
  245. */
  246. void setState(const HAnimationClip& clip, AnimationClipState state);
  247. /** Creates a new empty Animation object. */
  248. static SPtr<Animation> create();
  249. /** @name Internal
  250. * @{
  251. */
  252. /** Returns the unique ID for this animation object. */
  253. UINT64 _getId() const { return mId; }
  254. /** @} */
  255. private:
  256. friend class AnimationManager;
  257. Animation();
  258. /**
  259. * Updates the animation proxy object based on the currently set skeleton, playing clips and dirty flags.
  260. *
  261. * @param[in] timeDelta Seconds passed since the last call to this method.
  262. */
  263. void updateAnimProxy(float timeDelta);
  264. /**
  265. * Registers a new animation in the specified layer, or returns an existing animation clip info if the animation is
  266. * already registered. If @p stopExisting is true any existing animations in the layer will be stopped. Layout
  267. * will be marked as dirty if any changes were made.
  268. */
  269. AnimationClipInfo* addClip(const HAnimationClip& clip, UINT32 layer, bool stopExisting = true);
  270. UINT64 mId;
  271. AnimWrapMode mDefaultWrapMode;
  272. float mDefaultSpeed;
  273. AnimDirtyState mDirty;
  274. SPtr<Skeleton> mSkeleton;
  275. Vector<AnimationClipInfo> mClipInfos;
  276. // Animation thread only
  277. SPtr<AnimationProxy> mAnimProxy;
  278. };
  279. /** @} */
  280. }