diff options
author | Andy Nichols <andy.nichols@qt.io> | 2017-11-13 13:56:39 +0100 |
---|---|---|
committer | Andy Nichols <andy.nichols@qt.io> | 2017-11-13 13:56:39 +0100 |
commit | ab2d05d06b37fe875d360f92fe67e103ae17d80b (patch) | |
tree | 770a5c8a08f80baafe96cc349686ce6deadcd8b7 /src/animation/backend/animationutils.cpp | |
parent | 18ce3e68e6db896e9c01cf4df0dd7e9fa714b37c (diff) | |
parent | 764b715b5f682ddb1bdb52f67b5a35d85af7ccf1 (diff) |
Merge remote-tracking branch 'origin/5.10' into dev
Change-Id: I2d373d538df3a65ac2d41238e5c6a214a151be68
Diffstat (limited to 'src/animation/backend/animationutils.cpp')
-rw-r--r-- | src/animation/backend/animationutils.cpp | 103 |
1 files changed, 72 insertions, 31 deletions
diff --git a/src/animation/backend/animationutils.cpp b/src/animation/backend/animationutils.cpp index d05d96f38..fb5b19a5d 100644 --- a/src/animation/backend/animationutils.cpp +++ b/src/animation/backend/animationutils.cpp @@ -93,22 +93,26 @@ ClipEvaluationData evaluationDataForClip(AnimationClip *clip, { // global time values expected in seconds ClipEvaluationData result; - result.localTime = localTimeFromGlobalTime(animatorData.globalTime, animatorData.startTime, - animatorData.playbackRate, clip->duration(), - animatorData.loopCount, result.currentLoop); + result.currentLoop = animatorData.currentLoop; + result.localTime = localTimeFromElapsedTime(animatorData.currentTime, animatorData.elapsedTime, + animatorData.playbackRate, clip->duration(), + animatorData.loopCount, result.currentLoop); result.isFinalFrame = isFinalFrame(result.localTime, clip->duration(), result.currentLoop, animatorData.loopCount); return result; } -double localTimeFromGlobalTime(double t_global, - double t_start_global, - double playbackRate, - double duration, - int loopCount, - int ¤tLoop) +double localTimeFromElapsedTime(double t_current_local, + double t_elapsed_global, + double playbackRate, + double duration, + int loopCount, + int ¤tLoop) { - double t_local = playbackRate * (t_global - t_start_global); + // Calculate the new local time. + // playhead + rate * dt + // where playhead is completed loops * duration + current loop local time + double t_local = currentLoop * duration + t_current_local + playbackRate * t_elapsed_global; double loopNumber = 0; if (loopCount == 1) { t_local = qBound(0.0, t_local, duration); @@ -123,31 +127,44 @@ double localTimeFromGlobalTime(double t_global, t_local = std::fmod(t_local, duration); // Ensure we clamp to end of final loop - if (loopNumber == loopCount) { + if (int(loopNumber) == loopCount) { loopNumber = loopCount - 1; t_local = duration; } } - qCDebug(Jobs) << "t_global - t_start =" << t_global - t_start_global - << "current loop =" << loopNumber + qCDebug(Jobs) << "current loop =" << loopNumber << "t =" << t_local << "duration =" << duration; - currentLoop = loopNumber; + currentLoop = int(loopNumber); return t_local; } -double phaseFromGlobalTime(double t_global, double t_start_global, - double playbackRate, double duration, - int loopCount, int ¤tLoop) +double phaseFromElapsedTime(double t_current_local, + double t_elapsed_global, + double playbackRate, + double duration, + int loopCount, + int ¤tLoop) { - const double t_local = localTimeFromGlobalTime(t_global, t_start_global, playbackRate, - duration, loopCount, currentLoop); + const double t_local = localTimeFromElapsedTime(t_current_local, t_elapsed_global, playbackRate, + duration, loopCount, currentLoop); return t_local / duration; } +/*! + \internal + + Calculates the indices required to map from the component ordering within the + provided \a channel, into the standard channel orderings expected by Qt types. + + For example, given a channel representing a rotation with the components ordered + as X, Y, Z, Y, this function will return the indices [3, 0, 1, 2] which can then + later be used as part of the format vector in the formatClipResults() function to + remap the channels into the standard W, X, Y, Z order required by QQuaternion. +*/ ComponentIndices channelComponentsToIndices(const Channel &channel, int dataType, int offset) { #if defined Q_COMPILER_UNIFORM_INIT @@ -171,9 +188,9 @@ ComponentIndices channelComponentsToIndices(const Channel &channel, int dataType } ComponentIndices channelComponentsToIndicesHelper(const Channel &channel, - int dataType, - int offset, - const QVector<char> &suffixes) + int dataType, + int offset, + const QVector<char> &suffixes) { const int expectedComponentCount = componentsForType(dataType); const int actualComponentCount = channel.channelComponents.size(); @@ -183,21 +200,37 @@ ComponentIndices channelComponentsToIndicesHelper(const Channel &channel, } ComponentIndices indices(expectedComponentCount); + + // Generate the set of channel suffixes + QVector<char> channelSuffixes; + channelSuffixes.reserve(expectedComponentCount); for (int i = 0; i < expectedComponentCount; ++i) { const QString &componentName = channel.channelComponents[i].name; + // An unset component name indicates that the no mapping is necessary // and the index can be used as-is. if (componentName.isEmpty()) { indices[i] = i + offset; continue; } - char suffix = componentName.at(componentName.length() - 1).toLatin1(); - int index = suffixes.indexOf(suffix); + + char channelSuffix = componentName.at(componentName.length() - 1).toLatin1(); + channelSuffixes.push_back(channelSuffix); + } + + // We can short-circuit if the channels were all unnamed (in order) + if (channelSuffixes.isEmpty()) + return indices; + + // Find index of standard index in channel indexes + for (int i = 0; i < expectedComponentCount; ++i) { + int index = channelSuffixes.indexOf(suffixes[i]); if (index != -1) indices[i] = index + offset; else indices[i] = -1; } + return indices; } @@ -428,6 +461,11 @@ QVector<MappingData> buildPropertyMappings(const QVector<ChannelMapping*> &chann const ChannelNameAndType nameAndType = { mapping->channelName(), mapping->type() }; const int index = channelNamesAndTypes.indexOf(nameAndType); if (index != -1) { + // Do we have any animation data for this channel? If not, don't bother + // adding a mapping for it. + if (channelComponentIndices[index].isEmpty()) + continue; + // We got one! mappingData.channelIndices = channelComponentIndices[index]; mappingDataVec.push_back(mappingData); @@ -642,16 +680,14 @@ ComponentIndices generateClipFormatIndices(const QVector<ChannelNameAndType> &ta const int componentCount = targetIndices[i].size(); if (clipChannelIndex != -1) { - // Found a matching channel in the clip. Get the base channel - // component index and populate the format indices for this channel. + // Found a matching channel in the clip. Populate the corresponding + // entries in the format vector with the *source indices* + // needed to build the formatted results. const int baseIndex = clip->channelComponentBaseIndex(clipChannelIndex); - - // Within this group, match channel names with index ordering const auto channelIndices = channelComponentsToIndices(clip->channels()[clipChannelIndex], targetChannel.type, baseIndex); std::copy(channelIndices.begin(), channelIndices.end(), formatIt); - } else { // No such channel in this clip. We'll use default values when // mapping from the clip to the formatted clip results. @@ -673,11 +709,16 @@ ClipResults formatClipResults(const ClipResults &rawClipResults, ClipResults formattedClipResults(elementCount); // Perform a gather operation to format the data + // TODO: For large numbers of components do this in parallel with // for e.g. a parallel_for() like construct + // TODO: We could potentially avoid having holes in these intermediate + // vectors by adjusting the component indices stored in the MappingData + // and format vectors. Needs careful investigation! for (int i = 0; i < elementCount; ++i) { - const float value = format[i] != -1 ? rawClipResults[format[i]] : 0.0f; - formattedClipResults[i] = value; + if (format[i] == -1) + continue; + formattedClipResults[i] = rawClipResults[format[i]]; } return formattedClipResults; |