TDME2 1.9.121
Object3DAnimation.cpp
Go to the documentation of this file.
2
3#include <map>
4#include <string>
5#include <vector>
6
7#include <tdme/tdme.h>
15#include <tdme/engine/Engine.h>
16#include <tdme/engine/Timing.h>
17#include <tdme/math/Math.h>
18#include <tdme/math/Matrix4x4.h>
19#include <tdme/math/Vector3.h>
21
22using std::map;
23using std::string;
24using std::to_string;
25using std::vector;
26
40
41Object3DAnimation::Object3DAnimation(Model* model, Engine::AnimationProcessingTarget animationProcessingTarget)
42{
43 this->animationProcessingTarget = animationProcessingTarget;
44 this->model = model;
45 // skinning
46 hasSkinning = false;
47 if (model->hasSkinning() == true) {
48 hasSkinning = true;
52 for (auto i = 0; i < skinningNodes.size(); i++) {
53 vector<FlattenedNode> nodeListIgnored;
55 }
56 }
58 //
60 // animation
61 setAnimation(Model::ANIMATIONSETUP_DEFAULT);
62 // create transformations matrices
63 transformationsMatrices.push_back(map<string, Matrix4x4*>());
64 nodeLists.push_back(vector<FlattenedNode>());
66 // calculate transformations matrices
68 // skinning ...
69 if (hasSkinning == true) {
70 for (auto i = 0; i < skinningNodes.size(); i++) {
71 skinningNodesNodeSkinningJoints.push_back(vector<NodeSkinningJoint>());
72 for (auto& skinningJoint: skinningNodes[i]->getSkinning()->getJoints()) {
73 auto transformationsMatrixIt = transformationsMatrices[0].find(skinningJoint.getNodeId());
74 if (transformationsMatrixIt == transformationsMatrices[0].end()) continue;
75 auto skinningNodeMatrixIt = skinningNodesMatrices[i].find(skinningJoint.getNodeId());
76 if (skinningNodeMatrixIt == skinningNodesMatrices[i].end()) continue;
78 .joint = &skinningJoint,
79 .nodeTransformationsMatrix = transformationsMatrixIt->second,
80 .skinningNodeTransformationsMatrix = skinningNodeMatrixIt->second
81 });
82 }
83 }
85 }
86 // reset animation
87 if (baseAnimations.size() == 0) baseAnimations.push_back(AnimationState());
88 baseAnimations[baseAnimationIdx].endAtTime = -1LL;
90 baseAnimations[baseAnimationIdx].currentAtTime = 0LL;
92 baseAnimations[baseAnimationIdx].finished = false;
93}
94
96 for (auto baseAnimationTransformationsMatrices: transformationsMatrices) {
97 for (auto it: baseAnimationTransformationsMatrices) {
98 delete it.second;
99 }
100 }
101 for (auto skinningNodeMatricies: skinningNodesMatrices) {
102 for (auto it: skinningNodeMatricies) {
103 delete it.second;
104 }
105 }
106 for (auto overriddenTransformationsMatrixIt: overriddenTransformationsMatrices) {
107 delete overriddenTransformationsMatrixIt.second;
108 }
109}
110
111void Object3DAnimation::setAnimation(const string& id, float speed)
112{
113 auto _animationActiveSetup = model->getAnimationSetup(id);
114
115 // only switch animation if we have one
116 if (_animationActiveSetup != nullptr) {
117 AnimationState baseAnimation;
118 baseAnimation.setup = _animationActiveSetup;
119 baseAnimation.endAtTime = -1LL;
120 baseAnimation.lastAtTime = Timing::UNDEFINED;
121 baseAnimation.currentAtTime = 0LL;
122 baseAnimation.time = 0.0f;
123 baseAnimation.speed = speed;
124 baseAnimation.finished = false;
125 if (baseAnimations.size() == 0) {
126 baseAnimations.push_back(baseAnimation);
128 } else
129 if (baseAnimations.size() == 1) {
130 baseAnimations.push_back(baseAnimation);
132 transformationsMatrices.push_back(map<string, Matrix4x4*>());
133 nodeLists.push_back(vector<FlattenedNode>());
135 transformationsMatrices.push_back(map<string, Matrix4x4*>());
136 nodeLists.push_back(vector<FlattenedNode>());
138 } else {
140 baseAnimations[baseAnimationIdx] = baseAnimation;
141 }
142 if (baseAnimations.size() > 1) {
143 auto baseAnimationIdxLast = (baseAnimationIdx + 1) % 2;
144 auto& baseAnimationLast = baseAnimations[baseAnimationIdxLast];
145 baseAnimationLast.endAtTime = baseAnimationLast.currentAtTime;
146 }
147 } else {
148 Console::println("Object3DAnimation::setAnimation(): " + model->getId() + ": missing animation: " + id);
149 }
150}
151
153 if (baseAnimations.size() == 0) return;
154 baseAnimations[baseAnimationIdx].speed = speed;
155}
156
158{
159 // remove active overlay animation with given ids
161 // check overlay animation
162 auto animationSetup = model->getAnimationSetup(id);
163 if (animationSetup == nullptr) return;
164 if (animationSetup->getOverlayFromNodeId().size() == 0) return;
165 // create animation state
166 auto animationState = new AnimationState();
167 animationState->setup = animationSetup;
168 animationState->lastAtTime = Timing::UNDEFINED;
169 animationState->currentAtTime = 0LL;
170 animationState->time = 0.0f;
171 animationState->speed = 1.0f;
172 animationState->finished = false;
173 // register overlay animation
174 overlayAnimationsById[id] = animationState;
175 overlayAnimationsByJointId[animationSetup->getOverlayFromNodeId()] = animationState;
176 //
178}
179
181{
182 auto animationStateIt = overlayAnimationsById.find(id);
183 if (animationStateIt == overlayAnimationsById.end()) return;
184 auto animationState = animationStateIt->second;
185 overlayAnimationsById.erase(animationStateIt);
186 auto overlayAnimationsByJointIdIt = overlayAnimationsByJointId.find(animationState->setup->getOverlayFromNodeId());
187 if (overlayAnimationsByJointIdIt == overlayAnimationsByJointId.end() || overlayAnimationsByJointIdIt->second->setup != animationState->setup) {
188 delete animationState;
189 return;
190 }
191 overlayAnimationsByJointId.erase(overlayAnimationsByJointIdIt);
192 delete animationState;
193 //
195}
196
198{
199 // determine finished overlay animations
200 vector<string> overlayAnimationsToRemove;
201 for (auto it: overlayAnimationsById) {
202 const string& id = it.first;
203 AnimationState* animationState = it.second;
204 {
205 if (animationState->finished == true) {
206 overlayAnimationsToRemove.push_back(id);
207 }
208 }
209 }
210 // remove them
211 for (auto animationState: overlayAnimationsToRemove) {
212 removeOverlayAnimation(animationState);
213 }
214}
215
217{
218 // remove them
219 vector<string> overlayAnimationsToRemove;
220 for (auto it: overlayAnimationsById) {
221 overlayAnimationsToRemove.push_back(it.first);
222 }
223 for (auto animationState: overlayAnimationsToRemove) {
224 removeOverlayAnimation(animationState);
225 }
226}
227
229{
230 return baseAnimations[baseAnimationIdx].setup == nullptr ? "none" : baseAnimations[baseAnimationIdx].setup->getId();
231}
232
234{
235 return baseAnimations[baseAnimationIdx].time;
236}
237
239{
240 return overlayAnimationsById.find(id) != overlayAnimationsById.end();
241}
242
244{
245 AnimationState* animationState = nullptr;
246 auto animationStateIt = overlayAnimationsById.find(id);
247 if (animationStateIt != overlayAnimationsById.end()) {
248 animationState = animationStateIt->second;
249 }
250 return animationState == nullptr ? 1.0f : animationState->time;
251}
252
254{
255 auto overriddenTransformationsMatrixIt = overriddenTransformationsMatrices.find(id);
256 if (overriddenTransformationsMatrixIt != overriddenTransformationsMatrices.end()) {
257 return *overriddenTransformationsMatrixIt->second;
258 } else {
259 auto transformationMatrixIt = transformationsMatrices[0].find(id);
260 if (transformationMatrixIt != transformationsMatrices[0].end()) {
261 return *transformationMatrixIt->second;
262 }
263 Console::println("Object3DAnimation::getTransformationsMatrix(): " + id + ": node not found");
264 }
265 return Matrix4x4().identity();
266}
267
269{
270 auto overriddenTransformationsMatrixIt = overriddenTransformationsMatrices.find(id);
271 if (overriddenTransformationsMatrixIt != overriddenTransformationsMatrices.end()) {
272 *overriddenTransformationsMatrixIt->second = matrix;
273 } else {
275 }
276 //
278}
279
281{
282 auto overriddenTransformationsMatrixIt = overriddenTransformationsMatrices.find(id);
283 if (overriddenTransformationsMatrixIt != overriddenTransformationsMatrices.end()) {
284 delete overriddenTransformationsMatrixIt->second;
285 overriddenTransformationsMatrices.erase(overriddenTransformationsMatrixIt);
286 }
287 //
289}
290
291void Object3DAnimation::createTransformationsMatrices(map<string, Matrix4x4*>& matrices, vector<FlattenedNode>& nodeList, const map<string, Node*>& nodes, Matrix4x4* parentTransformationsMatrix, AnimationState* animationState)
292{
293 // iterate through nodes
294 for (auto it: nodes) {
295 //
296 auto nodeAnimationState = animationState;
297 // put and associate transformation matrices with node
298 auto node = it.second;
299 auto matrix = new Matrix4x4();
300 matrix->identity();
301 matrices[node->getId()] = matrix;
302 // overridden matrix
303 Matrix4x4* overriddenTransformationsMatrix = nullptr;
304 auto overriddenTransformationsMatrixIt = overriddenTransformationsMatrices.find(node->getId());
305 if (overriddenTransformationsMatrixIt != overriddenTransformationsMatrices.end()) overriddenTransformationsMatrix = overriddenTransformationsMatrixIt->second;
306 // overlay animation
307 auto overlayAnimationIt = overlayAnimationsByJointId.find(node->getId());
308 if (overlayAnimationIt != overlayAnimationsByJointId.end()) {
309 nodeAnimationState = overlayAnimationIt->second;
310 }
311 nodeList.push_back({
312 .nodeId = node->getId(),
313 .nodeTransformationsMatrix = &node->getTransformationsMatrix(),
314 .nodeOverriddenTransformationsMatrix = overriddenTransformationsMatrix,
315 .nodeAnimation = node->getAnimation(),
316 .nodeAnimationState = animationState,
317 .parentTransformationsMatrix = parentTransformationsMatrix,
318 .transformationsMatrix = matrix
319 });
320 // do sub nodes
321 auto& subNodes = node->getSubNodes();
322 if (subNodes.size() > 0) {
323 createTransformationsMatrices(matrices, nodeList, subNodes, matrix, nodeAnimationState);
324 }
325 }
326}
327
328void Object3DAnimation::updateNodeList(vector<FlattenedNode>& nodeList, int& nodeIdx, const map<string, Node*>& nodes, AnimationState* animationState) {
329 // iterate through nodes
330 for (auto it: nodes) {
331 //
332 auto nodeAnimationState = animationState;
333 // put and associate transformation matrices with node
334 auto node = it.second;
335 // overridden matrix
336 Matrix4x4* overriddenTransformationsMatrix = nullptr;
337 auto overriddenTransformationsMatrixIt = overriddenTransformationsMatrices.find(node->getId());
338 if (overriddenTransformationsMatrixIt != overriddenTransformationsMatrices.end()) overriddenTransformationsMatrix = overriddenTransformationsMatrixIt->second;
339 // overlay animation
340 auto overlayAnimationIt = overlayAnimationsByJointId.find(node->getId());
341 if (overlayAnimationIt != overlayAnimationsByJointId.end()) {
342 nodeAnimationState = overlayAnimationIt->second;
343 }
344 // update node list
345 nodeList[nodeIdx].nodeOverriddenTransformationsMatrix = overriddenTransformationsMatrix;
346 nodeList[nodeIdx].nodeAnimationState = nodeAnimationState;
347 nodeIdx++;
348 // do sub nodes
349 auto& subNodes = node->getSubNodes();
350 if (subNodes.size() > 0) {
351 updateNodeList(nodeList, nodeIdx, subNodes, nodeAnimationState);
352 }
353 }
354}
355
356void Object3DAnimation::computeTransformationsMatrices(vector<FlattenedNode>& nodeList, const Matrix4x4 parentTransformationsMatrix, AnimationState* animationState)
357{
358 // iterate through flattened nodes
359 Matrix4x4 transformationsMatrix;
360 for (auto& flattenedNode: nodeList) {
361 auto nodeAnimationState = flattenedNode.nodeAnimationState != nullptr?flattenedNode.nodeAnimationState:animationState;
362 // compute animation matrix if animation setups exist
363 auto animation = flattenedNode.nodeAnimation;
364 // TODO: check if its better to not compute animation matrix if finished
365 if (animation != nullptr && nodeAnimationState != nullptr && nodeAnimationState->setup != nullptr) {
366 auto& animationMatrices = animation->getTransformationsMatrices();
367 auto frames = nodeAnimationState->setup->getFrames();
368 auto fps = model->getFPS();
369 // determine current and last matrix
370 auto frameAtLast = (nodeAnimationState->lastAtTime / 1000.0f) * fps * nodeAnimationState->setup->getSpeed() * nodeAnimationState->speed;
371 auto frameAtCurrent = (nodeAnimationState->currentAtTime / 1000.0f) * fps * nodeAnimationState->setup->getSpeed() * nodeAnimationState->speed;
372 // check if looping is disabled
373 if (nodeAnimationState->setup->isLoop() == false && frameAtCurrent >= frames) {
374 frameAtLast = frames - 1;
375 frameAtCurrent = frames - 1;
376 nodeAnimationState->finished = true;
377 }
378 auto matrixAtLast = static_cast<int32_t>(frameAtLast) % frames;
379 auto matrixAtCurrent = static_cast<int32_t>(frameAtCurrent) % frames;
380 nodeAnimationState->time = frames <= 1?0.0f:static_cast<float>(matrixAtCurrent) / static_cast<float>((frames - 1));
381 // compute animation transformations matrix
382 auto t = frameAtCurrent - static_cast<float>(Math::floor(frameAtLast));
383 if (t < 1.0f) {
384 if (matrixAtLast == matrixAtCurrent) {
385 matrixAtCurrent+= 1;
386 if (matrixAtCurrent >= frames) {
387 if (nodeAnimationState->setup->isLoop() == true) {
388 matrixAtCurrent = matrixAtCurrent % frames;
389 } else {
390 matrixAtCurrent = frames - 1;
391 }
392 }
393 }
394 transformationsMatrix = Matrix4x4::interpolateLinear(
395 animationMatrices[matrixAtLast + nodeAnimationState->setup->getStartFrame()],
396 animationMatrices[matrixAtCurrent + nodeAnimationState->setup->getStartFrame()],
397 t
398 );
399 } else {
400 transformationsMatrix.set(animationMatrices[matrixAtCurrent + nodeAnimationState->setup->getStartFrame()]);
401 }
402 } else {
403 if (flattenedNode.nodeOverriddenTransformationsMatrix != nullptr) {
404 transformationsMatrix.set(*flattenedNode.nodeOverriddenTransformationsMatrix);
405 } else {
406 // no animation matrix, set up local transformation matrix up as node matrix
407 transformationsMatrix.set(*flattenedNode.nodeTransformationsMatrix);
408 }
409 }
410 // apply parent transformation matrix
411 transformationsMatrix.multiply(flattenedNode.parentTransformationsMatrix != nullptr?*flattenedNode.parentTransformationsMatrix:parentTransformationsMatrix);
412 // put and associate transformation matrices with node
413 flattenedNode.transformationsMatrix->set(transformationsMatrix);
414 }
415}
416
418 for (auto& skinningNodeNodeSkinningJoints: skinningNodesNodeSkinningJoints)
419 for (auto& skinningNodeNodeSkinningJoint: skinningNodeNodeSkinningJoints) {
420 skinningNodeNodeSkinningJoint.skinningNodeTransformationsMatrix->set(skinningNodeNodeSkinningJoint.joint->getBindMatrix()).multiply(*skinningNodeNodeSkinningJoint.nodeTransformationsMatrix);
421 }
422}
423
424void Object3DAnimation::computeTransformations(vector<FlattenedNode>& nodeList, const Matrix4x4& instanceTransformationsMatrix, AnimationState& baseAnimation, int contextIdx, int64_t lastFrameAtTime, int64_t currentFrameAtTime)
425{
426 // do transformations if we have a animation
427 if (baseAnimation.setup != nullptr) {
428 // animation timing
429 // do progress of base animation
430 if (lastFrameAtTime != Timing::UNDEFINED && baseAnimation.lastAtTime != -1LL) {
431 baseAnimation.currentAtTime+= currentFrameAtTime - lastFrameAtTime;
432 }
433 // do progress of overlay animations
434 for (auto it: overlayAnimationsById) {
435 AnimationState* overlayAnimationState = it.second;
436 if (lastFrameAtTime != Timing::UNDEFINED && overlayAnimationState->lastAtTime != -1LL) {
437 overlayAnimationState->currentAtTime+= currentFrameAtTime - lastFrameAtTime;
438 }
439 overlayAnimationState->lastAtTime = overlayAnimationState->currentAtTime;
440 }
441 // set up parent transformations matrix
442 Matrix4x4 parentTransformationsMatrix;
443 parentTransformationsMatrix.set(model->getImportTransformationsMatrix());
444 if (animationProcessingTarget == Engine::AnimationProcessingTarget::CPU_NORENDERING) {
445 parentTransformationsMatrix.multiply(instanceTransformationsMatrix);
446 }
447 // calculate transformations matrices
448 computeTransformationsMatrices(nodeList, parentTransformationsMatrix, &baseAnimation);
449 //
450 baseAnimation.lastAtTime = baseAnimation.currentAtTime;
451 } else
452 if (animationProcessingTarget == Engine::AnimationProcessingTarget::CPU_NORENDERING) {
453 // set up parent transformations matrix
454 Matrix4x4 parentTransformationsMatrix;
455 parentTransformationsMatrix.set(model->getImportTransformationsMatrix());
456 if (animationProcessingTarget == Engine::AnimationProcessingTarget::CPU_NORENDERING) {
457 parentTransformationsMatrix.multiply(instanceTransformationsMatrix);
458 }
459 // calculate transformations matrices
460 computeTransformationsMatrices(nodeList, parentTransformationsMatrix, &baseAnimation);
461 }
462}
463
464void Object3DAnimation::computeTransformations(int contextIdx, const Matrix4x4& instanceTransformationsMatrix, int64_t lastFrameAtTime, int64_t currentFrameAtTime) {
465 // compute last animation matrices if required
466 auto baseAnimationIdxLast = transformationsMatrices.size() > 1?(baseAnimationIdx + 1) % 2:-1;
467 if (baseAnimationIdxLast != -1 &&
468 baseAnimations[baseAnimationIdxLast].lastAtTime != -1LL) {
469 computeTransformations(nodeLists[1 + baseAnimationIdxLast], instanceTransformationsMatrix, baseAnimations[baseAnimationIdxLast], contextIdx, lastFrameAtTime, currentFrameAtTime);
470 } else {
471 baseAnimationIdxLast = -1;
472 }
473
474 // compute current animation matrices
475 computeTransformations(nodeLists[nodeLists.size() > 1?1 + baseAnimationIdx:baseAnimationIdx], instanceTransformationsMatrix, baseAnimations[baseAnimationIdx], contextIdx, lastFrameAtTime, currentFrameAtTime);
476
477 // blend if required
478 if (transformationsMatrices.size() > 1) {
479 for (auto i = 0; i < nodeLists[0].size(); i++) {
480 if (baseAnimationIdxLast != -1 &&
481 baseAnimations[baseAnimationIdxLast].endAtTime != -1LL) {
482 auto blendingAnimationDuration = static_cast<float>(baseAnimations[baseAnimationIdxLast].currentAtTime - baseAnimations[baseAnimationIdxLast].endAtTime) / Engine::getAnimationBlendingTime();
483 *nodeLists[0][i].transformationsMatrix = Matrix4x4::interpolateLinear(
484 *nodeLists[1 + baseAnimationIdxLast][i].transformationsMatrix,
485 *nodeLists[1 + baseAnimationIdx][i].transformationsMatrix,
486 Math::min(
487 blendingAnimationDuration,
488 1.0f
489 )
490 );
491 if (blendingAnimationDuration >= 1.0f) {
492 auto& animationStateLast = baseAnimations[baseAnimationIdxLast];
493 animationStateLast.setup = nullptr;
494 animationStateLast.endAtTime = -1LL;
495 animationStateLast.currentAtTime = -1LL;
496 animationStateLast.lastAtTime = -1LL;
497 animationStateLast.finished = true;
498 animationStateLast.time = -1LL;
499 }
500 } else {
501 nodeLists[0][i].transformationsMatrix->set(*nodeLists[1 + baseAnimationIdx][i].transformationsMatrix);
502 }
503 }
504 }
506}
507
508int32_t Object3DAnimation::determineSkinnedNodeCount(const map<string, Node*>& nodes)
509{
510 return determineSkinnedNodeCount(nodes, 0);
511}
512
513int32_t Object3DAnimation::determineSkinnedNodeCount(const map<string, Node*>& nodes, int32_t count)
514{
515 // iterate through nodes
516 for (auto it: nodes) {
517 Node* node = it.second;
518 //
519 if (node->getSkinning() != nullptr)
520 count++;
521 // calculate sub nodes
522 auto& subNodes = node->getSubNodes();
523 if (subNodes.size() > 0) {
524 count = determineSkinnedNodeCount(subNodes, count);
525 }
526 }
527 return count;
528}
529
530int32_t Object3DAnimation::determineSkinnedNodes(const map<string, Node*>& nodes, vector<Node*>& skinningNodes, int32_t idx)
531{
532 // iterate through nodes
533 for (auto it: nodes) {
534 Node* node = it.second;
535 // fetch skinning nodes
536 if (node->getSkinning() != nullptr) {
537 skinningNodes[idx++] = node;
538 }
539 // calculate sub nodes
540 auto& subNodes = node->getSubNodes();
541 if (subNodes.size() > 0) {
542 idx = determineSkinnedNodes(subNodes, skinningNodes, idx);
543 }
544 }
545 return idx;
546}
547
549{
550 if (hasSkinning == false) return nullptr;
551 for (auto i = 0; i < skinningNodes.size(); i++) {
552 if (skinningNodes[i] == node) {
553 return &skinningNodesMatrices[i];
554 }
555 }
556 return nullptr;
557}
Engine main class.
Definition: Engine.h:122
static float getAnimationBlendingTime()
Definition: Engine.h:609
Timing class.
Definition: Timing.h:17
static constexpr int64_t UNDEFINED
Definition: Timing.h:21
Joint / Bone.
Definition: Joint.h:19
Representation of a 3d model.
Definition: Model.h:32
const Matrix4x4 & getImportTransformationsMatrix()
Definition: Model.h:293
const string & getId()
Definition: Model.h:119
AnimationSetup * getAnimationSetup(const string &id)
Definition: Model.cpp:116
map< string, Node * > & getSubNodes()
Returns object's sub nodes.
Definition: Model.h:194
Model node.
Definition: Node.h:31
Skinning * getSkinning()
Definition: Node.h:238
map< string, Node * > & getSubNodes()
Definition: Node.h:289
Skinning definition for nodes.
Definition: Skinning.h:27
void setAnimation(const string &id, float speed=1.0f)
Sets up a base animation to play.
void createTransformationsMatrices(map< string, Matrix4x4 * > &matrices, vector< FlattenedNode > &nodeList, const map< string, Node * > &nodes, Matrix4x4 *parentTransformationsMatrix=nullptr, AnimationState *animationState=nullptr)
Creates all nodes transformation matrices.
void updateNodeList(vector< FlattenedNode > &nodeList, int &nodeIdx, const map< string, Node * > &nodes, AnimationState *animationState=nullptr)
Update node list.
void unsetNodeTransformationsMatrix(const string &id)
Unset transformation matrix for given node.
map< string, Matrix4x4 * > * getSkinningNodesMatrices(Node *node)
Get skinning nodes matrices.
void addOverlayAnimation(const string &id)
Overlays a animation above the base animation.
Engine::AnimationProcessingTarget animationProcessingTarget
float getOverlayAnimationTime(const string &id)
Returns current overlay animation time.
void removeOverlayAnimation(const string &id)
Removes a overlay animation.
bool hasOverlayAnimation(const string &id)
Returns if there is currently running a overlay animation with given id.
vector< vector< NodeSkinningJoint > > skinningNodesNodeSkinningJoints
map< string, AnimationState * > overlayAnimationsByJointId
void updateSkinningTransformationsMatrices()
Update skinning transformations matrices.
void setNodeTransformationsMatrix(const string &id, const Matrix4x4 &matrix)
Set transformation matrix for given node.
const Matrix4x4 getNodeTransformationsMatrix(const string &id)
Returns transformation matrix for given node.
void computeTransformationsMatrices(vector< FlattenedNode > &nodeList, const Matrix4x4 parentTransformationsMatrix, AnimationState *animationState)
Calculates all nodes transformation matrices.
void setAnimationSpeed(float speed)
Set up animation speed.
void removeOverlayAnimations()
Removes all overlay animations.
void removeOverlayAnimationsFinished()
Removes all finished overlay animations.
int32_t determineSkinnedNodeCount(const map< string, Node * > &nodes)
Determine skinned node count.
float getAnimationTime()
Returns current base animation time.
vector< map< string, Matrix4x4 * > > transformationsMatrices
int32_t determineSkinnedNodes(const map< string, Node * > &nodes, vector< Node * > &skinningNodes, int32_t idx)
Determine skinned nodes.
void computeTransformations(vector< FlattenedNode > &nodeList, const Matrix4x4 &instanceTransformationsMatrix, AnimationState &baseAnimation, int contextIdx, int64_t lastFrameAtTime, int64_t currentFrameAtTime)
Compute transformations for given animation state into given transformations matrices.
vector< map< string, Matrix4x4 * > > skinningNodesMatrices
Standard math functions.
Definition: Math.h:21
4x4 3D Matrix class
Definition: Matrix4x4.h:24
Matrix4x4 & identity()
Setup identity matrix.
Definition: Matrix4x4.h:326
Matrix4x4 & set(float r0c0, float r1c0, float r2c0, float r3c0, float r0c1, float r1c1, float r2c1, float r3c1, float r0c2, float r1c2, float r2c2, float r3c2, float r0c3, float r1c3, float r2c3, float r3c3)
Set up matrix by values.
Definition: Matrix4x4.h:95
Vector3 multiply(const Vector3 &v) const
Multiplies a vector3 with this matrix into destination vector.
Definition: Matrix4x4.h:351
3D vector 3 class
Definition: Vector3.h:22
Vector3 & set(float x, float y, float z)
Set up vector.
Definition: Vector3.h:73
Console class.
Definition: Console.h:26