diff options
26 files changed, 635 insertions, 231 deletions
diff --git a/.qmake.conf b/.qmake.conf index 78a277a3f..2108ac6fd 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -1,3 +1,3 @@ load(qt_build_config) -MODULE_VERSION = 5.9.2 +MODULE_VERSION = 5.9.3 diff --git a/src/animation/backend/animationutils.cpp b/src/animation/backend/animationutils.cpp index c12ad99f7..8308fab34 100644 --- a/src/animation/backend/animationutils.cpp +++ b/src/animation/backend/animationutils.cpp @@ -147,6 +147,17 @@ double phaseFromGlobalTime(double t_global, double t_start_global, 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 @@ -170,9 +181,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(); @@ -182,15 +193,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; - char suffix = componentName.at(componentName.length() - 1).toLatin1(); - int index = suffixes.indexOf(suffix); + + // 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 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; } @@ -308,62 +341,6 @@ QVector<Qt3DCore::QSceneChangePtr> preparePropertyChanges(Qt3DCore::QNodeId anim return changes; } -//TODO: Remove this and use new implementation below for both the unblended -// and blended animation cases. -QVector<MappingData> buildPropertyMappings(Handler *handler, - const AnimationClip *clip, - const ChannelMapper *mapper) -{ - QVector<MappingData> mappingDataVec; - ChannelMappingManager *mappingManager = handler->channelMappingManager(); - const QVector<Channel> &channels = clip->channels(); - - // Iterate over the mappings in the mapper object - const auto mappingIds = mapper->mappingIds(); - for (const Qt3DCore::QNodeId mappingId : mappingIds) { - // Get the mapping object - ChannelMapping *mapping = mappingManager->lookupResource(mappingId); - Q_ASSERT(mapping); - - // Populate the data we need, easy stuff first - MappingData mappingData; - mappingData.targetId = mapping->targetId(); - mappingData.propertyName = mapping->propertyName(); - mappingData.type = mapping->type(); - - if (mappingData.type == static_cast<int>(QVariant::Invalid)) { - qWarning() << "Unknown type for node id =" << mappingData.targetId - << "and property =" << mapping->property(); - continue; - } - - // Now the tricky part. Mapping the channel indices onto the property type. - // Try to find a ChannelGroup with matching name - const QString channelName = mapping->channelName(); - int channelGroupIndex = 0; - bool foundMatch = false; - for (const Channel &channel : channels) { - if (channel.name == channelName) { - foundMatch = true; - const int channelBaseIndex = clip->channelComponentBaseIndex(channelGroupIndex); - - // Within this group, match channel names with index ordering - mappingData.channelIndices = channelComponentsToIndices(channel, mappingData.type, channelBaseIndex); - - // Store the mapping data - mappingDataVec.push_back(mappingData); - - if (foundMatch) - break; - } - - ++channelGroupIndex; - } - } - - return mappingDataVec; -} - QVector<MappingData> buildPropertyMappings(const QVector<ChannelMapping*> &channelMappings, const QVector<ChannelNameAndType> &channelNamesAndTypes, const QVector<ComponentIndices> &channelComponentIndices) @@ -467,6 +444,10 @@ QVector<Qt3DCore::QNodeId> gatherValueNodesToEvaluate(Handler *handler, ClipBlendNodeVisitor::VisitOnlyDependencies); auto func = [&clipIds, nodeManager] (ClipBlendNode *blendNode) { + // Check if this is a value node itself + if (blendNode->blendType() == ClipBlendNode::ValueType) + clipIds.append(blendNode->peerId()); + const auto dependencyIds = blendNode->currentDependencyIds(); for (const auto dependencyId : dependencyIds) { // Look up the blend node and if it's a value type (clip), @@ -493,12 +474,11 @@ ComponentIndices generateClipFormatIndices(const QVector<ChannelNameAndType> &ta // Reserve enough storage for all the format indices int indexCount = 0; - for (const auto targetIndexVec : qAsConst(targetIndices)) + for (const auto &targetIndexVec : qAsConst(targetIndices)) indexCount += targetIndexVec.size(); ComponentIndices format; format.resize(indexCount); - // Iterate through the target channels const int channelCount = targetChannels.size(); auto formatIt = format.begin(); @@ -506,19 +486,17 @@ ComponentIndices generateClipFormatIndices(const QVector<ChannelNameAndType> &ta // Find the index of the channel from the clip const ChannelNameAndType &targetChannel = targetChannels[i]; const int clipChannelIndex = clip->channelIndex(targetChannel.name); - - // TODO: Ensure channel in the clip has enough components to map to the type. - // Requires some improvements to the clip data structure first. - // TODO: I don't think we need the targetIndices, only the number of components - // for each target channel. Check once blend tree is complete. 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); - std::iota(formatIt, formatIt + componentCount, baseIndex); - + 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. @@ -539,11 +517,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; diff --git a/src/animation/backend/animationutils_p.h b/src/animation/backend/animationutils_p.h index f8fcbafa7..c702ab5c4 100644 --- a/src/animation/backend/animationutils_p.h +++ b/src/animation/backend/animationutils_p.h @@ -157,11 +157,6 @@ QVector<Qt3DCore::QSceneChangePtr> preparePropertyChanges(Qt3DCore::QNodeId anim bool finalFrame); Q_AUTOTEST_EXPORT -QVector<MappingData> buildPropertyMappings(Handler *handler, - const AnimationClip *clip, - const ChannelMapper *mapper); - -Q_AUTOTEST_EXPORT QVector<MappingData> buildPropertyMappings(const QVector<ChannelMapping *> &channelMappings, const QVector<ChannelNameAndType> &channelNamesAndTypes, const QVector<ComponentIndices> &channelComponentIndices); diff --git a/src/animation/backend/channelmapper.cpp b/src/animation/backend/channelmapper.cpp index 0e5555096..48a1335fa 100644 --- a/src/animation/backend/channelmapper.cpp +++ b/src/animation/backend/channelmapper.cpp @@ -38,6 +38,7 @@ #include <Qt3DAnimation/qchannelmapper.h> #include <Qt3DAnimation/private/qchannelmapper_p.h> #include <Qt3DAnimation/private/animationlogging_p.h> +#include <Qt3DAnimation/private/managers_p.h> #include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DCore/qpropertynodeaddedchange.h> #include <Qt3DCore/qpropertynoderemovedchange.h> @@ -50,6 +51,7 @@ namespace Animation { ChannelMapper::ChannelMapper() : BackendNode(ReadOnly) , m_mappingIds() + , m_isDirty(true) { } @@ -58,12 +60,15 @@ void ChannelMapper::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QChannelMapperData>>(change); const auto &data = typedChange->data; m_mappingIds = data.mappingIds; + m_isDirty = true; } void ChannelMapper::cleanup() { setEnabled(false); m_mappingIds.clear(); + m_mappings.clear(); + m_isDirty = true; } void ChannelMapper::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) @@ -74,6 +79,7 @@ void ChannelMapper::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) if (change->propertyName() == QByteArrayLiteral("mappings")) { m_mappingIds.push_back(change->addedNodeId()); setDirty(Handler::ChannelMappingsDirty); + m_isDirty = true; } break; } @@ -83,6 +89,7 @@ void ChannelMapper::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) if (change->propertyName() == QByteArrayLiteral("mappings")) { m_mappingIds.removeOne(change->removedNodeId()); setDirty(Handler::ChannelMappingsDirty); + m_isDirty = true; } break; } @@ -93,6 +100,19 @@ void ChannelMapper::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) QBackendNode::sceneChangeEvent(e); } +void ChannelMapper::updateMappings() const +{ + m_mappings.clear(); + m_mappings.reserve(m_mappingIds.size()); + const auto mappingManager = m_handler->channelMappingManager(); + for (const auto &mappingId : m_mappingIds) { + const auto mapping = mappingManager->lookupResource(mappingId); + Q_ASSERT(mapping); + m_mappings.push_back(mapping); + } + m_isDirty = false; +} + } // namespace Animation } // namespace Qt3DAnimation diff --git a/src/animation/backend/channelmapper_p.h b/src/animation/backend/channelmapper_p.h index 710de01ab..8d8f03511 100644 --- a/src/animation/backend/channelmapper_p.h +++ b/src/animation/backend/channelmapper_p.h @@ -74,10 +74,22 @@ public: void setMappingIds(const QVector<Qt3DCore::QNodeId> &mappingIds) { m_mappingIds = mappingIds; } QVector<Qt3DCore::QNodeId> mappingIds() const { return m_mappingIds; } + QVector<ChannelMapping*> mappings() const + { + if (m_isDirty) + updateMappings(); + return m_mappings; + } + private: void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL; + void updateMappings() const; QVector<Qt3DCore::QNodeId> m_mappingIds; + + // Cached data + mutable QVector<ChannelMapping*> m_mappings; + mutable bool m_isDirty; }; } // namespace Animation diff --git a/src/animation/backend/clipanimator.cpp b/src/animation/backend/clipanimator.cpp index e68168f9e..92082b74f 100644 --- a/src/animation/backend/clipanimator.cpp +++ b/src/animation/backend/clipanimator.cpp @@ -104,6 +104,7 @@ void ClipAnimator::cleanup() m_mapperId = Qt3DCore::QNodeId(); m_running = false; m_loops = 1; + m_formatIndices.clear(); } void ClipAnimator::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) diff --git a/src/animation/backend/clipanimator_p.h b/src/animation/backend/clipanimator_p.h index 9db575ab9..5a9035dff 100644 --- a/src/animation/backend/clipanimator_p.h +++ b/src/animation/backend/clipanimator_p.h @@ -94,6 +94,9 @@ public: void animationClipMarkedDirty() { setDirty(Handler::ClipAnimatorDirty); } + void setFormatIndices(const ComponentIndices &formatIndices) { m_formatIndices = formatIndices; } + ComponentIndices formatIndices() const { return m_formatIndices; } + private: void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL; @@ -107,6 +110,7 @@ private: QVector<MappingData> m_mappingData; int m_currentLoop; + ComponentIndices m_formatIndices; }; } // namespace Animation diff --git a/src/animation/backend/clipblendvalue_p.h b/src/animation/backend/clipblendvalue_p.h index 6da800f98..5ff8d2b0f 100644 --- a/src/animation/backend/clipblendvalue_p.h +++ b/src/animation/backend/clipblendvalue_p.h @@ -73,7 +73,7 @@ public: inline QVector<Qt3DCore::QNodeId> currentDependencyIds() const Q_DECL_OVERRIDE { - return { m_clipId }; + return {}; } double duration() const Q_DECL_OVERRIDE; diff --git a/src/animation/backend/evaluateclipanimatorjob.cpp b/src/animation/backend/evaluateclipanimatorjob.cpp index e89405d63..72e16a593 100644 --- a/src/animation/backend/evaluateclipanimatorjob.cpp +++ b/src/animation/backend/evaluateclipanimatorjob.cpp @@ -68,7 +68,11 @@ void EvaluateClipAnimatorJob::run() // Prepare for evaluation (convert global time to local time ....) const AnimatorEvaluationData animatorEvaluationData = evaluationDataForAnimator(clipAnimator, globalTime); const ClipEvaluationData preEvaluationDataForClip = evaluationDataForClip(clip, animatorEvaluationData); - const ClipResults channelResults = evaluateClipAtLocalTime(clip, preEvaluationDataForClip.localTime); + const ClipResults rawClipResults = evaluateClipAtLocalTime(clip, preEvaluationDataForClip.localTime); + + // Reformat the clip results into the layout used by this animator/blend tree + ComponentIndices format = clipAnimator->formatIndices(); + ClipResults formattedClipResults = formatClipResults(rawClipResults, format); if (preEvaluationDataForClip.isFinalFrame) clipAnimator->setRunning(false); @@ -78,7 +82,7 @@ void EvaluateClipAnimatorJob::run() // Prepare property changes (if finalFrame it also prepares the change for the running property for the frontend) const QVector<Qt3DCore::QSceneChangePtr> changes = preparePropertyChanges(clipAnimator->peerId(), clipAnimator->mappingData(), - channelResults, + formattedClipResults, preEvaluationDataForClip.isFinalFrame); // Send the property changes diff --git a/src/animation/backend/fcurve_p.h b/src/animation/backend/fcurve_p.h index 7ab1593d1..e9138d6a1 100644 --- a/src/animation/backend/fcurve_p.h +++ b/src/animation/backend/fcurve_p.h @@ -98,14 +98,27 @@ private: inline QDebug operator<<(QDebug dbg, const FCurve &fcurve) { QDebugStateSaver saver(dbg); - dbg << "Keyframe Count =" << fcurve.keyframeCount() << endl; + dbg << "Keyframe Count = " << fcurve.keyframeCount() << endl; for (int i = 0; i < fcurve.keyframeCount(); ++i) { const Keyframe &kf = fcurve.keyframe(i); - dbg << "t =" << fcurve.localTime(i) - << "value =" << kf.value - << "leftHandle =" << kf.leftControlPoint - << "rightHandle =" << kf.rightControlPoint - << endl; + switch (kf.interpolation) { + case QKeyFrame::BezierInterpolation: { + dbg << "t = " << fcurve.localTime(i) + << ", value = " << kf.value + << ", leftHandle = " << kf.leftControlPoint + << ", rightHandle = " << kf.rightControlPoint + << endl; + break; + } + + case QKeyFrame::ConstantInterpolation: + case QKeyFrame::LinearInterpolation: { + dbg << "t = " << fcurve.localTime(i) + << ", value = " << kf.value + << endl; + break; + } + } } return dbg; } diff --git a/src/animation/backend/findrunningclipanimatorsjob.cpp b/src/animation/backend/findrunningclipanimatorsjob.cpp index a8349eb91..41454004d 100644 --- a/src/animation/backend/findrunningclipanimatorsjob.cpp +++ b/src/animation/backend/findrunningclipanimatorsjob.cpp @@ -62,24 +62,39 @@ void FindRunningClipAnimatorsJob::run() Q_ASSERT(m_handler); ClipAnimatorManager *clipAnimatorManager = m_handler->clipAnimatorManager(); - for (const auto clipAnimatorHandle : qAsConst(m_clipAnimatorHandles)) { + for (const auto &clipAnimatorHandle : qAsConst(m_clipAnimatorHandles)) { ClipAnimator *clipAnimator = clipAnimatorManager->data(clipAnimatorHandle); Q_ASSERT(clipAnimator); const bool canRun = clipAnimator->canRun(); m_handler->setClipAnimatorRunning(clipAnimatorHandle, canRun); - // The clip animator needs to know how to map fcurve values through to - // properties on QNodes. Now we know this animator can run, build the mapping - // table. - // TODO: Should be possible to parallelise this with the fcurve evaluation as - // sending the property change events doesn't happen until after evaluation - if (canRun) { - const AnimationClip *clip = m_handler->animationClipLoaderManager()->lookupResource(clipAnimator->clipId()); - const ChannelMapper *mapper = m_handler->channelMapperManager()->lookupResource(clipAnimator->mapperId()); - Q_ASSERT(clip && mapper); - const QVector<MappingData> mappingData = buildPropertyMappings(m_handler, clip, mapper); - clipAnimator->setMappingData(mappingData); - } + if (!canRun) + continue; + + // The clip animator needs to know how to map fcurve values through to properties on QNodes. + // Now we know this animator can run, build the mapping table. Even though this could be + // done a little simpler in the non-blended case, we follow the same code path as the + // blended clip animator for consistency and ease of maintenance. + const ChannelMapper *mapper = m_handler->channelMapperManager()->lookupResource(clipAnimator->mapperId()); + Q_ASSERT(mapper); + const QVector<ChannelMapping *> channelMappings = mapper->mappings(); + + const QVector<ChannelNameAndType> channelNamesAndTypes + = buildRequiredChannelsAndTypes(m_handler, mapper); + const QVector<ComponentIndices> channelComponentIndices + = assignChannelComponentIndices(channelNamesAndTypes); + + const AnimationClip *clip = m_handler->animationClipLoaderManager()->lookupResource(clipAnimator->clipId()); + Q_ASSERT(clip); + const ComponentIndices formatIndices = generateClipFormatIndices(channelNamesAndTypes, + channelComponentIndices, + clip); + clipAnimator->setFormatIndices(formatIndices); + + const QVector<MappingData> mappingData = buildPropertyMappings(channelMappings, + channelNamesAndTypes, + channelComponentIndices); + clipAnimator->setMappingData(mappingData); } qCDebug(Jobs) << "Running clip animators =" << m_handler->runningClipAnimators(); diff --git a/src/animation/backend/findrunningclipanimatorsjob_p.h b/src/animation/backend/findrunningclipanimatorsjob_p.h index 023f46303..f8b09939f 100644 --- a/src/animation/backend/findrunningclipanimatorsjob_p.h +++ b/src/animation/backend/findrunningclipanimatorsjob_p.h @@ -52,6 +52,10 @@ #include <Qt3DAnimation/private/handle_types_p.h> #include <QtCore/qvector.h> +#if defined(QT_BUILD_INTERNAL) +class tst_FindRunningClipAnimatorsJob; +#endif + QT_BEGIN_NAMESPACE namespace Qt3DAnimation { @@ -59,7 +63,7 @@ namespace Animation { class Handler; -class FindRunningClipAnimatorsJob : public Qt3DCore::QAspectJob +class Q_AUTOTEST_EXPORT FindRunningClipAnimatorsJob : public Qt3DCore::QAspectJob { public: FindRunningClipAnimatorsJob(); @@ -75,6 +79,10 @@ protected: private: QVector<HClipAnimator> m_clipAnimatorHandles; Handler *m_handler; + +#if defined(QT_BUILD_INTERNAL) + friend class ::tst_FindRunningClipAnimatorsJob; +#endif }; } // namespace Animation diff --git a/src/render/geometry/qmesh.cpp b/src/render/geometry/qmesh.cpp index 614806df0..cf14ff4ff 100644 --- a/src/render/geometry/qmesh.cpp +++ b/src/render/geometry/qmesh.cpp @@ -261,8 +261,10 @@ QGeometry *MeshFunctor::operator()() bool MeshFunctor::operator ==(const QGeometryFactory &other) const { const MeshFunctor *otherFunctor = functor_cast<MeshFunctor>(&other); - if (otherFunctor != nullptr) - return (otherFunctor->m_sourcePath == m_sourcePath); + if (otherFunctor != nullptr) { + return (otherFunctor->m_sourcePath == m_sourcePath + && otherFunctor->m_meshName == m_meshName); + } return false; } diff --git a/src/render/graphicshelpers/graphicscontext.cpp b/src/render/graphicshelpers/graphicscontext.cpp index b13449760..7b09985a7 100644 --- a/src/render/graphicshelpers/graphicscontext.cpp +++ b/src/render/graphicshelpers/graphicscontext.cpp @@ -1204,11 +1204,6 @@ void GraphicsContext::setParameters(ShaderParameterPack ¶meterPack) // be bound as a VertexArray bindGLBuffer(ssbo, GLBuffer::ShaderStorageBuffer); ssbo->bindBufferBase(this, ssboIndex++, GLBuffer::ShaderStorageBuffer); - // Perform update if required - if (cpuBuffer->isDirty()) { - uploadDataToGLBuffer(cpuBuffer, ssbo); - cpuBuffer->unsetDirty(); - } // TO DO: Make sure that there's enough binding points } @@ -1224,11 +1219,6 @@ void GraphicsContext::setParameters(ShaderParameterPack ¶meterPack) // be bound as a VertexArray bindGLBuffer(ubo, GLBuffer::UniformBuffer); ubo->bindBufferBase(this, uboIndex++, GLBuffer::UniformBuffer); - if (cpuBuffer->isDirty()) { - // Perform update if required - uploadDataToGLBuffer(cpuBuffer, ubo); - cpuBuffer->unsetDirty(); - } // TO DO: Make sure that there's enough binding points } diff --git a/tests/auto/animation/animation.pro b/tests/auto/animation/animation.pro index b48fd347b..421ecfdd5 100644 --- a/tests/auto/animation/animation.pro +++ b/tests/auto/animation/animation.pro @@ -34,5 +34,6 @@ qtConfig(private_tests) { additiveclipblend \ clipblendvalue \ animationutils \ - qabstractanimation + qabstractanimation \ + findrunningclipanimatorsjob } diff --git a/tests/auto/animation/animationutils/tst_animationutils.cpp b/tests/auto/animation/animationutils/tst_animationutils.cpp index e7a0f343d..36e954a85 100644 --- a/tests/auto/animation/animationutils/tst_animationutils.cpp +++ b/tests/auto/animation/animationutils/tst_animationutils.cpp @@ -241,77 +241,6 @@ public: private Q_SLOTS: void checkBuildPropertyMappings_data() { - QTest::addColumn<Handler *>("handler"); - QTest::addColumn<QVector<ChannelMapping *>>("channelMappings"); - QTest::addColumn<ChannelMapper *>("channelMapper"); - QTest::addColumn<AnimationClip *>("clip"); - QTest::addColumn<QVector<MappingData>>("expectedMappingData"); - - auto handler = new Handler; - auto channelMapping = createChannelMapping(handler, - QLatin1String("Location"), - Qt3DCore::QNodeId::createId(), - QLatin1String("translation"), - "translation", - static_cast<int>(QVariant::Vector3D)); - QVector<ChannelMapping *> channelMappings; - channelMappings.push_back(channelMapping); - - // ... a channel mapper... - auto channelMapper = createChannelMapper(handler, QVector<Qt3DCore::QNodeId>() << channelMapping->peerId()); - - // ...and an animation clip - auto clip = createAnimationClipLoader(handler, QUrl("qrc:/clip1.json")); - - QVector<MappingData> mappingData; - MappingData mapping; - mapping.targetId = channelMapping->targetId(); - mapping.propertyName = channelMapping->propertyName(); // Location - mapping.type = channelMapping->type(); - mapping.channelIndices = QVector<int>() << 0 << 1 << 2; // Location X, Y, Z - mappingData.push_back(mapping); - - QTest::newRow("clip1.json") << handler - << channelMappings - << channelMapper - << clip - << mappingData; - } - - void checkBuildPropertyMappings() - { - // GIVEN - QFETCH(Handler *, handler); - QFETCH(QVector<ChannelMapping *>, channelMappings); - QFETCH(ChannelMapper *, channelMapper); - QFETCH(AnimationClip *, clip); - QFETCH(QVector<MappingData>, expectedMappingData); - - // WHEN - // Build the mapping data for the above configuration - QVector<MappingData> mappingData = buildPropertyMappings(handler, clip, channelMapper); - - // THEN - QCOMPARE(mappingData.size(), expectedMappingData.size()); - for (int i = 0; i < mappingData.size(); ++i) { - const auto mapping = mappingData[i]; - const auto expectedMapping = expectedMappingData[i]; - - QCOMPARE(mapping.targetId, expectedMapping.targetId); - QCOMPARE(mapping.propertyName, expectedMapping.propertyName); - QCOMPARE(mapping.type, expectedMapping.type); - QCOMPARE(mapping.channelIndices.size(), expectedMapping.channelIndices.size()); - for (int j = 0; j < mapping.channelIndices.size(); ++j) { - QCOMPARE(mapping.channelIndices[j], expectedMapping.channelIndices[j]); - } - } - - // Cleanup - delete handler; - } - - void checkBuildPropertyMappings2_data() - { QTest::addColumn<QVector<ChannelMapping *>>("channelMappings"); QTest::addColumn<QVector<ChannelNameAndType>>("channelNamesAndTypes"); QTest::addColumn<QVector<ComponentIndices>>("channelComponentIndices"); @@ -477,7 +406,7 @@ private Q_SLOTS: } } - void checkBuildPropertyMappings2() + void checkBuildPropertyMappings() { // GIVEN QFETCH(QVector<ChannelMapping *>, channelMappings); @@ -1921,6 +1850,18 @@ private Q_SLOTS: QTest::newRow("simple lerp") << handler << lerp->peerId() << expectedIds; } + + { + Handler *handler = new Handler; + + const auto value1 = createClipBlendValue(handler); + const auto clip1Id = Qt3DCore::QNodeId::createId(); + value1->setClipId(clip1Id); + + QVector<Qt3DCore::QNodeId> expectedIds = { value1->peerId() }; + + QTest::newRow("value only") << handler << value1->peerId() << expectedIds; + } } void checkGatherValueNodesToEvaluate() @@ -2477,8 +2418,8 @@ private Q_SLOTS: clip->setSource(QUrl("qrc:/clip3.json")); clip->loadAnimation(); - ComponentIndices expectedResults = { 0, 1, 2, 3, // Rotation - 4, 5, 6, // Location + ComponentIndices expectedResults = { 0, 1, 3, 2, // Rotation (y/z swapped in clip3.json) + 4, 6, 5, // Location (y/z swapped in clip3.json) 7, 8, 9, // Base Color 10, // Metalness 11 }; // Roughness @@ -2507,8 +2448,8 @@ private Q_SLOTS: clip->setSource(QUrl("qrc:/clip3.json")); clip->loadAnimation(); - ComponentIndices expectedResults = { 4, 5, 6, // Location - 0, 1, 2, 3, // Rotation + ComponentIndices expectedResults = { 4, 6, 5, // Location (y/z swapped in clip3.json) + 0, 1, 3, 2, // Rotation (y/z swapped in clip3.json) 7, 8, 9, // Base Color 10, // Metalness 11 }; // Roughness @@ -2537,8 +2478,8 @@ private Q_SLOTS: clip->setSource(QUrl("qrc:/clip3.json")); clip->loadAnimation(); - ComponentIndices expectedResults = { 0, 1, 2, 3, // Rotation - 4, 5, 6, // Location + ComponentIndices expectedResults = { 0, 1, 3, 2, // Rotation (y/z swapped in clip3.json) + 4, 6, 5, // Location (y/z swapped in clip3.json) -1, -1, -1, // Albedo (missing from clip) 10, // Metalness 11 }; // Roughness @@ -2567,8 +2508,8 @@ private Q_SLOTS: clip->setSource(QUrl("qrc:/clip3.json")); clip->loadAnimation(); - ComponentIndices expectedResults = { 4, 5, 6, // Location - 0, 1, 2, 3, // Rotation + ComponentIndices expectedResults = { 4, 6, 5, // Location (y/z swapped in clip3.json) + 0, 1, 3, 2, // Rotation (y/z swapped in clip3.json) -1, -1, -1, // Albedo (missing from clip) 10, // Metalness 11 }; // Roughness diff --git a/tests/auto/animation/channelmapper/tst_channelmapper.cpp b/tests/auto/animation/channelmapper/tst_channelmapper.cpp index 4dcb52aef..446e1a0c5 100644 --- a/tests/auto/animation/channelmapper/tst_channelmapper.cpp +++ b/tests/auto/animation/channelmapper/tst_channelmapper.cpp @@ -30,6 +30,8 @@ #include <qbackendnodetester.h> #include <Qt3DAnimation/private/handler_p.h> #include <Qt3DAnimation/private/channelmapper_p.h> +#include <Qt3DAnimation/private/channelmapping_p.h> +#include <Qt3DAnimation/private/managers_p.h> #include <Qt3DAnimation/qchannelmapper.h> #include <Qt3DAnimation/qchannelmapping.h> #include <Qt3DAnimation/private/qchannelmapper_p.h> @@ -116,13 +118,40 @@ private Q_SLOTS: // WHEN Qt3DAnimation::QChannelMapping mapping; const Qt3DCore::QNodeId mappingId = mapping.id(); - const auto nodeAddedChange = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), &mapping); + Qt3DAnimation::Animation::ChannelMapping *backendMapping + = handler.channelMappingManager()->getOrCreateResource(mappingId); + backendMapping->setHandler(&handler); + simulateInitialization(&mapping, backendMapping); + + auto nodeAddedChange = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), &mapping); nodeAddedChange->setPropertyName("mappings"); backendMapper.sceneChangeEvent(nodeAddedChange); // THEN QCOMPARE(backendMapper.mappingIds().size(), 1); QCOMPARE(backendMapper.mappingIds().first(), mappingId); + QCOMPARE(backendMapper.mappings().size(), 1); + QCOMPARE(backendMapper.mappings().first(), backendMapping); + + // WHEN + Qt3DAnimation::QChannelMapping mapping2; + const Qt3DCore::QNodeId mappingId2 = mapping2.id(); + Qt3DAnimation::Animation::ChannelMapping *backendMapping2 + = handler.channelMappingManager()->getOrCreateResource(mappingId2); + backendMapping2->setHandler(&handler); + simulateInitialization(&mapping2, backendMapping2); + + nodeAddedChange = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), &mapping2); + nodeAddedChange->setPropertyName("mappings"); + backendMapper.sceneChangeEvent(nodeAddedChange); + + // THEN + QCOMPARE(backendMapper.mappingIds().size(), 2); + QCOMPARE(backendMapper.mappingIds().first(), mappingId); + QCOMPARE(backendMapper.mappingIds().last(), mappingId2); + QCOMPARE(backendMapper.mappings().size(), 2); + QCOMPARE(backendMapper.mappings().first(), backendMapping); + QCOMPARE(backendMapper.mappings().last(), backendMapping2); // WHEN const auto nodeRemovedChange = Qt3DCore::QPropertyNodeRemovedChangePtr::create(Qt3DCore::QNodeId(), &mapping); @@ -130,7 +159,10 @@ private Q_SLOTS: backendMapper.sceneChangeEvent(nodeRemovedChange); // THEN - QCOMPARE(backendMapper.mappingIds().size(), 0); + QCOMPARE(backendMapper.mappingIds().size(), 1); + QCOMPARE(backendMapper.mappingIds().first(), mappingId2); + QCOMPARE(backendMapper.mappings().size(), 1); + QCOMPARE(backendMapper.mappings().first(), backendMapping2); } }; diff --git a/tests/auto/animation/clipblendvalue/tst_clipblendvalue.cpp b/tests/auto/animation/clipblendvalue/tst_clipblendvalue.cpp index 6fe2846b8..fcbc167ca 100644 --- a/tests/auto/animation/clipblendvalue/tst_clipblendvalue.cpp +++ b/tests/auto/animation/clipblendvalue/tst_clipblendvalue.cpp @@ -137,8 +137,7 @@ private Q_SLOTS: QVector<Qt3DCore::QNodeId> actualIds = clipNode.currentDependencyIds(); // THEN - QCOMPARE(actualIds.size(), 1); - QCOMPARE(actualIds[0], clipId); + QCOMPARE(actualIds.size(), 0); // WHEN auto anotherClipId = Qt3DCore::QNodeId::createId(); @@ -146,8 +145,7 @@ private Q_SLOTS: actualIds = clipNode.currentDependencyIds(); // THEN - QCOMPARE(actualIds.size(), 1); - QCOMPARE(actualIds[0], anotherClipId); + QCOMPARE(actualIds.size(), 0); } void checkDuration() diff --git a/tests/auto/animation/findrunningclipanimatorsjob/clip1.json b/tests/auto/animation/findrunningclipanimatorsjob/clip1.json new file mode 100644 index 000000000..a2ad365a8 --- /dev/null +++ b/tests/auto/animation/findrunningclipanimatorsjob/clip1.json @@ -0,0 +1,114 @@ +{ + "animations": [ + { + "animationName": "CubeAction", + "channels": [ + { + "channelComponents": [ + { + "channelComponentName": "Location X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 5.0 + ], + "leftHandle": [ + 1.4985717137654622, + 5.0 + ], + "rightHandle": [ + 3.4180949529012046, + 5.0 + ] + } + ] + }, + { + "channelComponentName": "Location Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Location Z", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + } + ], + "channelName": "Location" + } + ] + } + ] +} + diff --git a/tests/auto/animation/findrunningclipanimatorsjob/findrunningclipanimatorsjob.pro b/tests/auto/animation/findrunningclipanimatorsjob/findrunningclipanimatorsjob.pro new file mode 100644 index 000000000..f81b95dcd --- /dev/null +++ b/tests/auto/animation/findrunningclipanimatorsjob/findrunningclipanimatorsjob.pro @@ -0,0 +1,15 @@ +TEMPLATE = app + +TARGET = tst_findrunningclipanimatorsjob + +QT += core-private 3dcore 3dcore-private 3danimation 3danimation-private testlib + +CONFIG += testcase + +SOURCES += \ + tst_findrunningclipanimatorsjob.cpp + +include(../../core/common/common.pri) + +RESOURCES += \ + findrunningclipanimatorsjob.qrc diff --git a/tests/auto/animation/findrunningclipanimatorsjob/findrunningclipanimatorsjob.qrc b/tests/auto/animation/findrunningclipanimatorsjob/findrunningclipanimatorsjob.qrc new file mode 100644 index 000000000..72234ec64 --- /dev/null +++ b/tests/auto/animation/findrunningclipanimatorsjob/findrunningclipanimatorsjob.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/"> + <file>clip1.json</file> + </qresource> +</RCC> diff --git a/tests/auto/animation/findrunningclipanimatorsjob/tst_findrunningclipanimatorsjob.cpp b/tests/auto/animation/findrunningclipanimatorsjob/tst_findrunningclipanimatorsjob.cpp new file mode 100644 index 000000000..79d18b7cf --- /dev/null +++ b/tests/auto/animation/findrunningclipanimatorsjob/tst_findrunningclipanimatorsjob.cpp @@ -0,0 +1,204 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <Qt3DAnimation/qanimationcliploader.h> +#include <Qt3DAnimation/qclipanimator.h> +#include <Qt3DAnimation/qchannelmapper.h> +#include <Qt3DAnimation/qchannelmapping.h> +#include <Qt3DAnimation/private/clipanimator_p.h> +#include <Qt3DAnimation/private/channelmapper_p.h> +#include <Qt3DAnimation/private/channelmapping_p.h> +#include <Qt3DAnimation/private/findrunningclipanimatorsjob_p.h> +#include <Qt3DAnimation/private/handler_p.h> +#include <Qt3DAnimation/private/managers_p.h> +#include <Qt3DCore/private/qnode_p.h> +#include <Qt3DCore/private/qscene_p.h> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/private/qbackendnode_p.h> +#include <qbackendnodetester.h> +#include <testpostmanarbiter.h> + +using namespace Qt3DAnimation::Animation; + +Q_DECLARE_METATYPE(Qt3DAnimation::Animation::Handler*) +Q_DECLARE_METATYPE(QVector<Qt3DAnimation::Animation::HClipAnimator>) + +typedef QHash<ClipAnimator*, QVector<Qt3DAnimation::Animation::MappingData>> MappingDataResults; +Q_DECLARE_METATYPE(MappingDataResults) + +class tst_FindRunningClipAnimatorsJob: public Qt3DCore::QBackendNodeTester +{ + Q_OBJECT +public: + ChannelMapping *createChannelMapping(Handler *handler, + const QString &channelName, + const Qt3DCore::QNodeId targetId, + const QString &property, + const char *propertyName, + int type) + { + 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); + channelMapping->setChannelName(channelName); + channelMapping->setType(type); + return channelMapping; + } + + ChannelMapper *createChannelMapper(Handler *handler, + const QVector<Qt3DCore::QNodeId> &mappingIds) + { + auto channelMapperId = Qt3DCore::QNodeId::createId(); + ChannelMapper *channelMapper = handler->channelMapperManager()->getOrCreateResource(channelMapperId); + setPeerId(channelMapper, channelMapperId); + channelMapper->setHandler(handler); + channelMapper->setMappingIds(mappingIds); + return channelMapper; + } + + AnimationClip *createAnimationClipLoader(Handler *handler, + const QUrl &source) + { + auto clipId = Qt3DCore::QNodeId::createId(); + AnimationClip *clip = handler->animationClipLoaderManager()->getOrCreateResource(clipId); + setPeerId(clip, clipId); + clip->setHandler(handler); + clip->setDataType(AnimationClip::File); + clip->setSource(source); + clip->loadAnimation(); + return clip; + } + + ClipAnimator *createClipAnimator(Handler *handler, + qint64 globalStartTimeNS, + int loops) + { + auto animatorId = Qt3DCore::QNodeId::createId(); + ClipAnimator *animator = handler->clipAnimatorManager()->getOrCreateResource(animatorId); + setPeerId(animator, animatorId); + animator->setHandler(handler); + animator->setStartTime(globalStartTimeNS); + animator->setLoops(loops); + return animator; + } + +private Q_SLOTS: + void checkJob_data() + { + QTest::addColumn<Handler *>("handler"); + QTest::addColumn<QVector<HClipAnimator>>("dirtyClipAnimators"); + QTest::addColumn<MappingDataResults>("expectedResults"); + + Handler *handler; + AnimationClip *clip; + ClipAnimator *animator; + QVector<HClipAnimator> dirtyClipAnimators; + ChannelMapper *channelMapper; + MappingDataResults expectedResults; + + { + handler = new Handler(); + clip = createAnimationClipLoader(handler, QUrl("qrc:/clip1.json")); + + const qint64 globalStartTimeNS = 0; + const int loops = 1; + animator = createClipAnimator(handler, globalStartTimeNS, loops); + animator->setClipId(clip->peerId()); + dirtyClipAnimators = (QVector<HClipAnimator>() + << handler->clipAnimatorManager()->getOrAcquireHandle(animator->peerId())); + + auto channelMapping = createChannelMapping(handler, + QLatin1String("Location"), + Qt3DCore::QNodeId::createId(), + QLatin1String("translation"), + "translation", + static_cast<int>(QVariant::Vector3D)); + QVector<ChannelMapping *> channelMappings; + channelMappings.push_back(channelMapping); + + channelMapper = createChannelMapper(handler, QVector<Qt3DCore::QNodeId>() << channelMapping->peerId()); + animator->setMapperId(channelMapper->peerId()); + animator->setRunning(true); // Has to be marked as running for the job to process it + + const ComponentIndices locationIndices = { 0, 1, 2 }; + MappingData expectedMapping; + expectedMapping.targetId = channelMapping->targetId(); + expectedMapping.propertyName = channelMapping->propertyName(); + expectedMapping.type = channelMapping->type(); + expectedMapping.channelIndices = locationIndices; + expectedResults.insert(animator, QVector<MappingData>() << expectedMapping); + + QTest::newRow("single mapping") + << handler + << dirtyClipAnimators + << expectedResults; + } + } + + void checkJob() + { + // GIVEN + QFETCH(Handler *, handler); + QFETCH(QVector<HClipAnimator>, dirtyClipAnimators); + QFETCH(MappingDataResults, expectedResults); + FindRunningClipAnimatorsJob job; + + // WHEN + job.setHandler(handler); + job.setDirtyClipAnimators(dirtyClipAnimators); + job.run(); + + // THEN - check the resulting MappingData on the animator matches the expected results + for (const auto &dirtyClipAnimator : dirtyClipAnimators) { + const auto animator = handler->clipAnimatorManager()->data(dirtyClipAnimator); + const QVector<MappingData> actualMappingData = animator->mappingData(); + const QVector<MappingData> expectedMappingData = expectedResults[animator]; + + QCOMPARE(expectedMappingData.size(), actualMappingData.size()); + for (int i = 0; i < actualMappingData.size(); ++i) { + QCOMPARE(expectedMappingData[i].targetId, actualMappingData[i].targetId); + QCOMPARE(expectedMappingData[i].type, actualMappingData[i].type); + QVERIFY(qstrcmp(expectedMappingData[i].propertyName, actualMappingData[i].propertyName) == 0); + QCOMPARE(expectedMappingData[i].channelIndices.size(), actualMappingData[i].channelIndices.size()); + + for (int j = 0; j < actualMappingData[i].channelIndices.size(); ++j) { + QCOMPARE(expectedMappingData[i].channelIndices[j], actualMappingData[i].channelIndices[j]); + } + } + } + } +}; + +QTEST_APPLESS_MAIN(tst_FindRunningClipAnimatorsJob) + +#include "tst_findrunningclipanimatorsjob.moc" diff --git a/tests/auto/render/meshfunctors/tst_meshfunctors.cpp b/tests/auto/render/meshfunctors/tst_meshfunctors.cpp index bf5f0d55f..e2877b24b 100644 --- a/tests/auto/render/meshfunctors/tst_meshfunctors.cpp +++ b/tests/auto/render/meshfunctors/tst_meshfunctors.cpp @@ -27,8 +27,11 @@ ****************************************************************************/ #include <QtTest/QtTest> +#include <Qt3DCore/qcomponent.h> #include <Qt3DRender/qgeometryfactory.h> #include <Qt3DRender/qgeometry.h> +#include <Qt3DRender/qmesh.h> +#include <Qt3DRender/private/qmesh_p.h> class MeshFunctorA : public Qt3DRender::QGeometryFactory { @@ -117,6 +120,31 @@ private Q_SLOTS: QVERIFY(*functorB == *functorB); QVERIFY(*functorASub == *functorASub); } + + void checkMeshFunctorEquality() + { + // GIVEN + const Qt3DRender::MeshFunctor functorA(QUrl::fromLocalFile(QLatin1String("/foo")), + QLatin1String("bar")); + const Qt3DRender::MeshFunctor functorB(QUrl::fromLocalFile(QLatin1String("/foo")), + QLatin1String("baz")); + const Qt3DRender::MeshFunctor functorC(QUrl::fromLocalFile(QLatin1String("/baz")), + QLatin1String("bar")); + const Qt3DRender::MeshFunctor functorD(QUrl::fromLocalFile(QLatin1String("/foo")), + QLatin1String("bar")); + + // WHEN + const bool selfEquality = (functorA == functorA); + const bool sameSource = (functorA == functorB); + const bool sameMeshName = (functorA == functorC); + const bool perfectMatch = (functorA == functorD); + + // THEN + QCOMPARE(selfEquality, true); + QCOMPARE(sameSource, false); + QCOMPARE(sameMeshName, false); + QCOMPARE(perfectMatch, true); + } }; QTEST_APPLESS_MAIN(tst_MeshFunctors) diff --git a/tests/manual/bigscene-cpp/entity.cpp b/tests/manual/bigscene-cpp/entity.cpp index 9a4ecae3b..876a2d171 100644 --- a/tests/manual/bigscene-cpp/entity.cpp +++ b/tests/manual/bigscene-cpp/entity.cpp @@ -51,22 +51,21 @@ #include "entity.h" #include <Qt3DExtras/QCylinderMesh> -#include <Qt3DExtras/QPhongMaterial> +#include <Qt3DRender/QMaterial> +#include <Qt3DRender/QParameter> #include <Qt3DCore/QTransform> #include <QMatrix4x4> -Entity::Entity(Qt3DCore::QNode *parent) +Entity::Entity(Qt3DRender::QEffect *effect, Qt3DCore::QNode *parent) : QEntity(parent) , m_transform(new Qt3DCore::QTransform()) - , m_mesh(new Qt3DExtras::QCylinderMesh()) - , m_material(new Qt3DExtras::QPhongMaterial()) + , m_material(new Qt3DRender::QMaterial()) + , m_diffuseColorParam(new Qt3DRender::QParameter()) { - m_mesh->setRings(50.0f); - m_mesh->setSlices(30.0f); - m_mesh->setRadius(2.5f); - m_mesh->setLength(5.0f); + m_diffuseColorParam->setName(QLatin1String("kd")); + m_material->addParameter(m_diffuseColorParam); + m_material->setEffect(effect); - addComponent(m_mesh); addComponent(m_transform); addComponent(m_material); } @@ -97,26 +96,30 @@ QVector3D Entity::position() const QColor Entity::diffuseColor() const { - return m_material->diffuse(); + return m_diffuseColorParam->value().value<QColor>(); } void Entity::setTheta(float theta) { - if (m_theta == theta) + if (qFuzzyCompare(m_theta, theta)) return; m_theta = theta; + const bool wasBlocked = blockNotifications(true); emit thetaChanged(theta); + blockNotifications(wasBlocked); updateTransform(); } void Entity::setPhi(float phi) { - if (m_phi == phi) + if (qFuzzyCompare(m_phi, phi)) return; m_phi = phi; + const bool wasBlocked = blockNotifications(true); emit phiChanged(phi); + blockNotifications(wasBlocked); updateTransform(); } @@ -132,9 +135,11 @@ void Entity::setPosition(QVector3D position) void Entity::setDiffuseColor(QColor diffuseColor) { - if (m_material->diffuse() == diffuseColor) + if (m_diffuseColorParam->value().value<QColor>() == diffuseColor) return; - m_material->setDiffuse(diffuseColor); + m_diffuseColorParam->setValue(QVariant::fromValue(diffuseColor)); + const bool wasBlocked = blockNotifications(true); emit diffuseColorChanged(diffuseColor); + blockNotifications(wasBlocked); } diff --git a/tests/manual/bigscene-cpp/entity.h b/tests/manual/bigscene-cpp/entity.h index 04dcbbcb3..656511cdc 100644 --- a/tests/manual/bigscene-cpp/entity.h +++ b/tests/manual/bigscene-cpp/entity.h @@ -61,9 +61,11 @@ namespace Qt3DCore { class QTransform; } -namespace Qt3DExtras { -class QCylinderMesh; -class QPhongMaterial; +namespace Qt3DRender { +class QEffect; +class QGeometryRenderer; +class QMaterial; +class QParameter; } QT_END_NAMESPACE @@ -77,7 +79,7 @@ class Entity : public Qt3DCore::QEntity Q_PROPERTY(QColor diffuseColor READ diffuseColor WRITE setDiffuseColor NOTIFY diffuseColorChanged) public: - Entity(Qt3DCore::QNode *parent = 0); + Entity(Qt3DRender::QEffect *effect, Qt3DCore::QNode *parent = 0); float theta() const; float phi() const; @@ -101,8 +103,8 @@ private: private: Qt3DCore::QTransform *m_transform; - Qt3DExtras::QCylinderMesh *m_mesh; - Qt3DExtras::QPhongMaterial *m_material; + Qt3DRender::QMaterial *m_material; + Qt3DRender::QParameter *m_diffuseColorParam; float m_theta; float m_phi; QVector3D m_position; diff --git a/tests/manual/bigscene-cpp/main.cpp b/tests/manual/bigscene-cpp/main.cpp index 791aeb19d..ef296e04d 100644 --- a/tests/manual/bigscene-cpp/main.cpp +++ b/tests/manual/bigscene-cpp/main.cpp @@ -81,6 +81,17 @@ int main(int ac, char **av) QEntity *root = new QEntity(); + // Mesh + auto *mesh = new Qt3DExtras::QCylinderMesh(root); + mesh->setRings(50.0f); + mesh->setSlices(30.0f); + mesh->setRadius(2.5f); + mesh->setLength(5.0f); + + // Material + auto phongMaterial = new Qt3DExtras::QPhongMaterial(root); + auto effect = phongMaterial->effect(); + // Camera QCamera *cameraEntity = view.camera(); cameraEntity->lens()->setPerspectiveProjection(45.0f, 16.0f/9.0f, 0.1f, 1000.0f); @@ -92,17 +103,20 @@ int main(int ac, char **av) Qt3DExtras::QFirstPersonCameraController *camController = new Qt3DExtras::QFirstPersonCameraController(root); camController->setCamera(cameraEntity); - const float radius = 100.0f; + const double radius = 100.0; const int max = 1000; - const float det = 1.0f / max; + const double det = 1.0 / max; // Scene for (int i = 0; i < max; i++) { - Entity *e = new Entity(); - const float angle = M_PI * 2.0f * i * det * 10.; - - e->setDiffuseColor(QColor(qFabs(qCos(angle)) * 255, 204, 75)); - e->setPosition(QVector3D(radius * qCos(angle), -200.* i * det, radius * qSin(angle))); + Entity *e = new Entity(effect, root); + e->addComponent(mesh); + const double angle = M_PI * 2.0 * double(i) * det * 10.; + + e->setDiffuseColor(QColor(int(qFabs(qCos(angle)) * 255.0), 204, 75)); + e->setPosition(QVector3D(float(radius * qCos(angle)), + float(-200.0 * i * det), + float(radius * qSin(angle)))); e->setTheta(30.0f * i); e->setPhi(45.0f * i); @@ -119,8 +133,6 @@ int main(int ac, char **av) animZ->setEndValue(QVariant::fromValue((i + 1) * 380.0f)); animZ->setLoopCount(-1); animZ->start(); - - e->setParent(root); } view.setRootEntity(root); |