RavEngine
Loading...
Searching...
No Matches
AnimatorComponent.hpp
1#pragma once
2#include <ozz/animation/runtime/animation.h>
3#include <ozz/base/maths/soa_transform.h>
4#include "AnimationAsset.hpp"
5#include "DataStructures.hpp"
6#include "Ref.hpp"
7#include <algorithm>
8#include "Tween.hpp"
9#include "App.hpp"
10#include "Function.hpp"
11#include "Queryable.hpp"
12
13namespace RavEngine{
14
15struct Transform;
16class SkeletonAsset;
17struct SkeletonMask;
18
19using anim_id_t = uint16_t;
20
25 float x = 0, y = 0;
26public:
27 clamped_vec2(float ix, float iy) : x(std::clamp(ix,-1.0f,1.0f)), y(std::clamp(iy,-1.0f,1.0f)){}
28 clamped_vec2(){}
29
30 constexpr inline decltype(x) get_x() const{
31 return x;
32 }
33 constexpr inline decltype(y) get_y() const{
34 return y;
35 }
36};
37
42struct AnimBlendTree : public IAnimGraphable{
43 struct Node : public IAnimGraphable{
44
46 clamped_vec2 graph_pos;
47 float max_influence = 1;
48
49 Node(){}
50
51 template<typename T>
52 Node(Ref<T> s, const clamped_vec2& pos, float i = 1) : state(std::static_pointer_cast<IAnimGraphable>(s)), graph_pos(pos), max_influence(i){}
53
60 bool Sample(float t, float start, float speed, bool looping, ozz::vector<ozz::math::SoaTransform>&, ozz::animation::SamplingJob::Context& cache, const ozz::animation::Skeleton* skeleton) const override;
61 };
62
63 static constexpr uint16_t kmax_nodes = 64;
64
70 inline void InsertNode(anim_id_t id, const Node& node){
71 states[id].node = node;
72 }
73
78 inline void DeleteNode(anim_id_t id){
79 states.erase(id);
80 }
81
88 Node& GetNode(const anim_id_t id){
89 return states.at(id).node;
90 }
91
95 inline bool IsEmpty() const{
96 return states.empty();
97 }
98
102 inline void Clear(){
103 states.clear();
104 }
105
112 bool Sample(float t, float start, float speed, bool looping, ozz::vector<ozz::math::SoaTransform>&, ozz::animation::SamplingJob::Context& cache, const ozz::animation::Skeleton* skeleton) const override;
113
118 constexpr inline void SetBlendPos(const clamped_vec2& newPos){
119 blend_pos = newPos;
120 }
121
122private:
123 struct Sampler{
124 ozz::vector<ozz::math::SoaTransform> locals;
125 Node node;
126 };
127 locked_node_hashmap<anim_id_t,Sampler,SpinLock> states;
128 clamped_vec2 blend_pos;
129};
130
131#if !RVE_SERVER
132class AnimatorComponent : public IDebugRenderable, public Queryable<AnimatorComponent,IDebugRenderable>
133#else
134class AnimatorComponent : public AutoCTTI, public Queryable<AnimatorComponent>
135#endif
136{
137 Ref<SkeletonAsset> skeleton;
138public:
139
140 MOVE_NO_COPY(AnimatorComponent);
141 static constexpr uint16_t kmax_layers = 32;
142
143 //a node in the state machine
144 struct State{
145 friend class AnimatorComponent;
146 anim_id_t ID = 0;
148 bool isLooping = true;
149 float speed = 1;
150
151 double lastPlayTime = 0;
152
154 enum class TimeMode{
155 Blended = 0, //the time from this state carries over to the target state
156 BeginNew = 1 //the target state's time is set to 0 when the transition begins
157 } type = TimeMode::Blended;
158 tweeny::tween<float> transition;
159 };
160
161 //transitions out of this state, keyed by ID
162 UnorderedMap<decltype(ID),Transition> exitTransitions;
163
164 template<typename T, typename decimal>
165 constexpr inline State& SetTransition(decltype(ID) id, T interpolation, decimal duration, Transition::TimeMode mode = Transition::TimeMode::Blended){
166 auto tween = tweeny::from(0.0f).to(1.0f).during(static_cast<float>(duration * GetApp()->evalNormal)).via(interpolation);
167 exitTransitions[id].transition = tween;
168 exitTransitions[id].type = mode;
169 return *this;
170 }
171
175 State(decltype(ID) ID, decltype(clip) clip, decltype(isLooping) il = true, decltype(speed) speed = 1) : ID(ID), clip(clip), isLooping(il), speed(speed) {}
176
177 private:
178 bool hasAutoTransition = false;
179 decltype(ID) autoTransitionID = 0;
180 Function<void(decltype(State::ID))> beginCallback, endCallback;
181
182 inline void DoBegin(decltype(ID) prevState) {
183 if (beginCallback) {
184 beginCallback(prevState);
185 }
186 }
187
188 inline void DoEnd(decltype(ID) nextState) {
189 if (endCallback) {
190 endCallback(nextState);
191 }
192 }
193 public:
194
200 constexpr inline void SetAutoTransition(decltype(ID) id) {
201 hasAutoTransition = true;
202 autoTransitionID = id;
203 }
204
208 constexpr inline void ClearAutoTransition() {
209 hasAutoTransition = false;
210 }
211
216 inline void SetBeginCallback(const decltype(beginCallback)& bc) {
217 beginCallback = bc;
218 }
219
224 inline void SetEndCallback(const decltype(endCallback)& ec) {
225 endCallback = ec;
226 }
227
228 constexpr inline bool HasAutoTransition() const{
229 return hasAutoTransition;
230 }
231
232 constexpr inline decltype(autoTransitionID) GetAutoTransitionID() const {
233 return autoTransitionID;
234 }
235 };
236
241 AnimatorComponent(Ref<SkeletonAsset> sk);
242
243 struct Layer{
244 friend class AnimatorComponent;
245
246 Layer(const Layer&) = delete; // no copy
247 Layer(Layer&&) = default; // movable
248 Layer(){}
249 Layer(const Ref<SkeletonMask>& mask) : skeletonMask(mask){}
255 void Goto(anim_id_t newState, bool skipTransition = false);
256
261 inline void InsertState(const State& state){
262 states.insert(std::make_pair(state.ID,state));
263 }
264
269 void Play(float resetPlayhead = false);
270
271 void Pause();
272
273 void UpdateBuffers(const Ref<SkeletonAsset>& skeleton);
274
278 auto GetCurrentState() const{
279 return currentState;
280 }
281
282 void SetSkeletonMask(Ref<SkeletonMask> mask) {
283 skeletonMask = mask;
284 }
285
286 auto& GetSkeletonMask() const{
287 return skeletonMask;
288 }
289
290 void SetWeight(float w){
291 weight = w;
292 }
293 float GetWeight() const{
294 return weight;
295 }
296
297 bool SetAdditive(bool additive){
298 isAdditive = additive;
299 }
300
301 private:
302 std::optional<Ref<SkeletonMask>> skeletonMask;
303 double lastPlayTime = 0;
304 float weight = 1;
305 bool isAdditive = false;
306 State& GetStateForID(anim_id_t id);
307 locked_node_hashmap<anim_id_t,State,SpinLock> states;
308
309 struct StateBlend{
310 anim_id_t from = 0, to = 0;
311 decltype(State::Transition::transition) currentTween;
312 } stateBlend;
313
314 anim_id_t currentState = 0;
315
316 bool isPlaying = false;
317 bool isBlending = false;
318 float currentBlendingValue = 0;
319
320 inline void EndState(State& state, decltype(State::ID) nextState) {
321 state.DoEnd(nextState);
322 if (state.HasAutoTransition()) {
323 Goto(state.GetAutoTransitionID());
324 }
325 }
326
327 void Tick(const Ref<SkeletonAsset>& skeleton);
328
329 ozz::vector<ozz::math::SoaTransform> transforms, transformsSecondaryBlending;
330 std::shared_ptr<ozz::animation::SamplingJob::Context> cache = std::make_shared<ozz::animation::SamplingJob::Context>();
331 };
332
333
338 void Tick(const Transform& t);
339
340 inline decltype(skeleton) GetSkeleton() const{
341 return skeleton;
342 }
343#if !RVE_SERVER
344
345 virtual void DebugDraw(RavEngine::DebugDrawer& dbg, const Transform&) const override;
346#endif
347
348 void UpdateSocket(const std::string&, Transform&) const;
349
350protected:
351
352
353 mutable ozz::vector<matrix4> glm_pose;
354 ozz::vector<matrix4> local_pose;
355 ozz::vector<matrix4> skinningmats;
356 ozz::vector<ozz::math::Float4x4> models;
357 ozz::vector<ozz::math::SoaTransform> all_transforms;
358
359 Vector<std::unique_ptr<Layer>> layers;
360
361
365 void UpdateSkeletonData(Ref<SkeletonAsset> sk);
366
367public:
368
373 Layer* AddLayer();
374
375 Layer* GetLayerAtIndex(uint16_t index){
376 return layers.at(index).get();
377 };
378
383 const decltype(glm_pose)& GetPose(const Transform& t) const;
384
385 const decltype(local_pose)& GetLocalPose();
386
387 inline const decltype(skinningmats)& GetSkinningMats(){
388 return skinningmats;
389 }
390
391};
392
393}
Definition AnimatorComponent.hpp:136
void UpdateSkeletonData(Ref< SkeletonAsset > sk)
Definition AnimatorComponent.cpp:258
const decltype(glm_pose) & GetPose(const Transform &t) const
Definition AnimatorComponent.cpp:303
AnimatorComponent(Ref< SkeletonAsset > sk)
Definition AnimatorComponent.cpp:33
virtual void DebugDraw(RavEngine::DebugDrawer &dbg, const Transform &) const override
Definition AnimatorComponent.cpp:385
void Tick(const Transform &t)
Definition AnimatorComponent.cpp:108
Layer * AddLayer()
Definition AnimatorComponent.cpp:287
Definition DebugDrawer.hpp:11
Definition AnimatorComponent.hpp:24
Definition concurrentqueue.h:747
Definition skeleton.h:61
Definition phmap.h:4308
uint16 uint16_t
Definition fwd.hpp:117
Definition Animation.hpp:6
Definition AnimatorComponent.hpp:43
bool Sample(float t, float start, float speed, bool looping, ozz::vector< ozz::math::SoaTransform > &, ozz::animation::SamplingJob::Context &cache, const ozz::animation::Skeleton *skeleton) const override
Definition AnimatorComponent.cpp:342
Definition AnimatorComponent.hpp:42
bool Sample(float t, float start, float speed, bool looping, ozz::vector< ozz::math::SoaTransform > &, ozz::animation::SamplingJob::Context &cache, const ozz::animation::Skeleton *skeleton) const override
Definition AnimatorComponent.cpp:346
Node & GetNode(const anim_id_t id)
Definition AnimatorComponent.hpp:88
void DeleteNode(anim_id_t id)
Definition AnimatorComponent.hpp:78
constexpr void SetBlendPos(const clamped_vec2 &newPos)
Definition AnimatorComponent.hpp:118
bool IsEmpty() const
Definition AnimatorComponent.hpp:95
void Clear()
Definition AnimatorComponent.hpp:102
void InsertNode(anim_id_t id, const Node &node)
Definition AnimatorComponent.hpp:70
Definition AnimatorComponent.hpp:243
void InsertState(const State &state)
Definition AnimatorComponent.hpp:261
void Play(float resetPlayhead=false)
Definition AnimatorComponent.cpp:87
void Goto(anim_id_t newState, bool skipTransition=false)
Definition AnimatorComponent.cpp:46
auto GetCurrentState() const
Definition AnimatorComponent.hpp:278
Definition AnimatorComponent.hpp:153
Definition AnimatorComponent.hpp:144
void SetEndCallback(const decltype(endCallback)&ec)
Definition AnimatorComponent.hpp:224
State(decltype(ID) ID, decltype(clip) clip, decltype(isLooping) il=true, decltype(speed) speed=1)
Definition AnimatorComponent.hpp:175
constexpr void SetAutoTransition(decltype(ID) id)
Definition AnimatorComponent.hpp:200
constexpr void ClearAutoTransition()
Definition AnimatorComponent.hpp:208
void SetBeginCallback(const decltype(beginCallback)&bc)
Definition AnimatorComponent.hpp:216
Definition CTTI.hpp:14
Definition IDebugRenderable.hpp:8
Definition Queryable.hpp:21