diff options
author | Sean Harmer <sean.harmer@kdab.com> | 2017-08-27 16:12:02 +0100 |
---|---|---|
committer | Sean Harmer <sean.harmer@kdab.com> | 2017-10-03 09:01:43 +0000 |
commit | 81877f4e463d9da86bc65feade213da5e7226915 (patch) | |
tree | 78d963b1d678613ec0710549dd97031e3a6d95ae | |
parent | 2ff5f87bc36fa4d5e15b49a31232bed0dbecfe5e (diff) |
Update the local poses of the skeleton in the animation aspect
At present it is still needlessly, and incorrectly, updating the
transforms of joints for which we have no animation data by using a
default value of 0 for each component. This causes the joints to be
scaled to 0 which is not particularly useful. We should only update
joints for which we have valid animation data and leave the other
joints alone.
For a skeleton this will be OK as we have the initial set of local
poses available. For regular QNode properties, the animator/mapper
will need to take a snapshot of the current property value when
the animation is started so that we can fill in the missing values
when generating property changes. This should also be fixed on the
5.9 branch.
Change-Id: Ib8f28c55cdfbca3f335777028f72250641092fc9
Reviewed-by: Paul Lemire <paul.lemire@kdab.com>
-rw-r--r-- | src/animation/backend/animationutils.cpp | 49 | ||||
-rw-r--r-- | src/animation/backend/animationutils_p.h | 9 | ||||
-rw-r--r-- | src/animation/backend/skeleton.cpp | 9 | ||||
-rw-r--r-- | src/animation/backend/skeleton_p.h | 17 | ||||
-rw-r--r-- | src/animation/frontend/qanimationaspect.cpp | 1 | ||||
-rw-r--r-- | src/core/transforms/sqt_p.h | 1 |
6 files changed, 85 insertions, 1 deletions
diff --git a/src/animation/backend/animationutils.cpp b/src/animation/backend/animationutils.cpp index 83a9a8426..a1224f69a 100644 --- a/src/animation/backend/animationutils.cpp +++ b/src/animation/backend/animationutils.cpp @@ -48,6 +48,7 @@ #include <QtGui/qquaternion.h> #include <QtGui/qcolor.h> #include <QtCore/qvariant.h> +#include <QtCore/qvarlengtharray.h> #include <Qt3DAnimation/private/animationlogging_p.h> #include <numeric> @@ -292,13 +293,45 @@ QVector<Qt3DCore::QSceneChangePtr> preparePropertyChanges(Qt3DCore::QNodeId anim bool finalFrame) { QVector<Qt3DCore::QSceneChangePtr> changes; + QVarLengthArray<Skeleton *, 4> dirtySkeletons; + // Iterate over the mappings for (const MappingData &mappingData : mappingDataVec) { if (!mappingData.propertyName) continue; + // Build the new value from the channel/fcurve evaluation results const QVariant v = buildPropertyValue(mappingData, channelResults); - if (v.isValid()) { + if (!v.isValid()) + continue; + + // TODO: Avoid wrapping joint transform components up in a variant, just + // to immediately unwrap them again. Refactor buildPropertyValue() to call + // helper functions that we can call directly here for joints. + if (mappingData.skeleton && mappingData.jointIndex != -1) { + // Remember that this skeleton is dirty. We will ask each dirty skeleton + // to send its set of local poses to observers below. + if (!dirtySkeletons.contains(mappingData.skeleton)) + dirtySkeletons.push_back(mappingData.skeleton); + + switch (mappingData.jointTransformComponent) { + case MappingData::Scale: + mappingData.skeleton->setJointScale(mappingData.jointIndex, v.value<QVector3D>()); + break; + + case MappingData::Rotation: + mappingData.skeleton->setJointRotation(mappingData.jointIndex, v.value<QQuaternion>()); + break; + + case MappingData::Translation: + mappingData.skeleton->setJointTranslation(mappingData.jointIndex, v.value<QVector3D>()); + break; + + default: + Q_UNREACHABLE(); + break; + } + } else { // Construct a property update change, set target, property and delivery options auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(mappingData.targetId); e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); @@ -311,6 +344,8 @@ QVector<Qt3DCore::QSceneChangePtr> preparePropertyChanges(Qt3DCore::QNodeId anim } } + for (const auto skeleton : dirtySkeletons) + skeleton->sendLocalPoses(); // If it's the final frame, notify the frontend that we've stopped if (finalFrame) { @@ -415,6 +450,7 @@ QVector<MappingData> buildPropertyMappings(const QVector<ChannelMapping*> &chann // Populate the data we need, easy stuff first MappingData mappingData; mappingData.targetId = mapping->skeletonId(); + mappingData.skeleton = mapping->skeleton(); const int propertyCount = jointProperties.size(); for (int propertyIndex = 0; propertyIndex < propertyCount; ++propertyIndex) { @@ -430,6 +466,17 @@ QVector<MappingData> buildPropertyMappings(const QVector<ChannelMapping*> &chann mappingData.type = nameAndType.type; mappingData.channelIndices = channelComponentIndices[index]; mappingData.jointIndex = jointIndex; + + // Convert property name for joint transform components to + // an enumerated type so we can avoid the string comparisons + // when sending the change events after evaluation. + if (qstrcmp(mappingData.propertyName, "scale") == 0) + mappingData.jointTransformComponent = MappingData::Scale; + else if (qstrcmp(mappingData.propertyName, "rotation") == 0) + mappingData.jointTransformComponent = MappingData::Rotation; + else if (qstrcmp(mappingData.propertyName, "translation") == 0) + mappingData.jointTransformComponent = MappingData::Translation; + mappingDataVec.push_back(mappingData); } } diff --git a/src/animation/backend/animationutils_p.h b/src/animation/backend/animationutils_p.h index 5d84f54b0..a225e9311 100644 --- a/src/animation/backend/animationutils_p.h +++ b/src/animation/backend/animationutils_p.h @@ -71,8 +71,17 @@ typedef QVector<int> ComponentIndices; struct MappingData { + enum JointTransformComponent { + NoTransformComponent = 0, + Scale, + Rotation, + Translation + }; + Qt3DCore::QNodeId targetId; + Skeleton *skeleton = nullptr; int jointIndex = -1; + JointTransformComponent jointTransformComponent = NoTransformComponent; const char *propertyName; QAnimationCallback *callback; QAnimationCallback::Flags callbackFlags; diff --git a/src/animation/backend/skeleton.cpp b/src/animation/backend/skeleton.cpp index a920e2473..dcfaf55e7 100644 --- a/src/animation/backend/skeleton.cpp +++ b/src/animation/backend/skeleton.cpp @@ -96,6 +96,15 @@ void Skeleton::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) BackendNode::sceneChangeEvent(e); } +void Skeleton::sendLocalPoses() +{ + auto e = QPropertyUpdatedChangePtr::create(peerId()); + e->setDeliveryFlags(Qt3DCore::QSceneChange::BackendNodes); + e->setPropertyName("localPoses"); + e->setValue(QVariant::fromValue(m_jointLocalPoses)); + notifyObservers(e); +} + } // namespace Animation } // namespace Qt3DAnimation diff --git a/src/animation/backend/skeleton_p.h b/src/animation/backend/skeleton_p.h index 19da98261..e26e276d9 100644 --- a/src/animation/backend/skeleton_p.h +++ b/src/animation/backend/skeleton_p.h @@ -66,6 +66,23 @@ public: int jointCount() const { return m_jointLocalPoses.size(); } + void setJointScale(int jointIndex, const QVector3D &scale) + { + m_jointLocalPoses[jointIndex].scale = scale; + } + + void setJointRotation(int jointIndex, const QQuaternion &rotation) + { + m_jointLocalPoses[jointIndex].rotation = rotation; + } + + void setJointTranslation(int jointIndex, const QVector3D &translation) + { + m_jointLocalPoses[jointIndex].translation = translation; + } + + void sendLocalPoses(); + #if defined(QT_BUILD_INTERNAL) void setJointCount(int jointCount) { diff --git a/src/animation/frontend/qanimationaspect.cpp b/src/animation/frontend/qanimationaspect.cpp index 14a0c4f8c..9b23a7b1d 100644 --- a/src/animation/frontend/qanimationaspect.cpp +++ b/src/animation/frontend/qanimationaspect.cpp @@ -95,6 +95,7 @@ QAnimationAspect::QAnimationAspect(QAnimationAspectPrivate &dd, QObject *parent) Q_D(QAnimationAspect); qRegisterMetaType<Qt3DAnimation::QAnimationClipLoader*>(); qRegisterMetaType<Qt3DAnimation::QChannelMapper*>(); + qRegisterMetaType<QVector<Qt3DCore::Sqt>>(); registerBackendType<QAbstractAnimationClip>( QSharedPointer<Animation::NodeFunctor<Animation::AnimationClip, Animation::AnimationClipLoaderManager>>::create(d->m_handler.data(), diff --git a/src/core/transforms/sqt_p.h b/src/core/transforms/sqt_p.h index 262e3a645..5fdefccc8 100644 --- a/src/core/transforms/sqt_p.h +++ b/src/core/transforms/sqt_p.h @@ -101,6 +101,7 @@ struct JointNamesAndLocalPoses QT_END_NAMESPACE +Q_DECLARE_METATYPE(QVector<Qt3DCore::Sqt>) Q_DECLARE_METATYPE(Qt3DCore::JointNamesAndLocalPoses) #endif // QT3DCORE_SQT_P_H |