5 #include <unordered_map>
25 using std::unique_ptr;
26 using std::unordered_map;
55 vector<FlattenedNode> nodeListIgnored;
74 for (
auto& skinningJoint:
skinningNodes[i]->getSkinning()->getJoints()) {
81 transformMatrixIt->second,
82 skinningNodeMatrixIt->second
99 for (
const auto& [
id, matrix]: baseAnimationTransformMatrices) {
104 for (
const auto& [
id, matrix]: skinningNodeMatricesEntity) {
118 if (animationActiveSetup !=
nullptr) {
121 animationActiveSetup,
133 animationActiveSetup,
151 animationActiveSetup,
163 baseAnimationLast.endAtTime = baseAnimationLast.currentAtTime;
166 Console::println(
"ObjectAnimation::setAnimation(): " +
model->
getId() +
": missing animation: " +
id);
181 if (animationSetup ==
nullptr)
return;
182 if (animationSetup->getOverlayFromNodeId().size() == 0)
return;
185 animationState->setup = animationSetup;
187 animationState->currentAtTime = 0LL;
188 animationState->time = 0.0f;
189 animationState->speed = 1.0f;
190 animationState->finished =
false;
203 auto animationState = unique_ptr<AnimationState>(animationStateIt->second);
213 vector<string> overlayAnimationsToRemove;
215 if (animationState->finished ==
true) {
216 overlayAnimationsToRemove.push_back(animationId);
220 for (
const auto& animationState: overlayAnimationsToRemove) {
228 vector<string> overlayAnimationsToRemove;
230 overlayAnimationsToRemove.push_back(animationId);
232 for (
const auto& animationState: overlayAnimationsToRemove) {
257 animationState = animationStateIt->second;
259 return animationState ==
nullptr ? 1.0f : animationState->
time;
266 return *overriddenTransformMatrixIt->second;
270 return *transformMatrixIt->second;
272 Console::println(
"ObjectAnimation::getTransformMatrix(): " +
id +
": node not found");
281 *overriddenTransformMatrixIt->second = matrix;
293 delete overriddenTransformMatrixIt->second;
303 for (
const auto& [nodeId, node]: nodes) {
305 auto nodeAnimationState = animationState;
309 matrices[node->getId()] = matrix;
311 Matrix4x4* overriddenTransformMatrix =
nullptr;
313 if (overriddenTransformMatrixIt !=
overriddenTransformMatrices.end()) overriddenTransformMatrix = overriddenTransformMatrixIt->second;
317 nodeAnimationState = overlayAnimationIt->second;
319 nodeList.emplace_back(
321 &node->getTransformMatrix(),
322 overriddenTransformMatrix,
323 node->getAnimation(),
325 parentTransformMatrix,
329 const auto& subNodes = node->getSubNodes();
330 if (subNodes.size() > 0) {
338 for (
const auto& [nodeId, node]: nodes) {
340 auto nodeAnimationState = animationState;
343 Matrix4x4* overriddenTransformMatrix =
nullptr;
345 if (overriddenTransformMatrixIt !=
overriddenTransformMatrices.end()) overriddenTransformMatrix = overriddenTransformMatrixIt->second;
349 nodeAnimationState = overlayAnimationIt->second;
352 nodeList[nodeIdx].nodeOverriddenTransformMatrix = overriddenTransformMatrix;
353 nodeList[nodeIdx].nodeAnimationState = nodeAnimationState;
356 const auto& subNodes = node->getSubNodes();
357 if (subNodes.size() > 0) {
367 for (
auto& flattenedNode: nodeList) {
368 auto nodeAnimationState = flattenedNode.nodeAnimationState !=
nullptr?flattenedNode.nodeAnimationState:animationState;
370 auto animation = flattenedNode.nodeAnimation;
372 if (animation !=
nullptr && nodeAnimationState !=
nullptr && nodeAnimationState->setup !=
nullptr) {
373 const auto& animationMatrices = animation->getTransformMatrices();
377 auto frameAtLast = (nodeAnimationState->lastAtTime / 1000.0f) * fps * nodeAnimationState->setup->getSpeed() * nodeAnimationState->speed;
378 auto frameAtCurrent = (nodeAnimationState->currentAtTime / 1000.0f) * fps * nodeAnimationState->setup->getSpeed() * nodeAnimationState->speed;
380 if (nodeAnimationState->setup->isLoop() ==
false && frameAtCurrent >= frames) {
381 frameAtLast = frames - 1;
382 frameAtCurrent = frames - 1;
383 nodeAnimationState->finished =
true;
385 auto matrixAtLast =
static_cast<int32_t
>(frameAtLast) % frames;
386 auto matrixAtCurrent =
static_cast<int32_t
>(frameAtCurrent) % frames;
387 nodeAnimationState->time = frames <= 1?0.0f:
static_cast<float>(matrixAtCurrent) /
static_cast<float>((frames - 1));
389 auto t = frameAtCurrent -
static_cast<float>(Math::floor(frameAtLast));
391 if (matrixAtLast == matrixAtCurrent) {
393 if (matrixAtCurrent >= frames) {
394 if (nodeAnimationState->setup->isLoop() ==
true) {
395 matrixAtCurrent = matrixAtCurrent % frames;
397 matrixAtCurrent = frames - 1;
401 transformMatrix = Matrix4x4::interpolateLinear(
402 animationMatrices[matrixAtLast + nodeAnimationState->setup->getStartFrame()],
403 animationMatrices[matrixAtCurrent + nodeAnimationState->setup->getStartFrame()],
407 transformMatrix.
set(animationMatrices[matrixAtCurrent + nodeAnimationState->setup->getStartFrame()]);
410 if (flattenedNode.nodeOverriddenTransformMatrix !=
nullptr) {
411 transformMatrix.
set(*flattenedNode.nodeOverriddenTransformMatrix);
414 transformMatrix.
set(*flattenedNode.nodeTransformMatrix);
418 transformMatrix.
multiply(flattenedNode.parentTransformMatrix !=
nullptr?*flattenedNode.parentTransformMatrix:parentTransformMatrix);
420 flattenedNode.transformMatrix->
set(transformMatrix);
426 for (
auto& skinningNodeNodeSkinningJoint: skinningNodeNodeSkinningJoints) {
427 skinningNodeNodeSkinningJoint.skinningNodeTransformMatrix->set(skinningNodeNodeSkinningJoint.joint->getBindMatrix()).multiply(*skinningNodeNodeSkinningJoint.nodeTransformMatrix);
434 if (baseAnimation.
setup !=
nullptr) {
438 baseAnimation.
currentAtTime+= currentFrameAtTime - lastFrameAtTime;
442 if (lastFrameAtTime !=
Timing::UNDEFINED && overlayAnimationState->lastAtTime != -1LL) {
443 overlayAnimationState->currentAtTime+= currentFrameAtTime - lastFrameAtTime;
445 overlayAnimationState->lastAtTime = overlayAnimationState->currentAtTime;
451 parentTransformMatrix.
multiply(instanceTransformMatrix);
463 parentTransformMatrix.
multiply(instanceTransformMatrix);
473 if (baseAnimationIdxLast != -1 &&
477 baseAnimationIdxLast = -1;
485 for (
auto i = 0; i <
nodeLists[0].size(); i++) {
486 if (baseAnimationIdxLast != -1 &&
489 *
nodeLists[0][i].transformMatrix = Matrix4x4::interpolateLinear(
490 *
nodeLists[1 + baseAnimationIdxLast][i].transformMatrix,
493 blendingAnimationDuration,
497 if (blendingAnimationDuration >= 1.0f) {
499 animationStateLast.setup =
nullptr;
500 animationStateLast.endAtTime = -1LL;
501 animationStateLast.currentAtTime = -1LL;
502 animationStateLast.lastAtTime = -1LL;
503 animationStateLast.finished =
true;
504 animationStateLast.time = -1LL;
522 for (
const auto& [nodeId, node]: nodes) {
524 if (node->getSkinning() !=
nullptr)
527 const auto& subNodes = node->getSubNodes();
528 if (subNodes.size() > 0) {
538 for (
const auto& [nodeId, node]: nodes) {
540 if (node->getSkinning() !=
nullptr) {
544 const auto& subNodes = node->getSubNodes();
545 if (subNodes.size() > 0) {
AnimationProcessingTarget
static float getAnimationBlendingTime()
static constexpr int64_t UNDEFINED
Representation of a 3D model.
unordered_map< string, Node * > & getSubNodes()
Returns object's sub nodes.
AnimationSetup * getAnimationSetup(const string &id)
const Matrix4x4 & getImportTransformMatrix()
Skinning definition for nodes.
void setAnimation(const string &id, float speed=1.0f)
Sets up a base animation to play.
vector< unordered_map< string, Matrix4x4 * > > transformMatrices
void computeNodesTransformMatrices(vector< FlattenedNode > &nodeList, const Matrix4x4 parentTransformMatrix, AnimationState *animationState)
Comutes all nodes transform matrices.
virtual ~ObjectAnimation()
Destructor.
const Matrix4x4 getNodeTransformMatrix(const string &id)
Returns transform matrix for given node.
void setNodeTransformMatrix(const string &id, const Matrix4x4 &matrix)
Set transform matrix for given node.
void computeAnimation(vector< FlattenedNode > &nodeList, const Matrix4x4 &instanceTransformMatrix, AnimationState &baseAnimation, int contextIdx, int64_t lastFrameAtTime, int64_t currentFrameAtTime)
Compute animation for given animation state into nodes transform matrices given by flattened node lis...
vector< AnimationState > baseAnimations
void addOverlayAnimation(const string &id)
Overlays a animation above the base animation.
unordered_map< string, AnimationState * > overlayAnimationsById
Engine::AnimationProcessingTarget animationProcessingTarget
float getOverlayAnimationTime(const string &id)
Returns current overlay animation time.
void createNodesTransformMatrices(unordered_map< string, Matrix4x4 * > &matrices, vector< FlattenedNode > &nodeList, const unordered_map< string, Node * > &nodes, Matrix4x4 *parentTransformMatrix=nullptr, AnimationState *animationState=nullptr)
Creates all nodes transform matrices.
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.
unordered_map< string, Matrix4x4 * > overriddenTransformMatrices
void updateSkinningJoints()
Update skinning transform matrices.
vector< vector< NodeSkinningJoint > > skinningNodesNodeSkinningJoints
const string getAnimation()
unordered_map< string, AnimationState * > overlayAnimationsByJointId
unordered_map< string, Matrix4x4 * > * getSkinningNodesTransformMatrices(Node *node)
Get skinning nodes transform matrices.
int32_t determineSkinnedNodeCount(const unordered_map< string, Node * > &nodes)
Determine skinned node count.
void setAnimationSpeed(float speed)
Set up animation speed.
vector< unordered_map< string, Matrix4x4 * > > skinningNodesMatrices
void removeOverlayAnimations()
Removes all overlay animations.
void updateNodeList(vector< FlattenedNode > &nodeList, int &nodeIdx, const unordered_map< string, Node * > &nodes, AnimationState *animationState=nullptr)
Update node list.
vector< Node * > skinningNodes
void unsetNodeTransformMatrix(const string &id)
Unset transform matrix for given node.
float getAnimationTime()
Returns current base animation time.
vector< vector< FlattenedNode > > nodeLists
void updateNodeLists()
Update node lists.
void removeFinishedOverlayAnimations()
Removes all finished overlay animations.
int32_t determineSkinnedNodes(const unordered_map< string, Node * > &nodes, vector< Node * > &skinningNodes, int32_t idx)
Determine skinned nodes.
Matrix4x4 class representing matrix4x4 mathematical structure and operations for 3d space.
Matrix4x4 & identity()
Creates identity matrix.
Vector3 multiply(const Vector3 &vector3) const
Multiplies this matrix with vector3.
Matrix4x4 & set(float r0c0, float r0c1, float r0c2, float r0c3, float r1c0, float r1c1, float r1c2, float r1c3, float r2c0, float r2c1, float r2c2, float r2c3, float r3c0, float r3c1, float r3c2, float r3c3)
Sets this matrix by its components.
Vector3 class representing vector3 mathematical structure and operations with x, y,...
Vector3 & set(float x, float y, float z)
Sets this vector3 by its components.