Divide Framework 0.1
A free and open-source 3D Framework under heavy development
Loading...
Searching...
No Matches
SceneAnimator.cpp
Go to the documentation of this file.
1
2
6
9
10namespace Divide {
11
14void CalculateBoneToWorldTransform(Bone* pInternalNode) noexcept {
15 pInternalNode->globalTransform(pInternalNode->localTransform());
16 Bone* parent = pInternalNode->_parent;
17 // This will climb the nodes up along through the parents concatenating all
18 // the matrices to get the Object to World transform,
19 // or in this case, the Bone To World transform
20 while (parent) {
21 pInternalNode->globalTransform() *= parent->localTransform();
22 // get the parent of the bone we are working on
23 parent = parent->_parent;
24 }
25}
26
28{
29 release(true);
30}
31
32void SceneAnimator::release(const bool releaseAnimations)
33{
34 _bones.clear();
35 delete _skeleton;
36 _skeleton = nullptr;
37
38 // this should clean everything up
39 _skeletonLines.clear();
42 if (releaseAnimations)
43 {
44 // clear all animations
45 _animationNameToID.clear();
46 _animations.clear();
47 }
48}
49
50bool SceneAnimator::init([[maybe_unused]] PlatformContext& context) {
51 Console::d_printfn(LOCALE_STR("LOAD_ANIMATIONS_BEGIN"));
52
53 constexpr D64 timeStep = 1. / ANIMATION_TICKS_PER_SECOND;
55
56 const U32 animationCount = to_U32(_animations.size());
57 _skeletonLines.resize(animationCount);
58
59 // pre-calculate the animations
60 for (U32 i = 0u; i < animationCount; ++i)
61 {
62 AnimEvaluator* crtAnimation = _animations[i].get();
63 const D64 duration = crtAnimation->duration();
64 const D64 tickStep = crtAnimation->ticksPerSecond() / ANIMATION_TICKS_PER_SECOND;
65 D64 dt = 0;
66 for (D64 ticks = 0; ticks < duration; ticks += tickStep)
67 {
68 dt += timeStep;
69 calculate(i, dt);
71 for (I32 a = 0; a < _skeletonDepthCache; ++a)
72 {
73 Bone* bone = _bones[a];
74 transforms[a] = bone->offsetMatrix() * bone->globalTransform();
75 bone->boneID(a);
76 }
77 crtAnimation->transforms().emplace_back().matrices(transforms);
78 }
79
82 }
83
84 Console::d_printfn(LOCALE_STR("LOAD_ANIMATIONS_END"), _skeletonDepthCache);
85
86 return _skeletonDepthCache > 0;
87}
88
90{
91 // pay the cost upfront
92 for (auto& crtAnimation : _animations)
93 {
94 crtAnimation->initBuffers(gfxDevice);
95 }
96}
97
99bool SceneAnimator::init( PlatformContext& context, Bone* skeleton, const vector<Bone*>& bones) {
100 release(false);
101
102 DIVIDE_ASSERT(_bones.size() < U8_MAX, "SceneAnimator::init error: Too many bones for current node!");
103
104 _skeleton = skeleton;
105 _bones = bones;
106 _skeletonDepthCache = to_I16(bones.size());
107
108 return init(context);
109}
110
111// ------------------------------------------------------------------------------------------------
112// Calculates the node transformations for the scene.
113void SceneAnimator::calculate(const U32 animationIndex, const D64 pTime)
114{
115 assert(_skeleton != nullptr);
116
117 if (animationIndex >= _animations.size())
118 {
119 return; // invalid animation
120 }
121
122 _animations[animationIndex]->evaluate(pTime, _skeleton);
124}
125
129{
130 CalculateBoneToWorldTransform(pNode); // update global transform as well
132 for (Bone* bone : pNode->_children)
133 {
134 UpdateTransforms(bone);
135 }
136}
137
138Bone* SceneAnimator::boneByName(const string& name) const
139{
140 assert(_skeleton != nullptr);
141
142 return _skeleton->find(name);
143}
144
145I32 SceneAnimator::boneIndex(const string& bName) const
146{
147 const Bone* bone = boneByName(bName);
148 return bone != nullptr ? bone->boneID() : -1;
149}
150
152const vector<Line>& SceneAnimator::skeletonLines(const U32 animationIndex, const D64 dt)
153{
154 assert( animationIndex < _animations.size() );
155
156 const I32 frameIndex = std::max(_animations[animationIndex]->frameIndexAt(dt)._curr - 1, 0);
157
158 I32& vecIndex = _skeletonLines[animationIndex][frameIndex];
159
160 if (vecIndex == -1)
161 {
162 vecIndex = to_I32(_skeletonLinesContainer.size());
163 _skeletonLinesContainer.emplace_back();
164 }
165
166 // create all the needed points
167 vector<Line>& lines = _skeletonLinesContainer[vecIndex];
168 if (lines.empty())
169 {
170 lines.reserve(boneCount());
171 // Construct skeleton
172 calculate(animationIndex, dt);
173 // Start with identity transform
175 }
176
177 return lines;
178}
179
182 const mat4<F32>& parent,
183 vector<Line>& lines) {
184 static Line s_line
185 {
187 ._positionEnd = VECTOR3_UNIT,
188 ._colourStart = DefaultColours::RED_U8,
189 ._colourEnd = DefaultColours::RED_U8,
190 ._widthStart = 2.0f,
191 ._widthEnd = 2.0f
192 };
193
194 const mat4<F32>& me = piNode->globalTransform();
195
196 if (piNode->_parent)
197 {
198 Line& line = lines.emplace_back(s_line);
199 line._positionStart = parent.getRow(3).xyz;
200 line._positionEnd = me.getRow(3).xyz;
201 }
202
203 // render all child nodes
204 for (const auto& bone : piNode->_children) {
205 CreateSkeleton(bone, me, lines);
206 }
207
208 return 1;
209}
210
211} //namespace Divide
#define LOCALE_STR(X)
Definition: Localization.h:91
#define DIVIDE_ASSERT(...)
vector< BoneTransform > & transforms() noexcept
U32 frameCount() const noexcept
Bone * _parent
Definition: Bone.h:51
Bone * find(const string &name)
Definition: Bone.h:77
vector< Bone * > _children
Definition: Bone.h:52
Rough around the edges Adapter pattern abstracting the actual rendering API and access to the GPU.
Definition: GFXDevice.h:215
static void UpdateTransforms(Bone *pNode)
U8 boneCount() const noexcept
vector< std::unique_ptr< AnimEvaluator > > _animations
A vector that holds each animation.
static I32 CreateSkeleton(Bone *piNode, const mat4< F32 > &parent, vector< Line > &lines)
Create animation skeleton.
const BoneTransform & transforms(const U32 animationIndex, const U32 index) const
bool init(PlatformContext &context, Bone *skeleton, const vector< Bone * > &bones)
This will build the skeleton based on the scene passed to it and CLEAR EVERYTHING.
U32 _maximumAnimationFrames
Frame count of the longest registered animation.
void calculate(U32 animationIndex, D64 pTime)
void release(bool releaseAnimations)
Frees all memory and initializes everything to a default state.
vector< vector< Line > > _skeletonLinesContainer
LineCollection _skeletonLines
Bone * boneByName(const string &name) const
const vector< Line > & skeletonLines(U32 animationIndex, D64 dt)
Renders the current skeleton pose at time index dt.
vector< Bone * > _bones
hashMap< U64, U32 > _animationNameToID
find animations quickly
I32 boneIndex(const string &bName) const
void buildBuffers(GFXDevice &gfxDevice)
Bone * _skeleton
Root node of the internal scene structure.
const vec4< T > & getRow(I32 index) const noexcept
Handle console commands that start with a forward slash.
Definition: AIProcessor.cpp:7
constexpr U32 to_U32(const T value)
int32_t I32
void CalculateBoneToWorldTransform(Bone *pInternalNode) noexcept
Calculates the global transformation matrix for the given internal node.
eastl::vector< Type > vector
Definition: Vector.h:42
static const vec3< F32 > VECTOR3_UNIT
Definition: MathVectors.h:1437
Project & parent
Definition: DefaultScene.h:41
constexpr U8 U8_MAX
constexpr I16 to_I16(const T value)
double D64
static constexpr F32 ANIMATION_TICKS_PER_SECOND
constexpr I32 to_I32(const T value)
static const mat4< F32 > MAT4_IDENTITY
Definition: MathMatrices.h:740
static const vec3< F32 > VECTOR3_ZERO
Definition: MathVectors.h:1434
uint32_t U32
vector< mat4< F32 > > Container
static NO_INLINE void d_printfn(const char *format, T &&... args)
vec3< F32 > _positionStart
Definition: Line.h:42
vec3< F32 > _positionEnd
Definition: Line.h:43