1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#pragma once
4
5#include "BsCorePrerequisites.h"
6#include "Utility/BsModule.h"
7#include "CoreThread/BsCoreThread.h"
8#include "Math/BsConvexVolume.h"
9#include "RenderAPI/BsVertexDataDesc.h"
10
11namespace bs
12{
13 struct AnimationProxy;
14
15 /** @addtogroup Animation-Internal
16 * @{
17 */
18
19 /** Contains skeleton poses for all animations evaluated on a single frame. */
20 struct EvaluatedAnimationData
21 {
22 /** Contains meta-data about a calculated skeleton pose. Actual data maps to the @p transforms buffer. */
23 struct PoseInfo
24 {
25 UINT64 animId;
26 UINT32 startIdx;
27 UINT32 numBones;
28 };
29
30 /** Contains data about a calculated morph shape. */
31 struct MorphShapeInfo
32 {
33 SPtr<MeshData> meshData;
34 UINT32 version;
35 };
36
37 /** Contains meta-data about where calculated animation data is stored. */
38 struct AnimInfo
39 {
40 PoseInfo poseInfo;
41 MorphShapeInfo morphShapeInfo;
42 };
43
44 /**
45 * Maps animation ID to a animation information structure, which points to relevant skeletal or morph shape data.
46 */
47 UnorderedMap<UINT64, AnimInfo> infos;
48
49 /** Global joint transforms for all skeletons in the scene. */
50 Vector<Matrix4> transforms;
51 };
52
53 /**
54 * Keeps track of all active animations, queues animation thread tasks and synchronizes data between simulation, core
55 * and animation threads.
56 */
57 class BS_CORE_EXPORT AnimationManager : public Module<AnimationManager>
58 {
59 public:
60 AnimationManager();
61
62 /** Pauses or resumes the animation evaluation. */
63 void setPaused(bool paused);
64
65 /**
66 * Determines how often to evaluate animations. If rendering is not running at adequate framerate the animation
67 * could end up being evaluated less times than specified here.
68 *
69 * @param[in] fps Number of frames per second to evaluate the animation. Default is 60.
70 */
71 void setUpdateRate(UINT32 fps);
72
73 /**
74 * Evaluates animations for all animated objects, and returns the evaluated skeleton bone poses and morph shape
75 * meshes that can be passed along to the renderer.
76 *
77 * @param[in] async If true the method returns immediately while the animation gets evaluated in the
78 * background. The returned evaluated data will be the data from the previous frame.
79 * Therefore note that this introduces a one frame latency on the animation. If the
80 * latency is not acceptable set this to false, at a potential performance impact.
81 * @return Evaluated animation data for this frame (if @p async is false), or the previous
82 * frame (if @p async is true). Note that the system re-uses the returned buffers,
83 * and the returned buffer should stop being used after every second call to update().
84 * This is enough to have one buffer be processed by the core thread, one queued
85 * for future rendering and one that's being written to.
86 */
87 const EvaluatedAnimationData* update(bool async = true);
88
89 private:
90 friend class Animation;
91
92 /** Possible states the worker thread can be in, used for synchronization. */
93 enum class WorkerState
94 {
95 Inactive,
96 Started,
97 DataReady
98 };
99
100 /**
101 * Registers a new animation and returns a unique ID for it. Must be called whenever an Animation is constructed.
102 */
103 UINT64 registerAnimation(Animation* anim);
104
105 /** Unregisters an animation with the specified ID. Must be called before an Animation is destroyed. */
106 void unregisterAnimation(UINT64 id);
107
108 /**
109 * Evaluates animation for a single object and writes the result in the currently active write buffer.
110 *
111 * @param[in] anim Proxy representing the animation to evaluate.
112 * @param[in] boneIdx Index in the output buffer in which to write evaluated bone information. This will be
113 * automatically advanced by the number of written bone transforms.
114 */
115 void evaluateAnimation(AnimationProxy* anim, UINT32& boneIdx);
116
117 UINT64 mNextId = 1;
118 UnorderedMap<UINT64, Animation*> mAnimations;
119
120 float mUpdateRate = 1.0f / 60.0f;
121 float mAnimationTime = 0.0f;
122 float mLastAnimationUpdateTime = 0.0f;
123 float mNextAnimationUpdateTime = 0.0f;
124 float mLastAnimationDeltaTime = 0.0f;
125 bool mPaused = false;
126
127 SPtr<VertexDataDesc> mBlendShapeVertexDesc;
128
129 // Animation thread
130 Vector<SPtr<AnimationProxy>> mProxies;
131 Vector<ConvexVolume> mCullFrustums;
132 EvaluatedAnimationData mAnimData[CoreThread::NUM_SYNC_BUFFERS + 1];
133
134 UINT32 mPoseReadBufferIdx = 2;
135 UINT32 mPoseWriteBufferIdx = 0;
136
137 Signal mWorkerDoneSignal;
138 Mutex mMutex;
139
140 UINT32 mNumActiveWorkers = 0;
141 bool mSwapBuffers = false;
142 };
143
144 /** Provides easier access to AnimationManager. */
145 BS_CORE_EXPORT AnimationManager& gAnimation();
146
147 /** @} */
148}
149