summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSean Harmer <sean.harmer@kdab.com>2017-08-27 11:35:48 +0100
committerSean Harmer <sean.harmer@kdab.com>2017-10-03 09:01:40 +0000
commit2ff5f87bc36fa4d5e15b49a31232bed0dbecfe5e (patch)
tree5e2ec2cbeeacf8609a28ecd3e24ebd3f940af9f9
parent9c951154256734b36328142e1078382dc2d7ae01 (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.cpp105
-rw-r--r--src/animation/backend/animationutils_p.h1
-rw-r--r--src/animation/backend/channelmapping.cpp6
-rw-r--r--src/animation/backend/channelmapping_p.h1
-rw-r--r--tests/auto/animation/animationutils/tst_animationutils.cpp164
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()