diff options
author | Sean Harmer <sean.harmer@kdab.com> | 2017-08-27 11:35:48 +0100 |
---|---|---|
committer | Sean Harmer <sean.harmer@kdab.com> | 2017-10-03 09:01:40 +0000 |
commit | 2ff5f87bc36fa4d5e15b49a31232bed0dbecfe5e (patch) | |
tree | 5e2ec2cbeeacf8609a28ecd3e24ebd3f940af9f9 | |
parent | 9c951154256734b36328142e1078382dc2d7ae01 (diff) |
Extend buildPropertyMappings to support skeleton mapping use case
Change-Id: I2eaf725022f5044d7faf647f8789e73de969d49b
Reviewed-by: Paul Lemire <paul.lemire@kdab.com>
-rw-r--r-- | src/animation/backend/animationutils.cpp | 105 | ||||
-rw-r--r-- | src/animation/backend/animationutils_p.h | 1 | ||||
-rw-r--r-- | src/animation/backend/channelmapping.cpp | 6 | ||||
-rw-r--r-- | src/animation/backend/channelmapping_p.h | 1 | ||||
-rw-r--r-- | tests/auto/animation/animationutils/tst_animationutils.cpp | 164 |
5 files changed, 216 insertions, 61 deletions
diff --git a/src/animation/backend/animationutils.cpp b/src/animation/backend/animationutils.cpp index 4e90d3c1d..83a9a8426 100644 --- a/src/animation/backend/animationutils.cpp +++ b/src/animation/backend/animationutils.cpp @@ -342,37 +342,100 @@ QVector<AnimationCallbackAndValue> prepareCallbacks(const QVector<MappingData> & return callbacks; } +// TODO: Optimize this even more by combining the work done here with the functions: +// buildRequiredChannelsAndTypes() and assignChannelComponentIndices(). We are +// currently repeating the iteration over mappings and extracting/generating +// channel names, types and joint indices. QVector<MappingData> buildPropertyMappings(const QVector<ChannelMapping*> &channelMappings, const QVector<ChannelNameAndType> &channelNamesAndTypes, const QVector<ComponentIndices> &channelComponentIndices) { + // Accumulate the required number of mappings + int maxMappingDatas = 0; + for (const auto mapping : channelMappings) { + switch (mapping->mappingType()) { + case ChannelMapping::ChannelMappingType: + case ChannelMapping::CallbackMappingType: + ++maxMappingDatas; + break; + + case ChannelMapping::SkeletonMappingType: { + Skeleton *skeleton = mapping->skeleton(); + maxMappingDatas += 3 * skeleton->jointCount(); // S, R, T + break; + } + } + } QVector<MappingData> mappingDataVec; - mappingDataVec.reserve(channelMappings.size()); + mappingDataVec.reserve(maxMappingDatas); // Iterate over the mappings for (const auto mapping : channelMappings) { - // Populate the data we need, easy stuff first - MappingData mappingData; - mappingData.targetId = mapping->targetId(); - mappingData.propertyName = mapping->propertyName(); - mappingData.type = mapping->type(); - mappingData.callback = mapping->callback(); - mappingData.callbackFlags = mapping->callbackFlags(); - - if (mappingData.type == static_cast<int>(QVariant::Invalid)) { - qWarning() << "Unknown type for node id =" << mappingData.targetId - << "and property =" << mapping->property() - << "and callback =" << mapping->callback(); - continue; + switch (mapping->mappingType()) { + case ChannelMapping::ChannelMappingType: + case ChannelMapping::CallbackMappingType: { + // Populate the data we need, easy stuff first + MappingData mappingData; + mappingData.targetId = mapping->targetId(); + mappingData.propertyName = mapping->propertyName(); + mappingData.type = mapping->type(); + mappingData.callback = mapping->callback(); + mappingData.callbackFlags = mapping->callbackFlags(); + + if (mappingData.type == static_cast<int>(QVariant::Invalid)) { + qWarning() << "Unknown type for node id =" << mappingData.targetId + << "and property =" << mapping->property() + << "and callback =" << mapping->callback(); + continue; + } + + // Try to find matching channel name and type + const ChannelNameAndType nameAndType = { mapping->channelName(), mapping->type() }; + const int index = channelNamesAndTypes.indexOf(nameAndType); + if (index != -1) { + // We got one! + mappingData.channelIndices = channelComponentIndices[index]; + mappingDataVec.push_back(mappingData); + } + break; } - // Try to find matching channel name and type - const ChannelNameAndType nameAndType = { mapping->channelName(), mapping->type() }; - const int index = channelNamesAndTypes.indexOf(nameAndType); - if (index != -1) { - // We got one! - mappingData.channelIndices = channelComponentIndices[index]; - mappingDataVec.push_back(mappingData); + case ChannelMapping::SkeletonMappingType: { + const QVector<ChannelNameAndType> jointProperties + = { { QLatin1String("Location"), static_cast<int>(QVariant::Vector3D) }, + { QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion) }, + { QLatin1String("Scale"), static_cast<int>(QVariant::Vector3D) } }; + const QHash<QString, const char *> channelNameToPropertyName + = { { QLatin1String("Location"), "translation" }, + { QLatin1String("Rotation"), "rotation" }, + { QLatin1String("Scale"), "scale" } }; + Skeleton *skeleton = mapping->skeleton(); + const int jointCount = skeleton->jointCount(); + for (int jointIndex = 0; jointIndex < jointCount; ++jointIndex) { + // Populate the data we need, easy stuff first + MappingData mappingData; + mappingData.targetId = mapping->skeletonId(); + + const int propertyCount = jointProperties.size(); + for (int propertyIndex = 0; propertyIndex < propertyCount; ++propertyIndex) { + // Get the name, type and index + ChannelNameAndType nameAndType = jointProperties[propertyIndex]; + nameAndType.jointIndex = jointIndex; + + // Try to find matching channel name and type + const int index = channelNamesAndTypes.indexOf(nameAndType); + if (index != -1) { + // We got one! + mappingData.propertyName = channelNameToPropertyName[nameAndType.name]; + mappingData.type = nameAndType.type; + mappingData.channelIndices = channelComponentIndices[index]; + mappingData.jointIndex = jointIndex; + mappingDataVec.push_back(mappingData); + } + } + } + break; + } } } diff --git a/src/animation/backend/animationutils_p.h b/src/animation/backend/animationutils_p.h index cf21c448d..5d84f54b0 100644 --- a/src/animation/backend/animationutils_p.h +++ b/src/animation/backend/animationutils_p.h @@ -72,6 +72,7 @@ typedef QVector<int> ComponentIndices; struct MappingData { Qt3DCore::QNodeId targetId; + int jointIndex = -1; const char *propertyName; QAnimationCallback *callback; QAnimationCallback::Flags callbackFlags; diff --git a/src/animation/backend/channelmapping.cpp b/src/animation/backend/channelmapping.cpp index 417c10a1a..4c263edba 100644 --- a/src/animation/backend/channelmapping.cpp +++ b/src/animation/backend/channelmapping.cpp @@ -40,6 +40,7 @@ #include <Qt3DAnimation/private/qskeletonmapping_p.h> #include <Qt3DAnimation/private/animationlogging_p.h> #include <Qt3DAnimation/private/qchannelmappingcreatedchange_p.h> +#include <Qt3DAnimation/private/managers_p.h> #include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE @@ -137,6 +138,11 @@ void ChannelMapping::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) QBackendNode::sceneChangeEvent(e); } +Skeleton *ChannelMapping::skeleton() const +{ + return m_handler->skeletonManager()->lookupResource(m_skeletonId); +} + } // namespace Animation } // namespace Qt3DAnimation diff --git a/src/animation/backend/channelmapping_p.h b/src/animation/backend/channelmapping_p.h index 5cebbaf55..72b9975ef 100644 --- a/src/animation/backend/channelmapping_p.h +++ b/src/animation/backend/channelmapping_p.h @@ -101,6 +101,7 @@ public: void setSkeletonId(Qt3DCore::QNodeId skeletonId) { m_skeletonId = skeletonId; } Qt3DCore::QNodeId skeletonId() const { return m_skeletonId; } + Skeleton *skeleton() const; void setMappingType(MappingType mappingType) { m_mappingType = mappingType; } MappingType mappingType() const { return m_mappingType; } diff --git a/tests/auto/animation/animationutils/tst_animationutils.cpp b/tests/auto/animation/animationutils/tst_animationutils.cpp index 177dbd19a..c3253b9ce 100644 --- a/tests/auto/animation/animationutils/tst_animationutils.cpp +++ b/tests/auto/animation/animationutils/tst_animationutils.cpp @@ -149,6 +149,7 @@ public: auto channelMappingId = Qt3DCore::QNodeId::createId(); ChannelMapping *channelMapping = handler->channelMappingManager()->getOrCreateResource(channelMappingId); setPeerId(channelMapping, channelMappingId); + channelMapping->setHandler(handler); channelMapping->setTargetId(targetId); channelMapping->setProperty(property); channelMapping->setPropertyName(propertyName); @@ -164,6 +165,7 @@ public: auto channelMappingId = Qt3DCore::QNodeId::createId(); ChannelMapping *channelMapping = handler->channelMappingManager()->getOrCreateResource(channelMappingId); setPeerId(channelMapping, channelMappingId); + channelMapping->setHandler(handler); channelMapping->setSkeletonId(skeletonId); channelMapping->setMappingType(ChannelMapping::SkeletonMappingType); return channelMapping; @@ -271,6 +273,7 @@ public: private Q_SLOTS: void checkBuildPropertyMappings_data() { + QTest::addColumn<Handler *>("handler"); QTest::addColumn<QVector<ChannelMapping *>>("channelMappings"); QTest::addColumn<QVector<ChannelNameAndType>>("channelNamesAndTypes"); QTest::addColumn<QVector<ComponentIndices>>("channelComponentIndices"); @@ -278,12 +281,14 @@ private Q_SLOTS: // Single ChannelMapping { - auto channelMapping = new ChannelMapping(); - channelMapping->setChannelName("Location"); - channelMapping->setTargetId(Qt3DCore::QNodeId::createId()); - channelMapping->setProperty(QLatin1String("translation")); - channelMapping->setPropertyName("translation"); - channelMapping->setType(static_cast<int>(QVariant::Vector3D)); + Handler *handler = new Handler(); + + auto channelMapping = createChannelMapping(handler, + QLatin1String("Location"), + Qt3DCore::QNodeId::createId(), + QLatin1String("translation"), + "translation", + static_cast<int>(QVariant::Vector3D)); QVector<ChannelMapping *> channelMappings = { channelMapping }; @@ -319,6 +324,7 @@ private Q_SLOTS: QVector<MappingData> expectedResults = { expectedMapping }; QTest::newRow("single mapping") + << handler << channelMappings << channelNamesAndTypes << channelComponentIndices @@ -327,40 +333,42 @@ private Q_SLOTS: // Multiple ChannelMappings { - auto locationMapping = new ChannelMapping(); - locationMapping->setChannelName("Location"); - locationMapping->setTargetId(Qt3DCore::QNodeId::createId()); - locationMapping->setProperty(QLatin1String("translation")); - locationMapping->setPropertyName("translation"); - locationMapping->setType(static_cast<int>(QVariant::Vector3D)); - - auto metalnessMapping = new ChannelMapping(); - metalnessMapping->setChannelName("Metalness"); - metalnessMapping->setTargetId(Qt3DCore::QNodeId::createId()); - metalnessMapping->setProperty(QLatin1String("metalness")); - metalnessMapping->setPropertyName("metalness"); - metalnessMapping->setType(static_cast<int>(QVariant::Double)); - - auto baseColorMapping = new ChannelMapping(); - baseColorMapping->setChannelName("BaseColor"); - baseColorMapping->setTargetId(Qt3DCore::QNodeId::createId()); - baseColorMapping->setProperty(QLatin1String("baseColor")); - baseColorMapping->setPropertyName("baseColor"); - baseColorMapping->setType(static_cast<int>(QVariant::Vector3D)); - - auto roughnessMapping = new ChannelMapping(); - roughnessMapping->setChannelName("Roughness"); - roughnessMapping->setTargetId(Qt3DCore::QNodeId::createId()); - roughnessMapping->setProperty(QLatin1String("roughness")); - roughnessMapping->setPropertyName("roughness"); - roughnessMapping->setType(static_cast<int>(QVariant::Double)); - - auto rotationMapping = new ChannelMapping(); - rotationMapping->setChannelName("Rotation"); - rotationMapping->setTargetId(Qt3DCore::QNodeId::createId()); - rotationMapping->setProperty(QLatin1String("rotation")); - rotationMapping->setPropertyName("rotation"); - rotationMapping->setType(static_cast<int>(QVariant::Quaternion)); + Handler *handler = new Handler(); + + auto locationMapping = createChannelMapping(handler, + QLatin1String("Location"), + Qt3DCore::QNodeId::createId(), + QLatin1String("translation"), + "translation", + static_cast<int>(QVariant::Vector3D)); + + auto metalnessMapping = createChannelMapping(handler, + QLatin1String("Metalness"), + Qt3DCore::QNodeId::createId(), + QLatin1String("metalness"), + "metalness", + static_cast<int>(QVariant::Double)); + + auto baseColorMapping = createChannelMapping(handler, + QLatin1String("BaseColor"), + Qt3DCore::QNodeId::createId(), + QLatin1String("baseColor"), + "baseColor", + static_cast<int>(QVariant::Vector3D)); + + auto roughnessMapping = createChannelMapping(handler, + QLatin1String("Roughness"), + Qt3DCore::QNodeId::createId(), + QLatin1String("roughness"), + "roughness", + static_cast<int>(QVariant::Double)); + + auto rotationMapping = createChannelMapping(handler, + QLatin1String("Rotation"), + Qt3DCore::QNodeId::createId(), + QLatin1String("rotation"), + "rotation", + static_cast<int>(QVariant::Quaternion)); QVector<ChannelMapping *> channelMappings = { locationMapping, metalnessMapping, @@ -429,6 +437,77 @@ private Q_SLOTS: expectedRotationMapping }; QTest::newRow("multiple mappings") + << handler + << channelMappings + << channelNamesAndTypes + << channelComponentIndices + << expectedResults; + } + + // Single skeleton mapping + { + Handler *handler = new Handler(); + const int jointCount = 4; + auto skeleton = createSkeleton(handler, jointCount); + auto channelMapping = createChannelMapping(handler, skeleton->peerId()); + + QVector<ChannelMapping *> channelMappings = { channelMapping }; + + // Create a few channels in the format description + QVector<ChannelNameAndType> channelNamesAndTypes; + for (int i = 0; i < jointCount; ++i) { + channelNamesAndTypes.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D), i }); + channelNamesAndTypes.push_back({ QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion), i }); + channelNamesAndTypes.push_back({ QLatin1String("Scale"), static_cast<int>(QVariant::Vector3D), i }); + } + + // And the matching indices + QVector<ComponentIndices> channelComponentIndices; + channelComponentIndices.push_back({ 0, 1, 2 }); + channelComponentIndices.push_back({ 3, 4, 5, 6 }); + channelComponentIndices.push_back({ 7, 8, 9 }); + + channelComponentIndices.push_back({ 10, 11, 12 }); + channelComponentIndices.push_back({ 13, 14, 15, 16 }); + channelComponentIndices.push_back({ 17, 18, 19 }); + + channelComponentIndices.push_back({ 20, 21, 22 }); + channelComponentIndices.push_back({ 23, 24, 25, 26 }); + channelComponentIndices.push_back({ 27, 28, 29 }); + + channelComponentIndices.push_back({ 30, 31, 32 }); + channelComponentIndices.push_back({ 33, 34, 35, 36 }); + channelComponentIndices.push_back({ 37, 38, 39 }); + + QVector<MappingData> expectedResults; + int componentIndicesIndex = 0; + for (int i = 0; i < jointCount; ++i) { + MappingData locationMapping; + locationMapping.targetId = channelMapping->skeletonId(); + locationMapping.propertyName = "translation"; + locationMapping.type = static_cast<int>(QVariant::Vector3D); + locationMapping.channelIndices = channelComponentIndices[componentIndicesIndex++]; + locationMapping.jointIndex = i; + + MappingData rotationMapping; + rotationMapping.targetId = channelMapping->skeletonId(); + rotationMapping.propertyName = "rotation"; + rotationMapping.type = static_cast<int>(QVariant::Quaternion); + rotationMapping.channelIndices = channelComponentIndices[componentIndicesIndex++]; + rotationMapping.jointIndex = i; + + MappingData scaleMapping; + scaleMapping.targetId = channelMapping->skeletonId(); + scaleMapping.propertyName = "scale"; + scaleMapping.type = static_cast<int>(QVariant::Vector3D); + scaleMapping.channelIndices = channelComponentIndices[componentIndicesIndex++]; + scaleMapping.jointIndex = i; + + expectedResults << locationMapping << rotationMapping << scaleMapping; + } + + QTest::newRow("single skeleton mapping") + << handler << channelMappings << channelNamesAndTypes << channelComponentIndices @@ -439,6 +518,7 @@ private Q_SLOTS: void checkBuildPropertyMappings() { // GIVEN + QFETCH(Handler *, handler); QFETCH(QVector<ChannelMapping *>, channelMappings); QFETCH(QVector<ChannelNameAndType>, channelNamesAndTypes); QFETCH(QVector<ComponentIndices>, channelComponentIndices); @@ -456,6 +536,7 @@ private Q_SLOTS: const auto expectedMapping = expectedResults[i]; QCOMPARE(actualMapping.targetId, expectedMapping.targetId); + QCOMPARE(actualMapping.jointIndex, expectedMapping.jointIndex); QCOMPARE(actualMapping.propertyName, expectedMapping.propertyName); QCOMPARE(actualMapping.type, expectedMapping.type); QCOMPARE(actualMapping.channelIndices.size(), expectedMapping.channelIndices.size()); @@ -463,6 +544,9 @@ private Q_SLOTS: QCOMPARE(actualMapping.channelIndices[j], expectedMapping.channelIndices[j]); } } + + // Cleanup + delete handler; } void checkLocalTimeFromGlobalTime_data() |