summaryrefslogtreecommitdiffstats
path: root/src/animation/backend/evaluateblendclipanimatorjob.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/animation/backend/evaluateblendclipanimatorjob.cpp')
-rw-r--r--src/animation/backend/evaluateblendclipanimatorjob.cpp142
1 files changed, 53 insertions, 89 deletions
diff --git a/src/animation/backend/evaluateblendclipanimatorjob.cpp b/src/animation/backend/evaluateblendclipanimatorjob.cpp
index e15a419b1..76d24a4d3 100644
--- a/src/animation/backend/evaluateblendclipanimatorjob.cpp
+++ b/src/animation/backend/evaluateblendclipanimatorjob.cpp
@@ -39,7 +39,10 @@
#include <Qt3DAnimation/private/managers_p.h>
#include <Qt3DAnimation/private/animationlogging_p.h>
#include <Qt3DAnimation/private/animationutils_p.h>
-#include <Qt3DAnimation/private/lerpblend_p.h>
+#include <Qt3DAnimation/private/clipblendvalue_p.h>
+#include <Qt3DAnimation/private/lerpclipblend_p.h>
+#include <Qt3DAnimation/private/clipblendnodevisitor_p.h>
+#include <Qt3DAnimation/private/job_common_p.h>
QT_BEGIN_NAMESPACE
@@ -49,110 +52,71 @@ namespace Animation {
EvaluateBlendClipAnimatorJob::EvaluateBlendClipAnimatorJob()
: Qt3DCore::QAspectJob()
{
- // TO DO: Add Profiler ID
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::EvaluateBlendClipAnimator, 0);
}
void EvaluateBlendClipAnimatorJob::run()
{
- const qint64 globalTime = m_handler->simulationTime();
- //qDebug() << Q_FUNC_INFO << "t_global =" << globalTime;
-
+ // Find the set of clips that need to be evaluated by querying each node
+ // in the blend tree.
+ // TODO: We should be able to cache this for each blend animator and only
+ // update when a node indicates its dependencies have changed as a result
+ // of blend factors changing
BlendedClipAnimator *blendedClipAnimator = m_handler->blendedClipAnimatorManager()->data(m_blendClipAnimatorHandle);
- Q_ASSERT(blendedClipAnimator);
-
- // TO DO: Right now we are doing LERP but refactor to handle other types
- ClipBlendNode *blendNode = m_handler->clipBlendNodeManager()->lookupNode(blendedClipAnimator->blendTreeRootId());
- Q_ASSERT(blendNode->blendType() == ClipBlendNode::LerpBlendType);
- LerpBlend *lerpBlendNode = static_cast<LerpBlend *>(blendNode);
-
- const Qt3DCore::QNodeIdVector clipIds = lerpBlendNode->clipIds();
+ Qt3DCore::QNodeId blendTreeRootId = blendedClipAnimator->blendTreeRootId();
+ const QVector<Qt3DCore::QNodeId> valueNodeIdsToEvaluate = gatherValueNodesToEvaluate(m_handler, blendTreeRootId);
- bool globalFinalFrame = false;
+ // Calculate the resulting duration of the blend tree based upon its current state
+ ClipBlendNodeManager *blendNodeManager = m_handler->clipBlendNodeManager();
+ ClipBlendNode *blendTreeRootNode = blendNodeManager->lookupNode(blendTreeRootId);
+ Q_ASSERT(blendTreeRootNode);
+ const double duration = blendTreeRootNode->duration();
- // Evaluate the fcurves for both clip
- AnimationClip *clip1 = m_handler->animationClipManager()->lookupResource(clipIds.first());
- AnimationClip *clip2 = m_handler->animationClipManager()->lookupResource(clipIds.last());
- Q_ASSERT(clip1 && clip2);
- bool finalFrame1 = false;
- bool finalFrame2 = false;
+ // Calculate the phase given the blend tree duration and global time
+ const qint64 globalTime = m_handler->simulationTime();
+ const AnimatorEvaluationData animatorData = evaluationDataForAnimator(blendedClipAnimator, globalTime);
int currentLoop = 0;
- const QVector<float> channelResultsClip1 = AnimationUtils::evaluateAtGlobalTime(clip1,
- globalTime,
- blendedClipAnimator->startTime(),
- blendedClipAnimator->loops(),
- currentLoop,
- finalFrame1);
- const QVector<float> channelResultsClip2 = AnimationUtils::evaluateAtGlobalTime(clip2,
- globalTime,
- blendedClipAnimator->startTime(),
- blendedClipAnimator->loops(),
- currentLoop,
- finalFrame2);
- globalFinalFrame = (finalFrame1 && finalFrame2);
-
- blendedClipAnimator->setCurrentLoop(currentLoop);
-
- // Perform blending between the two clips
- const float blendFactor = lerpBlendNode->blendFactor();
-
- QVector<AnimationUtils::MappingData> blendedMappingData;
- QVector<float> blendedValues;
-
- // Build a combined vector of blended value
- const QVector<AnimationUtils::BlendingMappingData> blendingMappingData = blendedClipAnimator->mappingData();
- for (const AnimationUtils::BlendingMappingData &mapping : blendingMappingData) {
-
- AnimationUtils::MappingData finalMapping;
- finalMapping.type = mapping.type;
- finalMapping.targetId = mapping.targetId;
- finalMapping.propertyName = mapping.propertyName;
-
- switch (mapping.blendAction) {
- case AnimationUtils::BlendingMappingData::ClipBlending: {
- Q_ASSERT(mapping.channelIndicesClip1.size() == mapping.channelIndicesClip2.size());
- for (int i = 0, m = mapping.channelIndicesClip1.size(); i < m; ++i) {
- const float value1 = channelResultsClip1.at(mapping.channelIndicesClip1[i]);
- const float value2 = channelResultsClip2.at(mapping.channelIndicesClip2[i]);
- const float blendedValue = ((1.0f - blendFactor) * value1) + (blendFactor * value2);
- finalMapping.channelIndices.push_back(blendedValues.size());
- blendedValues.push_back(blendedValue);
- }
- break;
- }
- case AnimationUtils::BlendingMappingData::NoBlending: {
- const bool useClip1 = !mapping.channelIndicesClip1.empty();
- const QVector<int> channelIndices = useClip1 ? mapping.channelIndicesClip1 : mapping.channelIndicesClip2;
- const QVector<float> values = useClip1 ? channelResultsClip1 : channelResultsClip2;
- for (int i = 0, m = channelIndices.size(); i < m; ++i) {
- const float value = values.at(channelIndices[i]);
- finalMapping.channelIndices.push_back(blendedValues.size());
- blendedValues.push_back(value);
- }
- break;
- }
- default:
- Q_UNREACHABLE();
- break;
- }
-
- blendedMappingData.push_back(finalMapping);
+ const double phase = phaseFromGlobalTime(animatorData.globalTime,
+ animatorData.startTime,
+ animatorData.playbackRate,
+ duration,
+ animatorData.loopCount,
+ currentLoop);
+
+ // Iterate over the value nodes of the blend tree, evaluate the
+ // contained animation clips at the current phase and store the results
+ // in the animator indexed by node.
+ AnimationClipLoaderManager *clipLoaderManager = m_handler->animationClipLoaderManager();
+ for (const auto valueNodeId : valueNodeIdsToEvaluate) {
+ ClipBlendValue *valueNode = static_cast<ClipBlendValue *>(blendNodeManager->lookupNode(valueNodeId));
+ Q_ASSERT(valueNode);
+ AnimationClip *clip = clipLoaderManager->lookupResource(valueNode->clipId());
+ Q_ASSERT(clip);
+
+ ClipResults rawClipResults = evaluateClipAtPhase(clip, phase);
+
+ // Reformat the clip results into the layout used by this animator/blend tree
+ ComponentIndices format = valueNode->formatIndices(blendedClipAnimator->peerId());
+ ClipResults formattedClipResults = formatClipResults(rawClipResults, format);
+ valueNode->setClipResults(blendedClipAnimator->peerId(), formattedClipResults);
}
- if (globalFinalFrame)
- blendedClipAnimator->setRunning(false);
+ // Evaluate the blend tree
+ ClipResults blendedResults = evaluateBlendTree(m_handler, blendedClipAnimator, blendTreeRootId);
- // Prepare property changes (if finalFrame it also prepares the change for the running property for the frontend)
- const QVector<Qt3DCore::QSceneChangePtr> changes = AnimationUtils::preparePropertyChanges(blendedClipAnimator->peerId(),
- blendedMappingData,
- blendedValues,
- globalFinalFrame);
+ const double localTime = phase * duration;
+ const bool finalFrame = isFinalFrame(localTime, duration, currentLoop, animatorData.loopCount);
+ // Prepare the property change events
+ const QVector<MappingData> mappingData = blendedClipAnimator->mappingData();
+ const QVector<Qt3DCore::QSceneChangePtr> changes = preparePropertyChanges(blendedClipAnimator->peerId(),
+ mappingData,
+ blendedResults,
+ finalFrame);
// Send the property changes
blendedClipAnimator->sendPropertyChanges(changes);
-
}
-
} // Animation
} // Qt3DAnimation