BsAnimation.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  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 "BsSkeletonMask.h"
  9. #include "BsVector2.h"
  10. namespace BansheeEngine
  11. {
  12. /** @addtogroup Animation-Internal
  13. * @{
  14. */
  15. /** Determines how an animation clip behaves when it reaches the end. */
  16. enum class AnimWrapMode
  17. {
  18. Loop, /**< Loop around to the beginning/end when the last/first frame is reached. */
  19. Clamp /**< Clamp to end/beginning, keeping the last/first frame active. */
  20. };
  21. /** Flags that determine which portion of Animation was changed and needs to be updated. */
  22. enum class AnimDirtyStateFlag
  23. {
  24. Clean = 0,
  25. Value = 1 << 0,
  26. Layout = 1 << 1,
  27. Skeleton = 1 << 2
  28. };
  29. typedef Flags<AnimDirtyStateFlag> AnimDirtyState;
  30. BS_FLAGS_OPERATORS(AnimDirtyStateFlag)
  31. /** Contains information about a currently playing animation clip. */
  32. struct AnimationClipState
  33. {
  34. AnimationClipState() { }
  35. /** Layer the clip is playing on. Multiple clips can be played simulatenously on different layers. */
  36. UINT32 layer = 0;
  37. float time = 0.0f; /**< Current time the animation is playing from. */
  38. float speed = 1.0f; /**< Speed at which the animation is playing. */
  39. float weight = 1.0f; /**< Determines how much of an influence does the clip have on the final pose. */
  40. /** Determines what happens to other animation clips when a new clip starts playing. */
  41. AnimWrapMode wrapMode = AnimWrapMode::Loop;
  42. /**
  43. * Determines should the time be advanced automatically. Certain type of animation clips don't involve playback
  44. * (e.g. for blending where animation weight controls the animation).
  45. */
  46. bool stopped = false;
  47. };
  48. /** Internal information about a single playing animation clip within Animation. */
  49. struct AnimationClipInfo
  50. {
  51. AnimationClipInfo();
  52. AnimationClipInfo(const HAnimationClip& clip);
  53. HAnimationClip clip;
  54. AnimationClipState state;
  55. float fadeDirection;
  56. float fadeTime;
  57. float fadeLength;
  58. /**
  59. * Version of the animation curves used by the AnimationProxy. Used to detecting the internal animation curves
  60. * changed.
  61. */
  62. UINT64 curveVersion;
  63. UINT32 layerIdx; /**< Layer index this clip belongs to in AnimationProxy structure. */
  64. UINT32 stateIdx; /**< State index this clip belongs to in AnimationProxy structure. */
  65. };
  66. /** Represents an animation clip used in 1D blending. Each clip has a position on the number line. */
  67. struct BS_CORE_EXPORT BlendClipInfo
  68. {
  69. BlendClipInfo() { }
  70. HAnimationClip clip;
  71. float position = 0.0f;
  72. };
  73. /** Defines a 1D blend where multiple animation clips are blended between each other using linear interpolation. */
  74. struct BS_CORE_EXPORT Blend1DInfo
  75. {
  76. Blend1DInfo(UINT32 numClips);
  77. ~Blend1DInfo();
  78. UINT32 numClips;
  79. BlendClipInfo* clips;
  80. };
  81. /** Defines a 2D blend where two animation clips are blended between each other using bilinear interpolation. */
  82. struct Blend2DInfo
  83. {
  84. HAnimationClip topLeftClip;
  85. HAnimationClip topRightClip;
  86. HAnimationClip botLeftClip;
  87. HAnimationClip botRightClip;
  88. };
  89. /** Contains a mapping between a scene object and an animation curve it is animated with. */
  90. struct AnimatedSceneObject
  91. {
  92. HSceneObject so;
  93. String curveName;
  94. };
  95. /** Contains information about a scene object that is animated by a specific animation curve. */
  96. struct AnimatedSceneObjectInfo
  97. {
  98. UINT64 id; /**< Instance ID of the scene object. */
  99. INT32 boneIdx; /**< Bone from which to access the transform. If -1 then no bone mapping is present. */
  100. INT32 layerIdx; /**< If no bone mapping, layer on which the animation containing the referenced curve is in. */
  101. INT32 stateIdx; /**< If no bone mapping, animation state containing the referenced curve. */
  102. AnimationCurveMapping curveIndices; /**< Indices of the curves used for the transform. */
  103. UINT32 hash; /**< Hash value of the scene object's transform. */
  104. };
  105. /** Represents a copy of the Animation data for use specifically on the animation thread. */
  106. struct AnimationProxy
  107. {
  108. AnimationProxy(UINT64 id);
  109. AnimationProxy(const AnimationProxy&) = delete;
  110. ~AnimationProxy();
  111. AnimationProxy& operator=(const AnimationProxy&) = delete;
  112. /**
  113. * Rebuilds the internal proxy data according to the newly assigned skeleton and clips. This should be called
  114. * whenever the animation skeleton changes.
  115. *
  116. * @param[in] skeleton New skeleton to assign to the proxy.
  117. * @param[in] mask Mask that filters which skeleton bones are enabled or disabled.
  118. * @param[in, out] clipInfos Potentially new clip infos that will be used for rebuilding the proxy. Once the
  119. * method completes clip info layout and state indices will be populated for
  120. * further use in the update*() methods.
  121. * @param[in] sceneObjects A list of scene objects that are influenced by specific animation curves.
  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 rebuild(const SPtr<Skeleton>& skeleton, const SkeletonMask& mask, Vector<AnimationClipInfo>& clipInfos,
  126. const Vector<AnimatedSceneObject>& sceneObjects);
  127. /**
  128. * Rebuilds the internal proxy data according to the newly clips. This should be called whenever clips are added
  129. * or removed, or clip layout indices change.
  130. *
  131. * @param[in, out] clipInfos New clip infos that will be used for rebuilding the proxy. Once the method
  132. * completes clip info layout and state indices will be populated for further use
  133. * in the update*() methods.
  134. * @param[in] sceneObjects A list of scene objects that are influenced by specific animation curves.
  135. *
  136. * @note Should be called from the sim thread when the caller is sure the animation thread is not using it.
  137. */
  138. void rebuild(Vector<AnimationClipInfo>& clipInfos, const Vector<AnimatedSceneObject>& sceneObjects);
  139. /**
  140. * Updates the proxy data with new information about the clips. Caller must guarantee that clip layout didn't
  141. * change since the last call to rebuild().
  142. *
  143. * @note Should be called from the sim thread when the caller is sure the animation thread is not using it.
  144. */
  145. void updateValues(const Vector<AnimationClipInfo>& clipInfos);
  146. /**
  147. * Updates the proxy data with new scene object transforms. Caller must guarantee that clip layout didn't
  148. * change since the last call to rebuild().
  149. *
  150. * @note Should be called from the sim thread when the caller is sure the animation thread is not using it.
  151. */
  152. void updateTransforms(const Vector<AnimatedSceneObject>& sceneObjects);
  153. /**
  154. * Updates the proxy data with new clip times. Caller must guarantee that clip layout didn't change since the last
  155. * call to rebuild().
  156. *
  157. * @note Should be called from the sim thread when the caller is sure the animation thread is not using it.
  158. */
  159. void updateTime(const Vector<AnimationClipInfo>& clipInfos);
  160. /** Destroys all dynamically allocated objects. */
  161. void clear();
  162. UINT64 id;
  163. AnimationStateLayer* layers;
  164. UINT32 numLayers;
  165. SPtr<Skeleton> skeleton;
  166. SkeletonMask skeletonMask;
  167. UINT32 numSceneObjects;
  168. AnimatedSceneObjectInfo* sceneObjectInfos;
  169. Matrix4* sceneObjectTransforms;
  170. // Evaluation results
  171. LocalSkeletonPose skeletonPose;
  172. LocalSkeletonPose sceneObjectPose;
  173. UINT32 numGenericCurves;
  174. float* genericCurveOutputs;
  175. };
  176. /**
  177. * Handles animation playback. Takes one or multiple animation clips as input and evaluates them every animation update
  178. * tick depending on set properties. The evaluated data is used by the core thread for skeletal animation, by the sim
  179. * thread for updating attached scene objects and bones (if skeleton is attached), or the data is made available for
  180. * manual queries in the case of generic animation.
  181. */
  182. class BS_CORE_EXPORT Animation : public CoreObject
  183. {
  184. public:
  185. ~Animation();
  186. /**
  187. * Changes the skeleton which will the translation/rotation/scale animation values manipulate. If no skeleton is set
  188. * the animation will only evaluate the generic curves, and the root translation/rotation/scale curves.
  189. */
  190. void setSkeleton(const SPtr<Skeleton>& skeleton);
  191. /**
  192. * Sets a mask that allows certain bones from the skeleton to be disabled. Caller must ensure that the mask matches
  193. * the skeleton assigned to the animation.
  194. */
  195. void setMask(const SkeletonMask& mask);
  196. /**
  197. * Changes the wrap mode for all active animations. Wrap mode determines what happens when animation reaches the
  198. * first or last frame.
  199. *
  200. * @see AnimWrapMode
  201. */
  202. void setWrapMode(AnimWrapMode wrapMode);
  203. /** Changes the speed for all animations. The default value is 1.0f. Use negative values to play-back in reverse. */
  204. void setSpeed(float speed);
  205. /**
  206. * Plays the specified animation clip.
  207. *
  208. * @param[in] clip Clip to play.
  209. */
  210. void play(const HAnimationClip& clip);
  211. /**
  212. * Plays the specified animation clip on top of the animation currently playing in the main layer. Multiple
  213. * such clips can be playing at once, as long as you ensure each is given its own layer. Each animation can
  214. * also have a weight that determines how much it influences the main animation.
  215. *
  216. * @param[in] clip Clip to additively blend. Must contain additive animation curves.
  217. * @param[in] weight Determines how much of an effect will the blended animation have on the final output.
  218. * In range [0, 1].
  219. * @param[in] fadeLength Applies the blend over a specified time period, increasing the weight as the time
  220. * passes. Set to zero to blend immediately. In seconds.
  221. * @param[in] layer Layer to play the clip in. Multiple additive clips can be playing at once in separate
  222. * layers and each layer has its own weight.
  223. */
  224. void blendAdditive(const HAnimationClip& clip, float weight, float fadeLength = 0.0f, UINT32 layer = 0);
  225. /**
  226. * Blend multiple animation clips between each other using linear interpolation. Unlike normal animations these
  227. * animations are not advanced with the progress of time, and is instead expected the user manually changes the
  228. * @p t parameter.
  229. *
  230. * @param[in] info Information about the clips to blend. Clip positions must be sorted from lowest to highest.
  231. * @param[in] t Parameter that controls the blending. Range depends on the positions of the provided
  232. * animation clips.
  233. */
  234. void blend1D(const Blend1DInfo& info, float t);
  235. /**
  236. * Blend four animation clips between each other using bilinear interpolation. Unlike normal animations these
  237. * animations are not advanced with the progress of time, and is instead expected the user manually changes the
  238. * @p t parameter.
  239. *
  240. * @param[in] info Information about the clips to blend.
  241. * @param[in] t Parameter that controls the blending, in range [(0, 0), (1, 1)]. t = (0, 0) means top left
  242. * animation has full influence, t = (0, 1) means top right animation has full influence,
  243. * t = (1, 0) means bottom left animation has full influence, t = (1, 1) means bottom right
  244. * animation has full influence.
  245. */
  246. void blend2D(const Blend2DInfo& info, const Vector2& t);
  247. /**
  248. * Fades the specified animation clip in, while fading other playing animation out, over the specified time
  249. * period.
  250. *
  251. * @param[in] clip Clip to fade in.
  252. * @param[in] fadeLength Determines the time period over which the fade occurs. In seconds.
  253. */
  254. void crossFade(const HAnimationClip& clip, float fadeLength);
  255. /**
  256. * Stops playing all animations on the provided layer. Specify -1 to stop animation on the main layer
  257. * (non-additive animations).
  258. */
  259. void stop(UINT32 layer);
  260. /** Stops playing all animations. */
  261. void stopAll();
  262. /** Checks if any animation clips are currently playing. */
  263. bool isPlaying() const;
  264. /** Returns the total number of animation clips influencing this animation. */
  265. UINT32 getNumClips() const;
  266. /**
  267. * Returns one of the animation clips influencing this animation.
  268. *
  269. * @param[in] idx Sequential index of the animation clip to retrieve. In range [0, getNumClips()].
  270. * @return Animation clip at the specified index, or null if the index is out of range.
  271. */
  272. HAnimationClip getClip(UINT32 idx) const;
  273. /**
  274. * Retrieves detailed information about a currently playing animation clip.
  275. *
  276. * @param[in] clip Clip to retrieve the information for.
  277. * @param[out] state Animation clip state containing the requested information. Only valid if the method returns
  278. * true.
  279. * @return True if the state was found (animation clip is playing), false otherwise.
  280. */
  281. bool getState(const HAnimationClip& clip, AnimationClipState& state);
  282. /**
  283. * Changes the state of a playing animation clip. If animation clip is not currently playing the state change is
  284. * ignored.
  285. *
  286. * @param[in] clip Clip to change the state for.
  287. * @param[in] state New state of the animation (e.g. changing the time for seeking).
  288. */
  289. void setState(const HAnimationClip& clip, AnimationClipState state);
  290. /**
  291. * Ensures that any position/rotation/scale animation of a specific animation curve is transfered to the
  292. * the provided scene object. Also allow the opposite operation which can allow scene object transform changes
  293. * to manipulate object bones.
  294. *
  295. * @param[in] curve Name of the curve (bone) to connect the scene object with. Use empty string to map to the
  296. * root bone, regardless of the bone name.
  297. * @param[in] so Scene object to influence by the curve modifications, and vice versa.
  298. */
  299. void mapCurveToSceneObject(const String& curve, const HSceneObject& so);
  300. /** Removes the curve <-> scene object mapping that was set via mapCurveToSceneObject(). */
  301. void unmapSceneObject(const HSceneObject& so);
  302. /**
  303. * Retrieves an evaluated value for a generic curve with the specified index.
  304. *
  305. * @param[in] curveIdx The curve index referencing a set of curves from the first playing animation clip.
  306. * Generic curves from all other clips are ignored.
  307. * @param[out] value Value of the generic curve. Only valid if the method return true.
  308. * @return True if the value was retrieved successfully. The method might fail if animation update
  309. * didn't yet have a chance to execute and values are not yet available, or if the
  310. * animation clip changed since the last frame (the last problem can be avoided by ensuring
  311. * to read the curve values before changing the clip).
  312. */
  313. bool getGenericCurveValue(UINT32 curveIdx, float& value);
  314. /** Creates a new empty Animation object. */
  315. static SPtr<Animation> create();
  316. /** Triggered whenever an animation event is reached. */
  317. Event<void(const HAnimationClip&, const String&)> onEventTriggered;
  318. /** @name Internal
  319. * @{
  320. */
  321. /** Returns the unique ID for this animation object. */
  322. UINT64 _getId() const { return mId; }
  323. /** @} */
  324. private:
  325. friend class AnimationManager;
  326. Animation();
  327. /**
  328. * Triggers any events between the last frame and current one.
  329. *
  330. * @param[in] lastFrameTime Time of the last frame.
  331. * @param[in] delta Difference between the last and this frame.
  332. */
  333. void triggerEvents(float lastFrameTime, float delta);
  334. /**
  335. * Updates the animation proxy object based on the currently set skeleton, playing clips and dirty flags.
  336. *
  337. * @param[in] timeDelta Seconds passed since the last call to this method.
  338. */
  339. void updateAnimProxy(float timeDelta);
  340. /**
  341. * Applies any outputs stored in the animation proxy (as written by the animation thread), and uses them to update
  342. * the animation state on the simulation thread. Caller must ensure that the animation thread has finished
  343. * with the animation proxy.
  344. */
  345. void updateFromProxy();
  346. /**
  347. * Registers a new animation in the specified layer, or returns an existing animation clip info if the animation is
  348. * already registered. If @p stopExisting is true any existing animations in the layer will be stopped. Layout
  349. * will be marked as dirty if any changes were made.
  350. */
  351. AnimationClipInfo* addClip(const HAnimationClip& clip, UINT32 layer, bool stopExisting = true);
  352. UINT64 mId;
  353. AnimWrapMode mDefaultWrapMode;
  354. float mDefaultSpeed;
  355. AnimDirtyState mDirty;
  356. SPtr<Skeleton> mSkeleton;
  357. SkeletonMask mSkeletonMask;
  358. Vector<AnimationClipInfo> mClipInfos;
  359. UnorderedMap<UINT64, AnimatedSceneObject> mSceneObjects;
  360. Vector<float> mGenericCurveOutputs;
  361. bool mGenericCurveValuesValid;
  362. // Animation thread only
  363. SPtr<AnimationProxy> mAnimProxy;
  364. };
  365. /** @} */
  366. }