53 vector<FlattenedNode> nodeListIgnored;
64 nodeLists.push_back(vector<FlattenedNode>());
72 for (
auto& skinningJoint:
skinningNodes[i]->getSkinning()->getJoints()) {
78 .joint = &skinningJoint,
79 .nodeTransformationsMatrix = transformationsMatrixIt->second,
80 .skinningNodeTransformationsMatrix = skinningNodeMatrixIt->second
97 for (
auto it: baseAnimationTransformationsMatrices) {
102 for (
auto it: skinningNodeMatricies) {
107 delete overriddenTransformationsMatrixIt.second;
116 if (_animationActiveSetup !=
nullptr) {
118 baseAnimation.
setup = _animationActiveSetup;
122 baseAnimation.
time = 0.0f;
123 baseAnimation.
speed = speed;
133 nodeLists.push_back(vector<FlattenedNode>());
136 nodeLists.push_back(vector<FlattenedNode>());
145 baseAnimationLast.endAtTime = baseAnimationLast.currentAtTime;
148 Console::println(
"Object3DAnimation::setAnimation(): " +
model->
getId() +
": missing animation: " +
id);
163 if (animationSetup ==
nullptr)
return;
164 if (animationSetup->getOverlayFromNodeId().size() == 0)
return;
167 animationState->setup = animationSetup;
169 animationState->currentAtTime = 0LL;
170 animationState->time = 0.0f;
171 animationState->speed = 1.0f;
172 animationState->finished =
false;
184 auto animationState = animationStateIt->second;
187 if (overlayAnimationsByJointIdIt ==
overlayAnimationsByJointId.end() || overlayAnimationsByJointIdIt->second->setup != animationState->setup) {
188 delete animationState;
192 delete animationState;
200 vector<string> overlayAnimationsToRemove;
202 const string&
id = it.first;
205 if (animationState->
finished ==
true) {
206 overlayAnimationsToRemove.push_back(
id);
211 for (
auto animationState: overlayAnimationsToRemove) {
219 vector<string> overlayAnimationsToRemove;
221 overlayAnimationsToRemove.push_back(it.first);
223 for (
auto animationState: overlayAnimationsToRemove) {
248 animationState = animationStateIt->second;
250 return animationState ==
nullptr ? 1.0f : animationState->
time;
257 return *overriddenTransformationsMatrixIt->second;
261 return *transformationMatrixIt->second;
263 Console::println(
"Object3DAnimation::getTransformationsMatrix(): " +
id +
": node not found");
272 *overriddenTransformationsMatrixIt->second = matrix;
284 delete overriddenTransformationsMatrixIt->second;
294 for (
auto it: nodes) {
296 auto nodeAnimationState = animationState;
298 auto node = it.second;
301 matrices[node->getId()] = matrix;
303 Matrix4x4* overriddenTransformationsMatrix =
nullptr;
309 nodeAnimationState = overlayAnimationIt->second;
312 .nodeId = node->getId(),
313 .nodeTransformationsMatrix = &node->getTransformationsMatrix(),
314 .nodeOverriddenTransformationsMatrix = overriddenTransformationsMatrix,
315 .nodeAnimation = node->getAnimation(),
316 .nodeAnimationState = animationState,
317 .parentTransformationsMatrix = parentTransformationsMatrix,
318 .transformationsMatrix = matrix
321 auto& subNodes = node->getSubNodes();
322 if (subNodes.size() > 0) {
330 for (
auto it: nodes) {
332 auto nodeAnimationState = animationState;
334 auto node = it.second;
336 Matrix4x4* overriddenTransformationsMatrix =
nullptr;
342 nodeAnimationState = overlayAnimationIt->second;
345 nodeList[nodeIdx].nodeOverriddenTransformationsMatrix = overriddenTransformationsMatrix;
346 nodeList[nodeIdx].nodeAnimationState = nodeAnimationState;
349 auto& subNodes = node->getSubNodes();
350 if (subNodes.size() > 0) {
360 for (
auto& flattenedNode: nodeList) {
361 auto nodeAnimationState = flattenedNode.nodeAnimationState !=
nullptr?flattenedNode.nodeAnimationState:animationState;
363 auto animation = flattenedNode.nodeAnimation;
365 if (animation !=
nullptr && nodeAnimationState !=
nullptr && nodeAnimationState->setup !=
nullptr) {
366 auto& animationMatrices = animation->getTransformationsMatrices();
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;
373 if (nodeAnimationState->setup->isLoop() ==
false && frameAtCurrent >= frames) {
374 frameAtLast = frames - 1;
375 frameAtCurrent = frames - 1;
376 nodeAnimationState->finished =
true;
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));
382 auto t = frameAtCurrent -
static_cast<float>(Math::floor(frameAtLast));
384 if (matrixAtLast == matrixAtCurrent) {
386 if (matrixAtCurrent >= frames) {
387 if (nodeAnimationState->setup->isLoop() ==
true) {
388 matrixAtCurrent = matrixAtCurrent % frames;
390 matrixAtCurrent = frames - 1;
394 transformationsMatrix = Matrix4x4::interpolateLinear(
395 animationMatrices[matrixAtLast + nodeAnimationState->setup->getStartFrame()],
396 animationMatrices[matrixAtCurrent + nodeAnimationState->setup->getStartFrame()],
400 transformationsMatrix.
set(animationMatrices[matrixAtCurrent + nodeAnimationState->setup->getStartFrame()]);
403 if (flattenedNode.nodeOverriddenTransformationsMatrix !=
nullptr) {
404 transformationsMatrix.
set(*flattenedNode.nodeOverriddenTransformationsMatrix);
407 transformationsMatrix.
set(*flattenedNode.nodeTransformationsMatrix);
411 transformationsMatrix.
multiply(flattenedNode.parentTransformationsMatrix !=
nullptr?*flattenedNode.parentTransformationsMatrix:parentTransformationsMatrix);
413 flattenedNode.transformationsMatrix->
set(transformationsMatrix);
419 for (
auto& skinningNodeNodeSkinningJoint: skinningNodeNodeSkinningJoints) {
420 skinningNodeNodeSkinningJoint.skinningNodeTransformationsMatrix->set(skinningNodeNodeSkinningJoint.joint->getBindMatrix()).multiply(*skinningNodeNodeSkinningJoint.nodeTransformationsMatrix);
427 if (baseAnimation.
setup !=
nullptr) {
431 baseAnimation.
currentAtTime+= currentFrameAtTime - lastFrameAtTime;
437 overlayAnimationState->
currentAtTime+= currentFrameAtTime - lastFrameAtTime;
445 parentTransformationsMatrix.
multiply(instanceTransformationsMatrix);
457 parentTransformationsMatrix.
multiply(instanceTransformationsMatrix);
467 if (baseAnimationIdxLast != -1 &&
471 baseAnimationIdxLast = -1;
479 for (
auto i = 0; i <
nodeLists[0].size(); i++) {
480 if (baseAnimationIdxLast != -1 &&
483 *
nodeLists[0][i].transformationsMatrix = Matrix4x4::interpolateLinear(
484 *
nodeLists[1 + baseAnimationIdxLast][i].transformationsMatrix,
487 blendingAnimationDuration,
491 if (blendingAnimationDuration >= 1.0f) {
493 animationStateLast.setup =
nullptr;
494 animationStateLast.endAtTime = -1LL;
495 animationStateLast.currentAtTime = -1LL;
496 animationStateLast.lastAtTime = -1LL;
497 animationStateLast.finished =
true;
498 animationStateLast.time = -1LL;
516 for (
auto it: nodes) {
517 Node* node = it.second;
523 if (subNodes.size() > 0) {
533 for (
auto it: nodes) {
534 Node* node = it.second;
541 if (subNodes.size() > 0) {
AnimationProcessingTarget
static float getAnimationBlendingTime()
static constexpr int64_t UNDEFINED
Representation of a 3d model.
const Matrix4x4 & getImportTransformationsMatrix()
AnimationSetup * getAnimationSetup(const string &id)
map< string, Node * > & getSubNodes()
Returns object's sub nodes.
map< string, Node * > & getSubNodes()
Skinning definition for nodes.
Object3D animation class.
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.
map< string, AnimationState * > overlayAnimationsById
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.
vector< AnimationState > baseAnimations
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.
const string getAnimation()
void setNodeTransformationsMatrix(const string &id, const Matrix4x4 &matrix)
Set transformation matrix for given node.
virtual ~Object3DAnimation()
Destructor.
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.
vector< Node * > skinningNodes
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.
map< string, Matrix4x4 * > overriddenTransformationsMatrices
vector< vector< FlattenedNode > > nodeLists
void updateNodeLists()
Update node lists.
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
Matrix4x4 & identity()
Setup identity matrix.
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.
Vector3 multiply(const Vector3 &v) const
Multiplies a vector3 with this matrix into destination vector.
Vector3 & set(float x, float y, float z)
Set up vector.