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 | |
parent | 18ce3e68e6db896e9c01cf4df0dd7e9fa714b37c (diff) | |
parent | 764b715b5f682ddb1bdb52f67b5a35d85af7ccf1 (diff) |
Merge remote-tracking branch 'origin/5.10' into dev
Change-Id: I2d373d538df3a65ac2d41238e5c6a214a151be68
84 files changed, 2824 insertions, 806 deletions
diff --git a/dist/changes-5.9.2 b/dist/changes-5.9.2 new file mode 100644 index 000000000..d8e1cb493 --- /dev/null +++ b/dist/changes-5.9.2 @@ -0,0 +1,39 @@ +Qt 5.9.2 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.9.0. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + +http://doc.qt.io/qt-5/index.html + +The Qt version 5.9 series is binary compatible with the 5.8.x series. +Applications compiled for 5.8 will continue to run with 5.9. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + +https://bugreports.qt.io/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* Qt 5.9.2 Changes * +**************************************************************************** + +- Don't crash when removing clip animators +- Case-insensitive matching of DDS/PKM files [QTBUG-61760] +- Fix crash when using a single key frame +- Fix rendering glitches with 2D text +- Respect render target selector when reading pixel data back [QTBUG-61547] +- Fix memory leaks when loading multiple scenes with assimp [QTBUG-61856] +- Fix updates of some render states +- Fix sorting of render commands [QTBUG-60183] +- Fix assert crash when updating 3D content of a Scene3D item [QTBUG-60613] +- Fix crash when loading multiple assimp scenes +- Fix shader compilation on Rasp-Pi [QTBUG-59349] +- Don't deref null VAOs [QTBUG-59349] +- Respect byteStride in QAttribute +- Don't crash when rapidly changing textures +- Ignore ill-formed faces in OBJ files +- Many performance and memory use reduction changes diff --git a/examples/qt3d/planets-qml/images/solarsystemscope/qt_attribution.json b/examples/qt3d/planets-qml/images/solarsystemscope/qt_attribution.json index 35e9afe39..9d32e541d 100644 --- a/examples/qt3d/planets-qml/images/solarsystemscope/qt_attribution.json +++ b/examples/qt3d/planets-qml/images/solarsystemscope/qt_attribution.json @@ -6,7 +6,7 @@ "Description": "Solar System Scope provides high quality, free to use textures for objects in the solar system.", "QtUsage": "Used in Qt 3D planets-qml example.", - "Homepage": "www.solarsystemscope.com/textures", + "Homepage": "https://www.solarsystemscope.com/textures", "License": "Creative Commons Attribution 4.0", "LicenseId": "CC-BY-4.0", "LicenseFile": "license.txt", diff --git a/examples/qt3d/scene2d/main.qml b/examples/qt3d/scene2d/main.qml index 35b8f3eb6..ceaac3b34 100644 --- a/examples/qt3d/scene2d/main.qml +++ b/examples/qt3d/scene2d/main.qml @@ -97,10 +97,10 @@ Entity { PhongMaterial { id: logoMaterial - ambient: Qt.rgba( logoControls.colorR/255, + diffuse: Qt.rgba( logoControls.colorR/255, logoControls.colorG/255, logoControls.colorB/255, 1.0 ) - diffuse: Qt.rgba( 0.1, 0.1, 0.1, 0.5 ) + ambient: Qt.rgba( 0.1, 0.1, 0.1, 1.0 ) shininess: logoControls.shininess } diff --git a/examples/qt3d/widgets-scene3d/main.cpp b/examples/qt3d/widgets-scene3d/main.cpp index d306ed7b8..38eb46833 100644 --- a/examples/qt3d/widgets-scene3d/main.cpp +++ b/examples/qt3d/widgets-scene3d/main.cpp @@ -1,12 +1,22 @@ /**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are diff --git a/src/animation/backend/animationclip.cpp b/src/animation/backend/animationclip.cpp index daee4008d..e8f8f4552 100644 --- a/src/animation/backend/animationclip.cpp +++ b/src/animation/backend/animationclip.cpp @@ -41,6 +41,7 @@ #include <Qt3DAnimation/private/qanimationcliploader_p.h> #include <Qt3DAnimation/private/animationlogging_p.h> #include <Qt3DAnimation/private/managers_p.h> +#include <Qt3DAnimation/private/gltfimporter_p.h> #include <Qt3DRender/private/qurlhelper_p.h> #include <Qt3DCore/qpropertyupdatedchange.h> @@ -209,28 +210,43 @@ void AnimationClip::loadAnimationFromUrl() return; } - QByteArray animationData = file.readAll(); - QJsonDocument document = QJsonDocument::fromJson(animationData); - QJsonObject rootObject = document.object(); - - // TODO: Allow loading of a named animation from a file containing many - QJsonArray animationsArray = rootObject[QLatin1String("animations")].toArray(); - qCDebug(Jobs) << "Found" << animationsArray.size() << "animations:"; - for (int i = 0; i < animationsArray.size(); ++i) { - QJsonObject animation = animationsArray.at(i).toObject(); - qCDebug(Jobs) << "Animation Name:" << animation[QLatin1String("animationName")].toString(); - } + // TODO: Convert to plugins + // Load glTF or "native" + if (filePath.endsWith(QLatin1String("gltf"))) { + qCDebug(Jobs) << "Loading glTF animation from" << filePath; + GLTFImporter gltf; + gltf.load(&file); + // TODO: Allow loading of a named animation from a file containing many + m_name = gltf.animations().first().name; + m_channels = gltf.createAnimationData(); + } else if (filePath.endsWith(QLatin1String("json"))) { + // Native format + QByteArray animationData = file.readAll(); + QJsonDocument document = QJsonDocument::fromJson(animationData); + QJsonObject rootObject = document.object(); + + // TODO: Allow loading of a named animation from a file containing many + QJsonArray animationsArray = rootObject[QLatin1String("animations")].toArray(); + qCDebug(Jobs) << "Found" << animationsArray.size() << "animations:"; + for (int i = 0; i < animationsArray.size(); ++i) { + QJsonObject animation = animationsArray.at(i).toObject(); + qCDebug(Jobs) << "Animation Name:" << animation[QLatin1String("animationName")].toString(); + } - // For now just load the first animation - // TODO: Allow loading a named animation from within the file analogous to QMesh - QJsonObject animation = animationsArray.at(0).toObject(); - m_name = animation[QLatin1String("animationName")].toString(); - QJsonArray channelsArray = animation[QLatin1String("channels")].toArray(); - const int channelCount = channelsArray.size(); - m_channels.resize(channelCount); - for (int i = 0; i < channelCount; ++i) { - const QJsonObject group = channelsArray.at(i).toObject(); - m_channels[i].read(group); + // For now just load the first animation + // TODO: Allow loading a named animation from within the file analogous to QMesh + QJsonObject animation = animationsArray.at(0).toObject(); + m_name = animation[QLatin1String("animationName")].toString(); + QJsonArray channelsArray = animation[QLatin1String("channels")].toArray(); + const int channelCount = channelsArray.size(); + m_channels.resize(channelCount); + for (int i = 0; i < channelCount; ++i) { + const QJsonObject group = channelsArray.at(i).toObject(); + m_channels[i].read(group); + } + } else { + qWarning() << "Unknown animation clip type. Please use json or glTF 2.0"; + setStatus(QAnimationClipLoader::Error); } } 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; diff --git a/src/animation/backend/animationutils_p.h b/src/animation/backend/animationutils_p.h index 4bd3ee64b..d8127d8af 100644 --- a/src/animation/backend/animationutils_p.h +++ b/src/animation/backend/animationutils_p.h @@ -54,6 +54,8 @@ #include <Qt3DCore/qnodeid.h> #include <Qt3DCore/qscenechange.h> +#include <QtCore/qdebug.h> + QT_BEGIN_NAMESPACE namespace Qt3DAnimation { @@ -89,11 +91,25 @@ struct MappingData ComponentIndices channelIndices; }; +#ifndef QT_NO_DEBUG_STREAM +inline QDebug operator<<(QDebug dbg, const MappingData &mapping) +{ + QDebugStateSaver saver(dbg); + dbg << "targetId =" << mapping.targetId << endl + << "jointIndex =" << mapping.jointIndex << endl + << "jointTransformComponent: " << mapping.jointTransformComponent << endl + << "propertyName:" << mapping.propertyName << endl + << "channelIndices:" << mapping.channelIndices; + return dbg; +} +#endif + struct AnimatorEvaluationData { - double globalTime; - double startTime; + double elapsedTime; + double currentTime; int loopCount; + int currentLoop; double playbackRate; }; @@ -142,14 +158,15 @@ struct AnimationCallbackAndValue }; template<typename Animator> -AnimatorEvaluationData evaluationDataForAnimator(Animator animator, Clock* clock, qint64 globalTime) +AnimatorEvaluationData evaluationDataForAnimator(Animator animator, Clock* clock, qint64 nsSincePreviousFrame) { AnimatorEvaluationData data; data.loopCount = animator->loops(); + data.currentLoop = animator->currentLoop(); data.playbackRate = clock != nullptr ? clock->playbackRate() : 1.0; // Convert global time from nsec to sec - data.startTime = double(animator->startTime()) / 1.0e9; - data.globalTime = double(globalTime) / 1.0e9; + data.elapsedTime = double(nsSincePreviousFrame) / 1.0e9; + data.currentTime = animator->lastLocalTime(); return data; } @@ -212,12 +229,12 @@ Q_AUTOTEST_EXPORT QVector<ComponentIndices> assignChannelComponentIndices(const QVector<ChannelNameAndType> &namesAndTypes); Q_AUTOTEST_EXPORT -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); Q_AUTOTEST_EXPORT -double phaseFromGlobalTime(double t_global, double t_start_global, +double phaseFromElapsedTime(double t_current_local, double t_elapsed_global, double playbackRate, double duration, int loopCount, int ¤tLoop); diff --git a/src/animation/backend/backend.pri b/src/animation/backend/backend.pri index ee36a98ea..cc1104102 100644 --- a/src/animation/backend/backend.pri +++ b/src/animation/backend/backend.pri @@ -28,7 +28,8 @@ HEADERS += \ $$PWD/clipblendvalue_p.h \ $$PWD/animationclip_p.h \ $$PWD/clock_p.h \ - $$PWD/skeleton_p.h + $$PWD/skeleton_p.h \ + $$PWD/gltfimporter_p.h SOURCES += \ $$PWD/handler.cpp \ @@ -54,4 +55,5 @@ SOURCES += \ $$PWD/clipblendvalue.cpp \ $$PWD/animationclip.cpp \ $$PWD/clock.cpp \ - $$PWD/skeleton.cpp + $$PWD/skeleton.cpp \ + $$PWD/gltfimporter.cpp diff --git a/src/animation/backend/blendedclipanimator.cpp b/src/animation/backend/blendedclipanimator.cpp index ec0a5027a..1487d6c3e 100644 --- a/src/animation/backend/blendedclipanimator.cpp +++ b/src/animation/backend/blendedclipanimator.cpp @@ -48,7 +48,8 @@ namespace Animation { BlendedClipAnimator::BlendedClipAnimator() : BackendNode(ReadWrite) , m_running(false) - , m_startGlobalTime(0) + , m_lastGlobalTimeNS(0) + , m_lastLocalTime(0.0) , m_currentLoop(0) , m_loops(1) { @@ -66,6 +67,26 @@ void BlendedClipAnimator::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeB setDirty(Handler::BlendedClipAnimatorDirty); } +double BlendedClipAnimator::lastLocalTime() const +{ + return m_lastLocalTime; +} + +void BlendedClipAnimator::setLastLocalTime(double lastLocalTime) +{ + m_lastLocalTime = lastLocalTime; +} + +void BlendedClipAnimator::setLastGlobalTimeNS(const qint64 &lastGlobalTimeNS) +{ + m_lastGlobalTimeNS = lastGlobalTimeNS; +} + +qint64 BlendedClipAnimator::nsSincePreviousFrame(qint64 currentGlobalTimeNS) +{ + return currentGlobalTimeNS - m_lastGlobalTimeNS; +} + void BlendedClipAnimator::cleanup() { setEnabled(false); @@ -74,7 +95,8 @@ void BlendedClipAnimator::cleanup() m_mapperId = Qt3DCore::QNodeId(); m_clockId = Qt3DCore::QNodeId(); m_running = false; - m_startGlobalTime = 0; + m_lastGlobalTimeNS = 0; + m_lastLocalTime = 0.0; m_currentLoop = 0; m_loops = 1; } @@ -124,6 +146,7 @@ void BlendedClipAnimator::sendCallbacks(const QVector<AnimationCallbackAndValue> } } + Qt3DCore::QNodeId BlendedClipAnimator::blendTreeRootId() const { return m_blendTreeRootId; diff --git a/src/animation/backend/blendedclipanimator_p.h b/src/animation/backend/blendedclipanimator_p.h index 52ebdcc30..79c6d8c43 100644 --- a/src/animation/backend/blendedclipanimator_p.h +++ b/src/animation/backend/blendedclipanimator_p.h @@ -79,8 +79,7 @@ public: void setClockId(Qt3DCore::QNodeId clockId); void setRunning(bool running); - void setStartTime(qint64 globalTime) { m_startGlobalTime = globalTime; } - qint64 startTime() const { return m_startGlobalTime; } + void setStartTime(qint64 globalTime) { m_lastGlobalTimeNS = globalTime; } void setLoops(int loops) { m_loops = loops; } int loops() const { return m_loops; } @@ -96,6 +95,12 @@ public: void animationClipMarkedDirty() { setDirty(Handler::BlendedClipAnimatorDirty); } + qint64 nsSincePreviousFrame(qint64 currentGlobalTimeNS); + void setLastGlobalTimeNS(const qint64 &lastGlobalTimeNS); + + double lastLocalTime() const; + void setLastLocalTime(double lastLocalTime); + private: void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; Qt3DCore::QNodeId m_blendTreeRootId; @@ -103,7 +108,9 @@ private: Qt3DCore::QNodeId m_clockId; bool m_running; - qint64 m_startGlobalTime; + qint64 m_lastGlobalTimeNS; + double m_lastLocalTime; + int m_currentLoop; int m_loops; diff --git a/src/animation/backend/clipanimator.cpp b/src/animation/backend/clipanimator.cpp index 568e2dbb0..21c08b80a 100644 --- a/src/animation/backend/clipanimator.cpp +++ b/src/animation/backend/clipanimator.cpp @@ -56,7 +56,8 @@ ClipAnimator::ClipAnimator() , m_clockId() , m_running(false) , m_loops(1) - , m_startGlobalTime(0) + , m_lastGlobalTimeNS(0) + , m_lastLocalTime(0.0) , m_mappingData() , m_currentLoop(0) { @@ -162,6 +163,26 @@ void ClipAnimator::sendCallbacks(const QVector<AnimationCallbackAndValue> &callb } } +qint64 ClipAnimator::nsSincePreviousFrame(qint64 currentGlobalTimeNS) +{ + return currentGlobalTimeNS - m_lastGlobalTimeNS; +} + +void ClipAnimator::setLastGlobalTimeNS(qint64 lastGlobalTimeNS) +{ + m_lastGlobalTimeNS = lastGlobalTimeNS; +} + +double ClipAnimator::lastLocalTime() const +{ + return m_lastLocalTime; +} + +void ClipAnimator::setLastLocalTime(double lastLocalTime) +{ + m_lastLocalTime = lastLocalTime; +} + } // namespace Animation } // namespace Qt3DAnimation diff --git a/src/animation/backend/clipanimator_p.h b/src/animation/backend/clipanimator_p.h index ca05afdd3..4c33819f5 100644 --- a/src/animation/backend/clipanimator_p.h +++ b/src/animation/backend/clipanimator_p.h @@ -86,8 +86,7 @@ public: void setMappingData(const QVector<MappingData> &mappingData) { m_mappingData = mappingData; } QVector<MappingData> mappingData() const { return m_mappingData; } - void setStartTime(qint64 globalTime) { m_startGlobalTime = globalTime; } - qint64 startTime() const { return m_startGlobalTime; } + void setStartTime(qint64 globalTime) { m_lastGlobalTimeNS = globalTime; } int currentLoop() const { return m_currentLoop; } void setCurrentLoop(int currentLoop) { m_currentLoop = currentLoop; } @@ -100,6 +99,12 @@ public: void setFormatIndices(const ComponentIndices &formatIndices) { m_formatIndices = formatIndices; } ComponentIndices formatIndices() const { return m_formatIndices; } + qint64 nsSincePreviousFrame(qint64 currentGlobalTimeNS); + void setLastGlobalTimeNS(qint64 lastGlobalTimeNS); + + double lastLocalTime() const; + void setLastLocalTime(double lastLocalTime); + private: void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; @@ -110,7 +115,8 @@ private: int m_loops; // Working state - qint64 m_startGlobalTime; + qint64 m_lastGlobalTimeNS; + double m_lastLocalTime; QVector<MappingData> m_mappingData; int m_currentLoop; diff --git a/src/animation/backend/evaluateblendclipanimatorjob.cpp b/src/animation/backend/evaluateblendclipanimatorjob.cpp index be05f7ec0..3cde7b32f 100644 --- a/src/animation/backend/evaluateblendclipanimatorjob.cpp +++ b/src/animation/backend/evaluateblendclipanimatorjob.cpp @@ -51,6 +51,8 @@ namespace Animation { EvaluateBlendClipAnimatorJob::EvaluateBlendClipAnimatorJob() : Qt3DCore::QAspectJob() + , m_currentGlobalTime(0.0) + , m_lastGlobalTime(0.0) { SET_JOB_RUN_STAT_TYPE(this, JobTypes::EvaluateBlendClipAnimator, 0); } @@ -62,7 +64,15 @@ void EvaluateBlendClipAnimatorJob::run() // TODO: We should be able to cache this for each blend animator and only // update when a node indicates its dependencies have changed as a result // of blend factors changing + BlendedClipAnimator *blendedClipAnimator = m_handler->blendedClipAnimatorManager()->data(m_blendClipAnimatorHandle); + Q_ASSERT(blendedClipAnimator); + if (!blendedClipAnimator->isRunning()) + return; + + qint64 globalTimeNS = m_handler->simulationTime(); + qint64 nsSincePreviousFrame = blendedClipAnimator->nsSincePreviousFrame(globalTimeNS); + Qt3DCore::QNodeId blendTreeRootId = blendedClipAnimator->blendTreeRootId(); const QVector<Qt3DCore::QNodeId> valueNodeIdsToEvaluate = gatherValueNodesToEvaluate(m_handler, blendTreeRootId); @@ -75,15 +85,12 @@ void EvaluateBlendClipAnimatorJob::run() Clock *clock = m_handler->clockManager()->lookupResource(blendedClipAnimator->clockId()); // Calculate the phase given the blend tree duration and global time - const qint64 globalTime = m_handler->simulationTime(); - const AnimatorEvaluationData animatorData = evaluationDataForAnimator(blendedClipAnimator, clock, globalTime); - int currentLoop = 0; - const double phase = phaseFromGlobalTime(animatorData.globalTime, - animatorData.startTime, - animatorData.playbackRate, - duration, - animatorData.loopCount, - currentLoop); + AnimatorEvaluationData animatorData = evaluationDataForAnimator(blendedClipAnimator, clock, nsSincePreviousFrame); + const double phase = phaseFromElapsedTime(animatorData.currentTime, animatorData.elapsedTime, + animatorData.playbackRate, + duration, + animatorData.loopCount, + animatorData.currentLoop); // Iterate over the value nodes of the blend tree, evaluate the // contained animation clips at the current phase and store the results @@ -107,7 +114,10 @@ void EvaluateBlendClipAnimatorJob::run() ClipResults blendedResults = evaluateBlendTree(m_handler, blendedClipAnimator, blendTreeRootId); const double localTime = phase * duration; - const bool finalFrame = isFinalFrame(localTime, duration, currentLoop, animatorData.loopCount); + blendedClipAnimator->setLastGlobalTimeNS(globalTimeNS); + blendedClipAnimator->setLastLocalTime(localTime); + blendedClipAnimator->setCurrentLoop(animatorData.currentLoop); + const bool finalFrame = isFinalFrame(localTime, duration, animatorData.currentLoop, animatorData.loopCount); // Prepare the property change events const QVector<MappingData> mappingData = blendedClipAnimator->mappingData(); diff --git a/src/animation/backend/evaluateblendclipanimatorjob_p.h b/src/animation/backend/evaluateblendclipanimatorjob_p.h index 7548168e9..6ef3b93cf 100644 --- a/src/animation/backend/evaluateblendclipanimatorjob_p.h +++ b/src/animation/backend/evaluateblendclipanimatorjob_p.h @@ -78,6 +78,9 @@ protected: private: HBlendedClipAnimator m_blendClipAnimatorHandle; Handler *m_handler; + + qint64 m_currentGlobalTime; + qint64 m_lastGlobalTime; }; typedef QSharedPointer<EvaluateBlendClipAnimatorJob> EvaluateBlendClipAnimatorJobPtr; diff --git a/src/animation/backend/evaluateclipanimatorjob.cpp b/src/animation/backend/evaluateclipanimatorjob.cpp index d9600c375..972762033 100644 --- a/src/animation/backend/evaluateclipanimatorjob.cpp +++ b/src/animation/backend/evaluateclipanimatorjob.cpp @@ -48,6 +48,8 @@ namespace Animation { EvaluateClipAnimatorJob::EvaluateClipAnimatorJob() : Qt3DCore::QAspectJob() + , m_currentGlobalTime(0.0) + , m_lastGlobalTime(0.0) { SET_JOB_RUN_STAT_TYPE(this, JobTypes::EvaluateClipAnimator, 0); } @@ -56,11 +58,13 @@ void EvaluateClipAnimatorJob::run() { Q_ASSERT(m_handler); - const qint64 globalTime = m_handler->simulationTime(); - //qDebug() << Q_FUNC_INFO << "t_global =" << globalTime; - ClipAnimator *clipAnimator = m_handler->clipAnimatorManager()->data(m_clipAnimatorHandle); Q_ASSERT(clipAnimator); + if (!clipAnimator->isRunning()) + return; + + qint64 globalTimeNS = m_handler->simulationTime(); + qint64 nsSincePreviousFrame = clipAnimator->nsSincePreviousFrame(globalTimeNS); Clock *clock = m_handler->clockManager()->lookupResource(clipAnimator->clockId()); @@ -68,7 +72,7 @@ void EvaluateClipAnimatorJob::run() AnimationClip *clip = m_handler->animationClipLoaderManager()->lookupResource(clipAnimator->clipId()); Q_ASSERT(clip); // Prepare for evaluation (convert global time to local time ....) - const AnimatorEvaluationData animatorEvaluationData = evaluationDataForAnimator(clipAnimator, clock, globalTime); + const AnimatorEvaluationData animatorEvaluationData = evaluationDataForAnimator(clipAnimator, clock, nsSincePreviousFrame); const ClipEvaluationData preEvaluationDataForClip = evaluationDataForClip(clip, animatorEvaluationData); const ClipResults rawClipResults = evaluateClipAtLocalTime(clip, preEvaluationDataForClip.localTime); @@ -80,6 +84,8 @@ void EvaluateClipAnimatorJob::run() clipAnimator->setRunning(false); clipAnimator->setCurrentLoop(preEvaluationDataForClip.currentLoop); + clipAnimator->setLastGlobalTimeNS(globalTimeNS); + clipAnimator->setLastLocalTime(preEvaluationDataForClip.localTime); // 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(), diff --git a/src/animation/backend/evaluateclipanimatorjob_p.h b/src/animation/backend/evaluateclipanimatorjob_p.h index c9b1a8f96..389d12456 100644 --- a/src/animation/backend/evaluateclipanimatorjob_p.h +++ b/src/animation/backend/evaluateclipanimatorjob_p.h @@ -82,6 +82,9 @@ protected: private: HClipAnimator m_clipAnimatorHandle; Handler *m_handler; + + qint64 m_currentGlobalTime; + qint64 m_lastGlobalTime; }; } // namespace Animation diff --git a/src/animation/backend/fcurve_p.h b/src/animation/backend/fcurve_p.h index f2148d1e9..8c5cdd54d 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/gltfimporter.cpp b/src/animation/backend/gltfimporter.cpp new file mode 100644 index 000000000..8d9b5bb60 --- /dev/null +++ b/src/animation/backend/gltfimporter.cpp @@ -0,0 +1,852 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "gltfimporter_p.h" +#include <Qt3DAnimation/private/animationlogging_p.h> +#include <Qt3DAnimation/private/fcurve_p.h> +#include <Qt3DAnimation/private/keyframe_p.h> + +#include <QtGui/qopengl.h> +#include <QtGui/qquaternion.h> +#include <QtGui/qvector2d.h> +#include <QtGui/qvector3d.h> +#include <QtGui/qvector4d.h> +#include <QtCore/qdir.h> +#include <QtCore/qfile.h> +#include <QtCore/qfileinfo.h> +#include <QtCore/qiodevice.h> +#include <QtCore/qversionnumber.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DAnimation { +namespace Animation { + +namespace { + +QString gltfTargetPropertyToChannelName(const QString &propertyName) +{ + if (propertyName == QLatin1String("rotation")) + return QLatin1String("Rotation"); + else if (propertyName == QLatin1String("translation")) + return QLatin1String("Location"); + else if (propertyName == QLatin1String("scale")) + return QLatin1String("Scale"); + + qWarning() << "Unknown target property name"; + return QString(); +} + +QKeyFrame::InterpolationType gltfToQKeyFrameInterpolation(GLTFImporter::Sampler::InterpolationMode mode) +{ + switch (mode) { + case GLTFImporter::Sampler::Linear: + return QKeyFrame::LinearInterpolation; + case GLTFImporter::Sampler::Step: + return QKeyFrame::ConstantInterpolation; + case GLTFImporter::Sampler::CubicSpline: + return QKeyFrame::BezierInterpolation; + case GLTFImporter::Sampler::CatmullRomSpline: + // TODO: Implement this interpolation type + qWarning() << "Unhandled interpolation type"; + return QKeyFrame::LinearInterpolation; + } + + return QKeyFrame::LinearInterpolation; +} + +void jsonArrayToSqt(const QJsonArray &jsonArray, Qt3DCore::Sqt &sqt) +{ + Q_ASSERT(jsonArray.size() == 16); + QMatrix4x4 m; + float *data = m.data(); + int i = 0; + for (const auto element : jsonArray) + *(data + i++) = static_cast<float>(element.toDouble()); + + decomposeQMatrix4x4(m, sqt); +} + +void jsonArrayToVector3D(const QJsonArray &jsonArray, QVector3D &v) +{ + Q_ASSERT(jsonArray.size() == 3); + v.setX(static_cast<float>(jsonArray.at(0).toDouble())); + v.setY(static_cast<float>(jsonArray.at(1).toDouble())); + v.setZ(static_cast<float>(jsonArray.at(2).toDouble())); +} + +void jsonArrayToQuaternion(const QJsonArray &jsonArray, QQuaternion &q) +{ + Q_ASSERT(jsonArray.size() == 4); + q.setX(static_cast<float>(jsonArray.at(0).toDouble())); + q.setY(static_cast<float>(jsonArray.at(1).toDouble())); + q.setZ(static_cast<float>(jsonArray.at(2).toDouble())); + q.setScalar(static_cast<float>(jsonArray.at(3).toDouble())); +} + +} + +#define KEY_ACCESSORS QLatin1String("accessors") +#define KEY_ANIMATIONS QLatin1String("animations") +#define KEY_ASSET QLatin1String("asset") +#define KEY_BUFFER QLatin1String("buffer") +#define KEY_BUFFERS QLatin1String("buffers") +#define KEY_BUFFER_VIEW QLatin1String("bufferView") +#define KEY_BUFFER_VIEWS QLatin1String("bufferViews") +#define KEY_BYTE_LENGTH QLatin1String("byteLength") +#define KEY_BYTE_OFFSET QLatin1String("byteOffset") +#define KEY_BYTE_STRIDE QLatin1String("byteStride") +#define KEY_CAMERA QLatin1String("camera") +#define KEY_CHANNELS QLatin1String("channels") +#define KEY_CHILDREN QLatin1String("children") +#define KEY_COMPONENT_TYPE QLatin1String("componentType") +#define KEY_COUNT QLatin1String("count") +#define KEY_JOINTS QLatin1String("joints") +#define KEY_INPUT QLatin1String("input") +#define KEY_INTERPOLATION QLatin1String("interpolation") +#define KEY_INVERSE_BIND_MATRICES QLatin1String("inverseBindMatrices") +#define KEY_MATRIX QLatin1String("matrix") +#define KEY_MESH QLatin1String("mesh") +#define KEY_NAME QLatin1String("name") +#define KEY_NODE QLatin1String("node") +#define KEY_NODES QLatin1String("nodes") +#define KEY_OUTPUT QLatin1String("output") +#define KEY_PATH QLatin1String("path") +#define KEY_ROTATION QLatin1String("rotation") +#define KEY_SAMPLER QLatin1String("sampler") +#define KEY_SAMPLERS QLatin1String("samplers") +#define KEY_SCALE QLatin1String("scale") +#define KEY_SKIN QLatin1String("skin") +#define KEY_SKINS QLatin1String("skins") +#define KEY_TARGET QLatin1String("target") +#define KEY_TRANSLATION QLatin1String("translation") +#define KEY_TYPE QLatin1String("type") +#define KEY_URI QLatin1String("uri") +#define KEY_VERSION QLatin1String("version") + +GLTFImporter::BufferData::BufferData() + : byteLength(0) + , data() +{ +} + +GLTFImporter::BufferData::BufferData(const QJsonObject &json) + : byteLength(json.value(KEY_BYTE_LENGTH).toInt()) + , path(json.value(KEY_URI).toString()) + , data() +{ +} + +GLTFImporter::BufferView::BufferView() + : byteOffset(0) + , byteLength(0) + , bufferIndex(-1) + , target(0) +{ +} + +GLTFImporter::BufferView::BufferView(const QJsonObject &json) + : byteOffset(json.value(KEY_BYTE_OFFSET).toInt()) + , byteLength(json.value(KEY_BYTE_LENGTH).toInt()) + , bufferIndex(json.value(KEY_BUFFER).toInt()) + , target(0) +{ + const auto targetValue = json.value(KEY_TARGET); + if (!targetValue.isUndefined()) + target = targetValue.toInt(); +} + +GLTFImporter::AccessorData::AccessorData() + : type(Qt3DRender::QAttribute::Float) + , dataSize(0) + , count(0) + , byteOffset(0) + , byteStride(0) +{ +} + +GLTFImporter::AccessorData::AccessorData(const QJsonObject &json) + : bufferViewIndex(json.value(KEY_BUFFER_VIEW).toInt(-1)) + , type(accessorTypeFromJSON(json.value(KEY_COMPONENT_TYPE).toInt())) + , dataSize(accessorDataSizeFromJson(json.value(KEY_TYPE).toString())) + , count(json.value(KEY_COUNT).toInt()) + , byteOffset(0) + , byteStride(0) +{ + const auto byteOffsetValue = json.value(KEY_BYTE_OFFSET); + if (!byteOffsetValue.isUndefined()) + byteOffset = byteOffsetValue.toInt(); + const auto byteStrideValue = json.value(KEY_BYTE_STRIDE); + if (!byteStrideValue.isUndefined()) + byteStride = byteStrideValue.toInt(); +} + +GLTFImporter::Skin::Skin() + : inverseBindAccessorIndex(-1) + , jointNodeIndices() +{ +} + +GLTFImporter::Skin::Skin(const QJsonObject &json) + : name(json.value(KEY_NAME).toString()) + , inverseBindAccessorIndex(json.value(KEY_INVERSE_BIND_MATRICES).toInt()) +{ + QJsonArray jointNodes = json.value(KEY_JOINTS).toArray(); + jointNodeIndices.reserve(jointNodes.size()); + for (const auto jointNodeValue : jointNodes) + jointNodeIndices.push_back(jointNodeValue.toInt()); +} + +GLTFImporter::Channel::Channel() + : samplerIndex(-1) + , targetNodeIndex(-1) + , targetProperty() +{ +} + +GLTFImporter::Channel::Channel(const QJsonObject &json) + : samplerIndex(json.value(KEY_SAMPLER).toInt()) + , targetNodeIndex(-1) + , targetProperty() +{ + const auto targetJson = json.value(KEY_TARGET).toObject(); + targetNodeIndex = targetJson.value(KEY_NODE).toInt(); + targetProperty = targetJson.value(KEY_PATH).toString(); +} + +GLTFImporter::Sampler::Sampler() + : inputAccessorIndex(-1) + , outputAccessorIndex(-1) + , interpolationMode(Linear) +{ +} + +GLTFImporter::Sampler::Sampler(const QJsonObject &json) + : inputAccessorIndex(json.value(KEY_INPUT).toInt()) + , outputAccessorIndex(json.value(KEY_OUTPUT).toInt()) + , interpolationMode(Linear) +{ + const auto interpolation = json.value(KEY_INTERPOLATION).toString(); + if (interpolation == QLatin1String("LINEAR")) + interpolationMode = Linear; + else if (interpolation == QLatin1String("STEP")) + interpolationMode = Step; + else if (interpolation == QLatin1String("CATMULLROMSPLINE")) + interpolationMode = CatmullRomSpline; + else if (interpolation == QLatin1String("CUBICSPLINE")) + interpolationMode = CubicSpline; +} + +QString GLTFImporter::Sampler::interpolationModeString() const +{ + switch (interpolationMode) { + case Linear: return QLatin1String("LINEAR"); + case Step: return QLatin1String("STEP"); + case CatmullRomSpline: return QLatin1String("CATMULLROMSPLINE"); + case CubicSpline: return QLatin1String("CUBICSPLINE"); + } + + return QLatin1String("Unknown"); +} + +GLTFImporter::Animation::Animation() + : name() + , channels() + , samplers() +{ +} + +GLTFImporter::Animation::Animation(const QJsonObject &json) + : name(json.value(KEY_NAME).toString()) +{ + QJsonArray channelsArray = json.value(KEY_CHANNELS).toArray(); + channels.reserve(channelsArray.size()); + for (const auto channelValue : channelsArray) { + Channel channel(channelValue.toObject()); + channels.push_back(channel); + } + + QJsonArray samplersArray = json.value(KEY_SAMPLERS).toArray(); + samplers.reserve(samplersArray.size()); + for (const auto samplerValue : samplersArray) { + Sampler sampler(samplerValue.toObject()); + samplers.push_back(sampler); + } +} + +GLTFImporter::Node::Node() + : localTransform() + , childNodeIndices() + , name() + , parentNodeIndex(-1) + , cameraIndex(-1) + , meshIndex(-1) + , skinIndex(-1) +{ +} + +GLTFImporter::Node::Node(const QJsonObject &json) + : localTransform() + , childNodeIndices() + , name(json.value(KEY_NAME).toString()) + , parentNodeIndex(-1) + , cameraIndex(-1) + , meshIndex(-1) + , skinIndex(-1) +{ + // Child nodes - we setup the parent links in a later pass + QJsonArray childNodes = json.value(KEY_CHILDREN).toArray(); + childNodeIndices.reserve(childNodes.size()); + for (const auto childNodeValue : childNodes) + childNodeIndices.push_back(childNodeValue.toInt()); + + // Local transform - matrix or scale, rotation, translation + const auto matrixValue = json.value(KEY_MATRIX); + if (!matrixValue.isUndefined()) { + jsonArrayToSqt(matrixValue.toArray(), localTransform); + } else { + const auto scaleValue = json.value(KEY_SCALE); + const auto rotationValue = json.value(KEY_ROTATION); + const auto translationValue = json.value(KEY_TRANSLATION); + + QVector3D s(1.0f, 1.0f, 1.0f); + if (!scaleValue.isUndefined()) + jsonArrayToVector3D(scaleValue.toArray(), localTransform.scale); + + QQuaternion r; + if (!rotationValue.isUndefined()) + jsonArrayToQuaternion(json.value(KEY_ROTATION).toArray(), localTransform.rotation); + + QVector3D t; + if (!translationValue.isUndefined()) + jsonArrayToVector3D(json.value(KEY_TRANSLATION).toArray(), localTransform.translation); + } + + // Referenced objects + const auto cameraValue = json.value(KEY_CAMERA); + if (!cameraValue.isUndefined()) + cameraIndex = cameraValue.toInt(); + + const auto meshValue = json.value(KEY_MESH); + if (!meshValue.isUndefined()) + meshIndex = meshValue.toInt(); + + const auto skinValue = json.value(KEY_SKIN); + if (!skinValue.isUndefined()) + skinIndex = skinValue.toInt(); +} + +Qt3DRender::QAttribute::VertexBaseType GLTFImporter::accessorTypeFromJSON(int componentType) +{ + if (componentType == GL_BYTE) + return Qt3DRender::QAttribute::Byte; + else if (componentType == GL_UNSIGNED_BYTE) + return Qt3DRender::QAttribute::UnsignedByte; + else if (componentType == GL_SHORT) + return Qt3DRender::QAttribute::Short; + else if (componentType == GL_UNSIGNED_SHORT) + return Qt3DRender::QAttribute::UnsignedShort; + else if (componentType == GL_UNSIGNED_INT) + return Qt3DRender::QAttribute::UnsignedInt; + else if (componentType == GL_FLOAT) + return Qt3DRender::QAttribute::Float; + + // There shouldn't be an invalid case here + qWarning("unsupported accessor type %d", componentType); + return Qt3DRender::QAttribute::Float; +} + +uint GLTFImporter::accessorTypeSize(Qt3DRender::QAttribute::VertexBaseType componentType) +{ + switch (componentType) { + case Qt3DRender::QAttribute::Byte: + case Qt3DRender::QAttribute::UnsignedByte: + return 1; + + case Qt3DRender::QAttribute::Short: + case Qt3DRender::QAttribute::UnsignedShort: + return 2; + + case Qt3DRender::QAttribute::Int: + case Qt3DRender::QAttribute::Float: + return 4; + + default: + qWarning("Unhandled accessor data type %d", componentType); + return 0; + } +} + +uint GLTFImporter::accessorDataSizeFromJson(const QString &type) +{ + QString typeName = type.toUpper(); + if (typeName == QLatin1String("SCALAR")) + return 1; + if (typeName == QLatin1String("VEC2")) + return 2; + if (typeName == QLatin1String("VEC3")) + return 3; + if (typeName == QLatin1String("VEC4")) + return 4; + if (typeName == QLatin1String("MAT2")) + return 4; + if (typeName == QLatin1String("MAT3")) + return 9; + if (typeName == QLatin1String("MAT4")) + return 16; + + return 0; +} + +GLTFImporter::GLTFImporter() +{ +} + +bool GLTFImporter::load(QIODevice *ioDev) +{ + QByteArray jsonData = ioDev->readAll(); + QJsonDocument sceneDocument = QJsonDocument::fromBinaryData(jsonData); + if (sceneDocument.isNull()) + sceneDocument = QJsonDocument::fromJson(jsonData); + + if (Q_UNLIKELY(!setJSON(sceneDocument))) { + qWarning("not a JSON document"); + return false; + } + + auto file = qobject_cast<QFile*>(ioDev); + if (file) { + QFileInfo finfo(file->fileName()); + setBasePath(finfo.dir().absolutePath()); + } + + return parse(); +} + +QHash<int, int> GLTFImporter::createNodeIndexToJointIndexMap(const Skin &skin) const +{ + const int jointCount = skin.jointNodeIndices.size(); + QHash<int, int> nodeIndexToJointIndexMap; + nodeIndexToJointIndexMap.reserve(jointCount); + for (int i = 0; i < jointCount; ++i) + nodeIndexToJointIndexMap.insert(skin.jointNodeIndices[i], i); + return nodeIndexToJointIndexMap; +} + +QVector<Qt3DAnimation::Animation::Channel> GLTFImporter::createAnimationData(const QString &animationName) const +{ + QVector<Qt3DAnimation::Animation::Channel> channels; + if (m_animations.isEmpty()) { + qCWarning(Jobs) << "File does not contain any animation data"; + return channels; + } + + int animationIndex = 0; + if (!animationName.isEmpty()) { + for (int i = 0; i < m_animations.size(); ++i) { + if (m_animations[i].name == animationName) { + animationIndex = i; + break; + } + } + } + const Animation &animation = m_animations[animationIndex]; + + // Create node index to joint index lookup tables for each skin + QVector<QHash<int, int>> nodeIndexToJointIndexMaps; + nodeIndexToJointIndexMaps.reserve(m_skins.size()); + for (const auto &skin : m_skins) + nodeIndexToJointIndexMaps.push_back(createNodeIndexToJointIndexMap(skin)); + + int channelIndex = 0; + for (const auto &channel : animation.channels) { + Qt3DAnimation::Animation::Channel outputChannel; + outputChannel.name = gltfTargetPropertyToChannelName(channel.targetProperty); + + // Find the node index to joint index map that contains the target node and + // look up the joint index from it. If no such map is found, the target joint + // is not part of a skeleton and so we can just set the jointIndex to -1. + int jointIndex = -1; + for (const auto &map : nodeIndexToJointIndexMaps) { + const auto result = map.find(channel.targetNodeIndex); + if (result != map.cend()) { + jointIndex = result.value(); + break; + } + } + outputChannel.jointIndex = jointIndex; + + const auto &sampler = animation.samplers[channel.samplerIndex]; + const auto interpolationType = gltfToQKeyFrameInterpolation(sampler.interpolationMode); + + if (sampler.inputAccessorIndex == -1 || sampler.outputAccessorIndex == -1) { + qWarning() << "Skipping channel due to invalid accessor indices in the sampler" << endl; + continue; + } + + const auto &inputAccessor = m_accessors[sampler.inputAccessorIndex]; + const auto &outputAccessor = m_accessors[sampler.outputAccessorIndex]; + + if (inputAccessor.type != Qt3DRender::QAttribute::Float) { + qWarning() << "Input accessor has wrong data type. Skipping channel."; + continue; + } + + if (outputAccessor.type != Qt3DRender::QAttribute::Float) { + qWarning() << "Output accessor has wrong data type. Skipping channel."; + continue; + } + + if (inputAccessor.count != outputAccessor.count) { + qWarning() << "Warning!!! Input accessor has" << inputAccessor.count + << "entries and output accessor has" << outputAccessor.count + << "entries. They should match. Please check your data."; + continue; + } + + // TODO: Allow Qt 3D animation data to share timestamps between multiple + // channel components. I.e. allow key frame values of composite types. + // Doesn't give as much freedom but more efficient at runtime. + + // Get the key frame times first as these are common to all components of the + // key frame values. + const int keyFrameCount = inputAccessor.count; + QVector<float> keyframeTimes(keyFrameCount); + for (int i = 0; i < keyFrameCount; ++i) { + const auto rawTimestamp = accessorData(sampler.inputAccessorIndex, i); + keyframeTimes[i] = *reinterpret_cast<const float*>(rawTimestamp.data); + } + + // Create a ChannelComponent for each component of the output sampler and + // populate it with data. + switch (outputAccessor.dataSize) { + // TODO: Handle other types as needed + case 3: { + // vec3 + const int componentCount = 3; + + // Construct the channel component names and add component to the channel + const QStringList suffixes + = (QStringList() << QLatin1String("X") << QLatin1String("Y") << QLatin1String("Z")); + outputChannel.channelComponents.resize(componentCount); + for (int componentIndex = 0; componentIndex < componentCount; ++componentIndex) { + outputChannel.channelComponents[componentIndex].name + = QString(QLatin1String("%1 %2")).arg(outputChannel.name, + suffixes[componentIndex]); + } + + // Populate the fcurves in the channel components + for (int i = 0; i < keyFrameCount; ++i) { + const auto rawKeyframeValue = accessorData(sampler.outputAccessorIndex, i); + QVector3D v; + memcpy(&v, rawKeyframeValue.data, rawKeyframeValue.byteLength); + + for (int componentIndex = 0; componentIndex < componentCount; ++componentIndex) { + Keyframe keyFrame; + keyFrame.interpolation = interpolationType; + keyFrame.value = v[componentIndex]; + outputChannel.channelComponents[componentIndex].fcurve.appendKeyframe(keyframeTimes[i], keyFrame); + } + } + + break; + } // case 3 + + case 4: { + // vec4 or quaternion + const int componentCount = 4; + + // Construct the channel component names and add component to the channel + const QStringList rotationSuffixes = (QStringList() + << QLatin1String("X") << QLatin1String("Y") << QLatin1String("Z") << QLatin1String("W")); + const QStringList standardSuffixes = (QStringList() + << QLatin1String("X") << QLatin1String("Y") << QLatin1String("Z")); + const QStringList suffixes = (channel.targetProperty == QLatin1String("rotation")) + ? rotationSuffixes : standardSuffixes; + outputChannel.channelComponents.resize(componentCount); + for (int componentIndex = 0; componentIndex < componentCount; ++componentIndex) { + outputChannel.channelComponents[componentIndex].name + = QString(QLatin1String("%1 %2")).arg(outputChannel.name, + suffixes[componentIndex]); + } + + // Populate the fcurves in the channel components + for (int i = 0; i < keyFrameCount; ++i) { + const auto rawKeyframeValue = accessorData(sampler.outputAccessorIndex, i); + QVector4D v; + memcpy(&v, rawKeyframeValue.data, rawKeyframeValue.byteLength); + + for (int componentIndex = 0; componentIndex < componentCount; ++componentIndex) { + Keyframe keyFrame; + keyFrame.interpolation = interpolationType; + keyFrame.value = v[componentIndex]; + outputChannel.channelComponents[componentIndex].fcurve.appendKeyframe(keyframeTimes[i], keyFrame); + } + } + + break; + } // case 4 + } + + channels.push_back(outputChannel); + ++channelIndex; + } + + return channels; +} + +GLTFImporter::RawData GLTFImporter::accessorData(int accessorIndex, int index) const +{ + const AccessorData &accessor = m_accessors[accessorIndex]; + const BufferView &bufferView = m_bufferViews[accessor.bufferViewIndex]; + const BufferData &bufferData = m_bufferDatas[bufferView.bufferIndex]; + const QByteArray &ba = bufferData.data; + const char *rawData = ba.constData() + bufferView.byteOffset + accessor.byteOffset; + + const uint typeSize = accessorTypeSize(accessor.type); + const int stride = (accessor.byteStride == 0) + ? accessor.dataSize * typeSize + : accessor.byteStride; + + const char* data = rawData + index * stride; + if (data - rawData > ba.size()) { + qWarning("Attempting to access data beyond end of buffer"); + return RawData{ nullptr, 0 }; + } + + const quint64 byteLength = accessor.dataSize * typeSize; + RawData rd{ data, byteLength }; + + return rd; +} + +void GLTFImporter::setBasePath(const QString &path) +{ + m_basePath = path; +} + +bool GLTFImporter::setJSON(const QJsonDocument &json) +{ + if (!json.isObject()) + return false; + m_json = json; + cleanup(); + return true; +} + +bool GLTFImporter::parse() +{ + // Find the glTF version + const QJsonObject asset = m_json.object().value(KEY_ASSET).toObject(); + const QString versionString = asset.value(KEY_VERSION).toString(); + const auto version = QVersionNumber::fromString(versionString); + switch (version.majorVersion()) { + case 2: + return parseGLTF2(); + + default: + qWarning() << "Unsupported version of glTF" << versionString; + return false; + } +} + +bool GLTFImporter::parseGLTF2() +{ + bool success = true; + const QJsonArray buffers = m_json.object().value(KEY_BUFFERS).toArray(); + for (const auto &bufferValue : buffers) + success &= processJSONBuffer(bufferValue.toObject()); + + const QJsonArray bufferViews = m_json.object().value(KEY_BUFFER_VIEWS).toArray(); + for (const auto &bufferViewValue : bufferViews) + success &= processJSONBufferView(bufferViewValue.toObject()); + + const QJsonArray accessors = m_json.object().value(KEY_ACCESSORS).toArray(); + for (const auto &accessorValue : accessors) + success &= processJSONAccessor(accessorValue.toObject()); + + const QJsonArray skins = m_json.object().value(KEY_SKINS).toArray(); + for (const auto &skinValue : skins) + success &= processJSONSkin(skinValue.toObject()); + + const QJsonArray animations = m_json.object().value(KEY_ANIMATIONS).toArray(); + for (const auto &animationValue : animations) + success &= processJSONAnimation(animationValue.toObject()); + + const QJsonArray nodes = m_json.object().value(KEY_NODES).toArray(); + for (const auto &nodeValue : nodes) + success &= processJSONNode(nodeValue.toObject()); + setupNodeParentLinks(); + + // TODO: Make a complete GLTF 2 parser by extending to other top level elements: + // scenes, animations, meshes etc. + + return success; +} + +void GLTFImporter::cleanup() +{ + m_accessors.clear(); + m_bufferViews.clear(); + m_bufferDatas.clear(); +} + +bool GLTFImporter::processJSONBuffer(const QJsonObject &json) +{ + // Store buffer details and load data into memory + BufferData buffer(json); + buffer.data = resolveLocalData(buffer.path); + if (buffer.data.isEmpty()) + return false; + + m_bufferDatas.push_back(buffer); + return true; +} + +bool GLTFImporter::processJSONBufferView(const QJsonObject &json) +{ + BufferView bufferView(json); + + // Perform sanity checks + const auto bufferIndex = bufferView.bufferIndex; + if (Q_UNLIKELY(bufferIndex) >= m_bufferDatas.size()) { + qWarning("Unknown buffer %d when processing buffer view", bufferIndex); + return false; + } + + const auto &bufferData = m_bufferDatas[bufferIndex]; + if (bufferView.byteOffset > bufferData.byteLength) { + qWarning("Bufferview has offset greater than buffer %d length", bufferIndex); + return false; + } + + if (Q_UNLIKELY(bufferView.byteOffset + bufferView.byteLength > bufferData.byteLength)) { + qWarning("BufferView extends beyond end of buffer %d", bufferIndex); + return false; + } + + m_bufferViews.push_back(bufferView); + return true; +} + +bool GLTFImporter::processJSONAccessor(const QJsonObject &json) +{ + AccessorData accessor(json); + + // TODO: Perform sanity checks + + m_accessors.push_back(accessor); + return true; +} + +bool GLTFImporter::processJSONSkin(const QJsonObject &json) +{ + Skin skin(json); + + // TODO: Perform sanity checks + + m_skins.push_back(skin); + return true; +} + +bool GLTFImporter::processJSONAnimation(const QJsonObject &json) +{ + Animation animation(json); + + for (const auto &channel : animation.channels) { + if (channel.samplerIndex == -1) + qWarning() << "Invalid sampler index in animation" + << animation.name << "for channel targeting node" + << channel.targetNodeIndex << " and property" + << channel.targetProperty; + } + + for (const auto &sampler : animation.samplers) { + if (sampler.inputAccessorIndex == -1) { + qWarning() << "Sampler for animaton" << animation.name + << "references has an invalid input accessor index"; + } + + if (sampler.outputAccessorIndex == -1) { + qWarning() << "Sampler for animaton" << animation.name + << "references has an invalid output accessor index"; + } + } + + m_animations.push_back(animation); + return true; +} + +bool GLTFImporter::processJSONNode(const QJsonObject &json) +{ + Node node(json); + + // TODO: Perform sanity checks + + m_nodes.push_back(node); + return true; +} + +void GLTFImporter::setupNodeParentLinks() +{ + const int nodeCount = m_nodes.size(); + for (int i = 0; i < nodeCount; ++i) { + const Node &node = m_nodes[i]; + const QVector<int> &childNodeIndices = node.childNodeIndices; + for (const auto childNodeIndex : childNodeIndices) { + Q_ASSERT(childNodeIndex < m_nodes.size()); + Node &childNode = m_nodes[childNodeIndex]; + Q_ASSERT(childNode.parentNodeIndex == -1); + childNode.parentNodeIndex = i; + } + } +} + +QByteArray GLTFImporter::resolveLocalData(const QString &path) const +{ + QDir d(m_basePath); + Q_ASSERT(d.exists()); + + QString absPath = d.absoluteFilePath(path); + QFile f(absPath); + f.open(QIODevice::ReadOnly); + return f.readAll(); +} + +} // namespace Animation +} // namespace Qt3DAnimation + +QT_END_NAMESPACE diff --git a/src/animation/backend/gltfimporter_p.h b/src/animation/backend/gltfimporter_p.h new file mode 100644 index 000000000..ae7674fe7 --- /dev/null +++ b/src/animation/backend/gltfimporter_p.h @@ -0,0 +1,232 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DANIMATION_ANIMATION_GLTFIMPORTER_H +#define QT3DANIMATION_ANIMATION_GLTFIMPORTER_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtGlobal> +#include <Qt3DAnimation/private/fcurve_p.h> +#include <Qt3DRender/qattribute.h> +#include <Qt3DCore/private/sqt_p.h> +#include <Qt3DCore/private/qmath3d_p.h> + +#include <QJsonDocument> +#include <QJsonObject> +#include <QJsonArray> +#include <QJsonValue> +#include <QVector> + +QT_BEGIN_NAMESPACE + +class QIODevice; + +namespace Qt3DAnimation { +namespace Animation { + +class GLTFImporter +{ +public: + class BufferData + { + public: + BufferData(); + explicit BufferData(const QJsonObject &json); + + quint64 byteLength; + QString path; + QByteArray data; + }; + + class BufferView + { + public: + BufferView(); + explicit BufferView(const QJsonObject &json); + + quint64 byteOffset; + quint64 byteLength; + int bufferIndex; + int target; // Only for per vertex attributes + }; + + class AccessorData + { + public: + AccessorData(); + explicit AccessorData(const QJsonObject &json); + + int bufferViewIndex; + Qt3DRender::QAttribute::VertexBaseType type; + uint dataSize; + int count; + int byteOffset; + int byteStride; // Only for per vertex attributes + + // TODO: Extend to support sparse accessors + }; + + class Skin + { + public: + Skin(); + explicit Skin(const QJsonObject &json); + + QString name; + int inverseBindAccessorIndex; + QVector<int> jointNodeIndices; + }; + + class Channel + { + public: + Channel(); + explicit Channel(const QJsonObject &json); + + int samplerIndex; + int targetNodeIndex; + QString targetProperty; + }; + + class Sampler + { + public: + Sampler(); + explicit Sampler(const QJsonObject &json); + + enum InterpolationMode { + Linear, + Step, + CatmullRomSpline, + CubicSpline + }; + + QString interpolationModeString() const; + + int inputAccessorIndex; + int outputAccessorIndex; + InterpolationMode interpolationMode; + }; + + class Animation + { + public: + Animation(); + explicit Animation(const QJsonObject &json); + + QString name; + QVector<Channel> channels; + QVector<Sampler> samplers; + }; + + class Node + { + public: + Node(); + explicit Node(const QJsonObject &json); + + Qt3DCore::Sqt localTransform; + QVector<int> childNodeIndices; + QString name; + int parentNodeIndex; + int cameraIndex; + int meshIndex; + int skinIndex; + }; + + GLTFImporter(); + + bool load(QIODevice *ioDev); + const QVector<Animation> animations() const { return m_animations; } + + QVector<Qt3DAnimation::Animation::Channel> createAnimationData(const QString &animationName = QString()) const; + +private: + static Qt3DRender::QAttribute::VertexBaseType accessorTypeFromJSON(int componentType); + static uint accessorTypeSize(Qt3DRender::QAttribute::VertexBaseType componentType); + static uint accessorDataSizeFromJson(const QString &type); + + struct RawData + { + const char *data; + quint64 byteLength; + }; + + void setBasePath(const QString &path); + bool setJSON(const QJsonDocument &json); + + bool parse(); + bool parseGLTF2(); + void cleanup(); + QHash<int, int> createNodeIndexToJointIndexMap(const Skin &skin) const; + + bool processJSONBuffer(const QJsonObject &json); + bool processJSONBufferView(const QJsonObject &json); + bool processJSONAccessor(const QJsonObject &json); + bool processJSONSkin(const QJsonObject &json); + bool processJSONAnimation(const QJsonObject &json); + bool processJSONNode(const QJsonObject &json); + void setupNodeParentLinks(); + QByteArray resolveLocalData(const QString &path) const; + + RawData accessorData(int accessorIndex, int index) const; + + QJsonDocument m_json; + QString m_basePath; + QVector<BufferData> m_bufferDatas; + QVector<BufferView> m_bufferViews; + QVector<AccessorData> m_accessors; + QVector<Skin> m_skins; + QVector<Animation> m_animations; + QVector<Node> m_nodes; +}; + +} // namespace Animation +} // namespace Qt3DAnimation + +QT_END_NAMESPACE + +#endif // QT3DANIMATION_ANIMATION_GLTFIMPORTER_H diff --git a/src/animation/frontend/qanimationclip.cpp b/src/animation/frontend/qanimationclip.cpp index 7e7250021..2b04ce1ea 100644 --- a/src/animation/frontend/qanimationclip.cpp +++ b/src/animation/frontend/qanimationclip.cpp @@ -70,12 +70,18 @@ QAnimationClip::~QAnimationClip() { } +/*! + Returns the data describing the animation clip. +*/ QAnimationClipData QAnimationClip::clipData() const { Q_D(const QAnimationClip); return d->m_clipData; } +/*! + Set the parameters of the clip according to the \a clipData provided. +*/ void QAnimationClip::setClipData(const Qt3DAnimation::QAnimationClipData &clipData) { Q_D(QAnimationClip); diff --git a/src/animation/frontend/qclipanimator.cpp b/src/animation/frontend/qclipanimator.cpp index 19e6eafed..79125a76e 100644 --- a/src/animation/frontend/qclipanimator.cpp +++ b/src/animation/frontend/qclipanimator.cpp @@ -175,6 +175,7 @@ void QClipAnimator::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) if (callbackTrigger->callback()) callbackTrigger->callback()->valueChanged(callbackTrigger->value()); } + QAbstractClipAnimator::sceneChangeEvent(change); } } // namespace Qt3DAnimation diff --git a/src/core/transforms/qjoint.cpp b/src/core/transforms/qjoint.cpp index 84d75d55d..3f631ec98 100644 --- a/src/core/transforms/qjoint.cpp +++ b/src/core/transforms/qjoint.cpp @@ -240,7 +240,18 @@ void QJoint::setRotation(const QQuaternion &rotation) return; d->m_rotation = rotation; + const QVector3D oldRotation = d->m_eulerRotationAngles; + d->m_eulerRotationAngles = d->m_rotation.toEulerAngles(); emit rotationChanged(rotation); + + const bool wasBlocked = blockNotifications(true); + if (!qFuzzyCompare(d->m_eulerRotationAngles.x(), oldRotation.x())) + emit rotationXChanged(d->m_eulerRotationAngles.x()); + if (!qFuzzyCompare(d->m_eulerRotationAngles.y(), oldRotation.y())) + emit rotationYChanged(d->m_eulerRotationAngles.y()); + if (!qFuzzyCompare(d->m_eulerRotationAngles.z(), oldRotation.z())) + emit rotationZChanged(d->m_eulerRotationAngles.z()); + blockNotifications(wasBlocked); } void QJoint::setTranslation(const QVector3D &translation) @@ -267,47 +278,41 @@ void QJoint::setRotationX(float rotationX) { Q_D(QJoint); - if (d->m_eulerRotationAngles.x() == rotationX) + if (qFuzzyCompare(d->m_eulerRotationAngles.x(), rotationX)) return; - d->m_eulerRotationAngles.setX(rotationX); - const QQuaternion r = QQuaternion::fromEulerAngles(d->m_eulerRotationAngles); + const auto eulers = QVector3D(rotationX, + d->m_eulerRotationAngles.y(), + d->m_eulerRotationAngles.z()); + const QQuaternion r = QQuaternion::fromEulerAngles(eulers); setRotation(r); - - const bool wasBlocked = blockNotifications(true); - emit rotationXChanged(rotationX); - blockNotifications(wasBlocked); } void QJoint::setRotationY(float rotationY) { Q_D(QJoint); - if (d->m_eulerRotationAngles.y() == rotationY) + if (qFuzzyCompare(d->m_eulerRotationAngles.y(), rotationY)) return; - d->m_eulerRotationAngles.setY(rotationY); - const QQuaternion r = QQuaternion::fromEulerAngles(d->m_eulerRotationAngles); + const auto eulers = QVector3D(d->m_eulerRotationAngles.x(), + rotationY, + d->m_eulerRotationAngles.z()); + const QQuaternion r = QQuaternion::fromEulerAngles(eulers); setRotation(r); - - const bool wasBlocked = blockNotifications(true); - emit rotationYChanged(rotationY); - blockNotifications(wasBlocked); } void QJoint::setRotationZ(float rotationZ) { Q_D(QJoint); - if (d->m_eulerRotationAngles.z() == rotationZ) + if (qFuzzyCompare(d->m_eulerRotationAngles.z(), rotationZ)) return; - d->m_eulerRotationAngles.setZ(rotationZ); - const QQuaternion r = QQuaternion::fromEulerAngles(d->m_eulerRotationAngles); + const auto eulers = QVector3D(d->m_eulerRotationAngles.x(), + d->m_eulerRotationAngles.y(), + rotationZ); + const QQuaternion r = QQuaternion::fromEulerAngles(eulers); setRotation(r); - - const bool wasBlocked = blockNotifications(true); - emit rotationZChanged(rotationZ); - blockNotifications(wasBlocked); } void QJoint::setName(const QString &name) @@ -320,6 +325,13 @@ void QJoint::setName(const QString &name) emit nameChanged(name); } +void QJoint::setToIdentity() +{ + setScale(QVector3D(1.0f, 1.0f, 1.0f)); + setRotation(QQuaternion()); + setTranslation(QVector3D()); +} + /*! Adds \a joint as a child of this joint. If \a joint has no parent, then this joint takes ownership of it. Child joints are in the coordinate system diff --git a/src/core/transforms/qjoint.h b/src/core/transforms/qjoint.h index 732cfdddb..fdc3d51a3 100644 --- a/src/core/transforms/qjoint.h +++ b/src/core/transforms/qjoint.h @@ -91,6 +91,7 @@ public Q_SLOTS: void setRotationY(float rotationY); void setRotationZ(float rotationZ); void setName(const QString &name); + void setToIdentity(); Q_SIGNALS: void scaleChanged(const QVector3D &scale); diff --git a/src/extras/defaults/defaults.pri b/src/extras/defaults/defaults.pri index 2575de1a3..4fe79e0d9 100644 --- a/src/extras/defaults/defaults.pri +++ b/src/extras/defaults/defaults.pri @@ -28,7 +28,6 @@ HEADERS += \ $$PWD/qabstractcameracontroller.h \ $$PWD/qabstractcameracontroller_p.h \ $$PWD/qfirstpersoncameracontroller.h \ - $$PWD/qfirstpersoncameracontroller_p.h \ $$PWD/qorbitcameracontroller.h \ $$PWD/qorbitcameracontroller_p.h \ $$PWD/qabstractspritesheet.h \ diff --git a/src/extras/defaults/qabstractcameracontroller.cpp b/src/extras/defaults/qabstractcameracontroller.cpp index 8bf57f5fa..2ebf187aa 100644 --- a/src/extras/defaults/qabstractcameracontroller.cpp +++ b/src/extras/defaults/qabstractcameracontroller.cpp @@ -224,7 +224,7 @@ void QAbstractCameraControllerPrivate::applyInputAccelerations() } /*! - \class QAbstractCameraController + \class Qt3DExtras::QAbstractCameraController \brief The QAbstractCameraController class provides basic functionality for camera controllers. diff --git a/src/extras/defaults/qdiffusemapmaterial.cpp b/src/extras/defaults/qdiffusemapmaterial.cpp index 930fbbd1f..29e8586e3 100644 --- a/src/extras/defaults/qdiffusemapmaterial.cpp +++ b/src/extras/defaults/qdiffusemapmaterial.cpp @@ -46,6 +46,7 @@ #include <Qt3DRender/qtexture.h> #include <Qt3DRender/qtechnique.h> #include <Qt3DRender/qshaderprogram.h> +#include <Qt3DRender/qshaderprogrambuilder.h> #include <Qt3DRender/qparameter.h> #include <Qt3DRender/qrenderpass.h> #include <Qt3DRender/qgraphicsapifilter.h> @@ -75,7 +76,9 @@ QDiffuseMapMaterialPrivate::QDiffuseMapMaterialPrivate() , m_diffuseMapGL2RenderPass(new QRenderPass()) , m_diffuseMapES2RenderPass(new QRenderPass()) , m_diffuseMapGL3Shader(new QShaderProgram()) + , m_diffuseMapGL3ShaderBuilder(new QShaderProgramBuilder()) , m_diffuseMapGL2ES2Shader(new QShaderProgram()) + , m_diffuseMapGL2ES2ShaderBuilder(new QShaderProgramBuilder()) , m_filterKey(new QFilterKey) { m_diffuseTexture->setMagnificationFilter(QAbstractTexture::Linear); @@ -87,6 +90,8 @@ QDiffuseMapMaterialPrivate::QDiffuseMapMaterialPrivate() void QDiffuseMapMaterialPrivate::init() { + Q_Q(QDiffuseMapMaterial); + connect(m_ambientParameter, &Qt3DRender::QParameter::valueChanged, this, &QDiffuseMapMaterialPrivate::handleAmbientChanged); connect(m_diffuseParameter, &Qt3DRender::QParameter::valueChanged, @@ -99,9 +104,20 @@ void QDiffuseMapMaterialPrivate::init() this, &QDiffuseMapMaterialPrivate::handleTextureScaleChanged); m_diffuseMapGL3Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/default.vert")))); - m_diffuseMapGL3Shader->setFragmentShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/diffusemap.frag")))); + m_diffuseMapGL3ShaderBuilder->setParent(q); + m_diffuseMapGL3ShaderBuilder->setShaderProgram(m_diffuseMapGL3Shader); + m_diffuseMapGL3ShaderBuilder->setFragmentShaderGraph(QUrl(QStringLiteral("qrc:/shaders/graphs/phong.frag.json"))); + m_diffuseMapGL3ShaderBuilder->setEnabledLayers({QStringLiteral("diffuseTexture"), + QStringLiteral("specular"), + QStringLiteral("normal")}); + m_diffuseMapGL2ES2Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/default.vert")))); - m_diffuseMapGL2ES2Shader->setFragmentShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/diffusemap.frag")))); + m_diffuseMapGL2ES2ShaderBuilder->setParent(q); + m_diffuseMapGL2ES2ShaderBuilder->setShaderProgram(m_diffuseMapGL2ES2Shader); + m_diffuseMapGL2ES2ShaderBuilder->setFragmentShaderGraph(QUrl(QStringLiteral("qrc:/shaders/graphs/phong.frag.json"))); + m_diffuseMapGL2ES2ShaderBuilder->setEnabledLayers({QStringLiteral("diffuseTexture"), + QStringLiteral("specular"), + QStringLiteral("normal")}); m_diffuseMapGL3Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL); m_diffuseMapGL3Technique->graphicsApiFilter()->setMajorVersion(3); @@ -118,7 +134,6 @@ void QDiffuseMapMaterialPrivate::init() m_diffuseMapES2Technique->graphicsApiFilter()->setMinorVersion(0); m_diffuseMapES2Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::NoProfile); - Q_Q(QDiffuseMapMaterial); m_filterKey->setParent(q); m_filterKey->setName(QStringLiteral("renderingStyle")); m_filterKey->setValue(QStringLiteral("forward")); diff --git a/src/extras/defaults/qdiffusemapmaterial_p.h b/src/extras/defaults/qdiffusemapmaterial_p.h index c0bcc01eb..cef75a3f0 100644 --- a/src/extras/defaults/qdiffusemapmaterial_p.h +++ b/src/extras/defaults/qdiffusemapmaterial_p.h @@ -63,6 +63,7 @@ class QAbstractTexture; class QTechnique; class QParameter; class QShaderProgram; +class QShaderProgramBuilder; class QRenderPass; } // namespace Qt3DRender @@ -97,7 +98,9 @@ class QDiffuseMapMaterialPrivate : public Qt3DRender::QMaterialPrivate Qt3DRender::QRenderPass *m_diffuseMapGL2RenderPass; Qt3DRender::QRenderPass *m_diffuseMapES2RenderPass; Qt3DRender::QShaderProgram *m_diffuseMapGL3Shader; + Qt3DRender::QShaderProgramBuilder *m_diffuseMapGL3ShaderBuilder; Qt3DRender::QShaderProgram *m_diffuseMapGL2ES2Shader; + Qt3DRender::QShaderProgramBuilder *m_diffuseMapGL2ES2ShaderBuilder; Qt3DRender::QFilterKey *m_filterKey; Q_DECLARE_PUBLIC(QDiffuseMapMaterial) diff --git a/src/extras/defaults/qdiffusespecularmapmaterial.cpp b/src/extras/defaults/qdiffusespecularmapmaterial.cpp index 2e98bc8e7..cc5facd8c 100644 --- a/src/extras/defaults/qdiffusespecularmapmaterial.cpp +++ b/src/extras/defaults/qdiffusespecularmapmaterial.cpp @@ -46,6 +46,7 @@ #include <Qt3DRender/qtexture.h> #include <Qt3DRender/qtechnique.h> #include <Qt3DRender/qshaderprogram.h> +#include <Qt3DRender/qshaderprogrambuilder.h> #include <Qt3DRender/qparameter.h> #include <Qt3DRender/qrenderpass.h> #include <Qt3DRender/qgraphicsapifilter.h> @@ -76,7 +77,9 @@ QDiffuseSpecularMapMaterialPrivate::QDiffuseSpecularMapMaterialPrivate() , m_diffuseSpecularMapGL2RenderPass(new QRenderPass()) , m_diffuseSpecularMapES2RenderPass(new QRenderPass()) , m_diffuseSpecularMapGL3Shader(new QShaderProgram()) + , m_diffuseSpecularMapGL3ShaderBuilder(new QShaderProgramBuilder()) , m_diffuseSpecularMapGL2ES2Shader(new QShaderProgram()) + , m_diffuseSpecularMapGL2ES2ShaderBuilder(new QShaderProgramBuilder()) , m_filterKey(new QFilterKey) { m_diffuseTexture->setMagnificationFilter(QAbstractTexture::Linear); @@ -94,6 +97,8 @@ QDiffuseSpecularMapMaterialPrivate::QDiffuseSpecularMapMaterialPrivate() void QDiffuseSpecularMapMaterialPrivate::init() { + Q_Q(QDiffuseSpecularMapMaterial); + connect(m_ambientParameter, &Qt3DRender::QParameter::valueChanged, this, &QDiffuseSpecularMapMaterialPrivate::handleAmbientChanged); connect(m_diffuseParameter, &Qt3DRender::QParameter::valueChanged, @@ -106,9 +111,20 @@ void QDiffuseSpecularMapMaterialPrivate::init() this, &QDiffuseSpecularMapMaterialPrivate::handleTextureScaleChanged); m_diffuseSpecularMapGL3Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/default.vert")))); - m_diffuseSpecularMapGL3Shader->setFragmentShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/diffusespecularmap.frag")))); + m_diffuseSpecularMapGL3ShaderBuilder->setParent(q); + m_diffuseSpecularMapGL3ShaderBuilder->setShaderProgram(m_diffuseSpecularMapGL3Shader); + m_diffuseSpecularMapGL3ShaderBuilder->setFragmentShaderGraph(QUrl(QStringLiteral("qrc:/shaders/graphs/phong.frag.json"))); + m_diffuseSpecularMapGL3ShaderBuilder->setEnabledLayers({QStringLiteral("diffuseTexture"), + QStringLiteral("specularTexture"), + QStringLiteral("normal")}); + m_diffuseSpecularMapGL2ES2Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/default.vert")))); - m_diffuseSpecularMapGL2ES2Shader->setFragmentShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/diffusespecularmap.frag")))); + m_diffuseSpecularMapGL2ES2ShaderBuilder->setParent(q); + m_diffuseSpecularMapGL2ES2ShaderBuilder->setShaderProgram(m_diffuseSpecularMapGL2ES2Shader); + m_diffuseSpecularMapGL2ES2ShaderBuilder->setFragmentShaderGraph(QUrl(QStringLiteral("qrc:/shaders/graphs/phong.frag.json"))); + m_diffuseSpecularMapGL2ES2ShaderBuilder->setEnabledLayers({QStringLiteral("diffuseTexture"), + QStringLiteral("specularTexture"), + QStringLiteral("normal")}); m_diffuseSpecularMapGL3Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL); m_diffuseSpecularMapGL3Technique->graphicsApiFilter()->setMajorVersion(3); @@ -125,7 +141,6 @@ void QDiffuseSpecularMapMaterialPrivate::init() m_diffuseSpecularMapES2Technique->graphicsApiFilter()->setMinorVersion(0); m_diffuseSpecularMapES2Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::NoProfile); - Q_Q(QDiffuseSpecularMapMaterial); m_filterKey->setParent(q); m_filterKey->setName(QStringLiteral("renderingStyle")); m_filterKey->setValue(QStringLiteral("forward")); diff --git a/src/extras/defaults/qdiffusespecularmapmaterial_p.h b/src/extras/defaults/qdiffusespecularmapmaterial_p.h index b358e088a..f80922dff 100644 --- a/src/extras/defaults/qdiffusespecularmapmaterial_p.h +++ b/src/extras/defaults/qdiffusespecularmapmaterial_p.h @@ -63,6 +63,7 @@ class QAbstractTexture; class QTechnique; class QParameter; class QShaderProgram; +class QShaderProgramBuilder; class QRenderPass; } // namespace Qt3DRender @@ -99,7 +100,9 @@ public: Qt3DRender::QRenderPass *m_diffuseSpecularMapGL2RenderPass; Qt3DRender::QRenderPass *m_diffuseSpecularMapES2RenderPass; Qt3DRender::QShaderProgram *m_diffuseSpecularMapGL3Shader; + Qt3DRender::QShaderProgramBuilder *m_diffuseSpecularMapGL3ShaderBuilder; Qt3DRender::QShaderProgram *m_diffuseSpecularMapGL2ES2Shader; + Qt3DRender::QShaderProgramBuilder *m_diffuseSpecularMapGL2ES2ShaderBuilder; Qt3DRender::QFilterKey *m_filterKey; Q_DECLARE_PUBLIC(QDiffuseSpecularMapMaterial) diff --git a/src/extras/defaults/qmetalroughmaterial.cpp b/src/extras/defaults/qmetalroughmaterial.cpp index ac6117101..4d537f20f 100644 --- a/src/extras/defaults/qmetalroughmaterial.cpp +++ b/src/extras/defaults/qmetalroughmaterial.cpp @@ -107,7 +107,7 @@ void QMetalRoughMaterialPrivate::init() QObject::connect(m_ambientOcclusionMapParameter, &Qt3DRender::QParameter::valueChanged, q, &QMetalRoughMaterial::roughnessChanged); QObject::connect(m_normalMapParameter, &Qt3DRender::QParameter::valueChanged, - q, &QMetalRoughMaterial::roughnessChanged); + q, &QMetalRoughMaterial::normalChanged); connect(m_textureScaleParameter, &Qt3DRender::QParameter::valueChanged, this, &QMetalRoughMaterialPrivate::handleTextureScaleChanged); diff --git a/src/extras/defaults/qnormaldiffusemapalphamaterial.cpp b/src/extras/defaults/qnormaldiffusemapalphamaterial.cpp index dd8288683..c276c9717 100644 --- a/src/extras/defaults/qnormaldiffusemapalphamaterial.cpp +++ b/src/extras/defaults/qnormaldiffusemapalphamaterial.cpp @@ -45,6 +45,7 @@ #include <Qt3DRender/qtechnique.h> #include <Qt3DRender/qparameter.h> #include <Qt3DRender/qshaderprogram.h> +#include <Qt3DRender/qshaderprogrambuilder.h> #include <Qt3DRender/qrenderpass.h> #include <Qt3DRender/qgraphicsapifilter.h> #include <Qt3DRender/qalphacoverage.h> @@ -69,6 +70,8 @@ QNormalDiffuseMapAlphaMaterialPrivate::QNormalDiffuseMapAlphaMaterialPrivate() void QNormalDiffuseMapAlphaMaterialPrivate::init() { + Q_Q(QNormalDiffuseMapMaterial); + connect(m_ambientParameter, &Qt3DRender::QParameter::valueChanged, this, &QNormalDiffuseMapMaterialPrivate::handleAmbientChanged); connect(m_diffuseParameter, &Qt3DRender::QParameter::valueChanged, @@ -83,9 +86,20 @@ void QNormalDiffuseMapAlphaMaterialPrivate::init() this, &QNormalDiffuseMapMaterialPrivate::handleTextureScaleChanged); m_normalDiffuseGL3Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/default.vert")))); - m_normalDiffuseGL3Shader->setFragmentShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/normaldiffusemap.frag")))); + m_normalDiffuseGL3ShaderBuilder->setParent(q); + m_normalDiffuseGL3ShaderBuilder->setShaderProgram(m_normalDiffuseGL3Shader); + m_normalDiffuseGL3ShaderBuilder->setFragmentShaderGraph(QUrl(QStringLiteral("qrc:/shaders/graphs/phong.frag.json"))); + m_normalDiffuseGL3ShaderBuilder->setEnabledLayers({QStringLiteral("diffuseTexture"), + QStringLiteral("specular"), + QStringLiteral("normalTexture")}); + m_normalDiffuseGL2ES2Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/default.vert")))); - m_normalDiffuseGL2ES2Shader->setFragmentShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/normaldiffusemap.frag")))); + m_normalDiffuseGL2ES2ShaderBuilder->setParent(q); + m_normalDiffuseGL2ES2ShaderBuilder->setShaderProgram(m_normalDiffuseGL2ES2Shader); + m_normalDiffuseGL2ES2ShaderBuilder->setFragmentShaderGraph(QUrl(QStringLiteral("qrc:/shaders/graphs/phong.frag.json"))); + m_normalDiffuseGL2ES2ShaderBuilder->setEnabledLayers({QStringLiteral("diffuseTexture"), + QStringLiteral("specular"), + QStringLiteral("normalTexture")}); m_normalDiffuseGL3Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL); m_normalDiffuseGL3Technique->graphicsApiFilter()->setMajorVersion(3); @@ -102,7 +116,6 @@ void QNormalDiffuseMapAlphaMaterialPrivate::init() m_normalDiffuseES2Technique->graphicsApiFilter()->setMinorVersion(0); m_normalDiffuseES2Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::NoProfile); - Q_Q(QNormalDiffuseMapMaterial); m_filterKey->setParent(q); m_filterKey->setName(QStringLiteral("renderingStyle")); m_filterKey->setValue(QStringLiteral("forward")); diff --git a/src/extras/defaults/qnormaldiffusemapmaterial.cpp b/src/extras/defaults/qnormaldiffusemapmaterial.cpp index ec3bd0a22..687e59751 100644 --- a/src/extras/defaults/qnormaldiffusemapmaterial.cpp +++ b/src/extras/defaults/qnormaldiffusemapmaterial.cpp @@ -46,6 +46,7 @@ #include <Qt3DRender/qtechnique.h> #include <Qt3DRender/qparameter.h> #include <Qt3DRender/qshaderprogram.h> +#include <Qt3DRender/qshaderprogrambuilder.h> #include <Qt3DRender/qrenderpass.h> #include <Qt3DRender/qgraphicsapifilter.h> #include <QtCore/QUrl> @@ -76,7 +77,9 @@ QNormalDiffuseMapMaterialPrivate::QNormalDiffuseMapMaterialPrivate() , m_normalDiffuseGL2RenderPass(new QRenderPass()) , m_normalDiffuseES2RenderPass(new QRenderPass()) , m_normalDiffuseGL3Shader(new QShaderProgram()) + , m_normalDiffuseGL3ShaderBuilder(new QShaderProgramBuilder()) , m_normalDiffuseGL2ES2Shader(new QShaderProgram()) + , m_normalDiffuseGL2ES2ShaderBuilder(new QShaderProgramBuilder()) , m_filterKey(new QFilterKey) { m_diffuseTexture->setMagnificationFilter(QAbstractTexture::Linear); @@ -94,6 +97,8 @@ QNormalDiffuseMapMaterialPrivate::QNormalDiffuseMapMaterialPrivate() void QNormalDiffuseMapMaterialPrivate::init() { + Q_Q(QNormalDiffuseMapMaterial); + connect(m_ambientParameter, &Qt3DRender::QParameter::valueChanged, this, &QNormalDiffuseMapMaterialPrivate::handleAmbientChanged); connect(m_diffuseParameter, &Qt3DRender::QParameter::valueChanged, @@ -108,9 +113,20 @@ void QNormalDiffuseMapMaterialPrivate::init() this, &QNormalDiffuseMapMaterialPrivate::handleTextureScaleChanged); m_normalDiffuseGL3Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/default.vert")))); - m_normalDiffuseGL3Shader->setFragmentShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/normaldiffusemap.frag")))); + m_normalDiffuseGL3ShaderBuilder->setParent(q); + m_normalDiffuseGL3ShaderBuilder->setShaderProgram(m_normalDiffuseGL3Shader); + m_normalDiffuseGL3ShaderBuilder->setFragmentShaderGraph(QUrl(QStringLiteral("qrc:/shaders/graphs/phong.frag.json"))); + m_normalDiffuseGL3ShaderBuilder->setEnabledLayers({QStringLiteral("diffuseTexture"), + QStringLiteral("specular"), + QStringLiteral("normalTexture")}); + m_normalDiffuseGL2ES2Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/default.vert")))); - m_normalDiffuseGL2ES2Shader->setFragmentShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/normaldiffusemap.frag")))); + m_normalDiffuseGL2ES2ShaderBuilder->setParent(q); + m_normalDiffuseGL2ES2ShaderBuilder->setShaderProgram(m_normalDiffuseGL2ES2Shader); + m_normalDiffuseGL2ES2ShaderBuilder->setFragmentShaderGraph(QUrl(QStringLiteral("qrc:/shaders/graphs/phong.frag.json"))); + m_normalDiffuseGL2ES2ShaderBuilder->setEnabledLayers({QStringLiteral("diffuseTexture"), + QStringLiteral("specular"), + QStringLiteral("normalTexture")}); m_normalDiffuseGL3Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL); m_normalDiffuseGL3Technique->graphicsApiFilter()->setMajorVersion(3); @@ -127,7 +143,6 @@ void QNormalDiffuseMapMaterialPrivate::init() m_normalDiffuseES2Technique->graphicsApiFilter()->setMinorVersion(0); m_normalDiffuseES2Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::NoProfile); - Q_Q(QNormalDiffuseMapMaterial); m_filterKey->setParent(q); m_filterKey->setName(QStringLiteral("renderingStyle")); m_filterKey->setValue(QStringLiteral("forward")); diff --git a/src/extras/defaults/qnormaldiffusemapmaterial_p.h b/src/extras/defaults/qnormaldiffusemapmaterial_p.h index d88b01f1f..1ac937b1e 100644 --- a/src/extras/defaults/qnormaldiffusemapmaterial_p.h +++ b/src/extras/defaults/qnormaldiffusemapmaterial_p.h @@ -63,6 +63,7 @@ class QAbstractTexture; class QTechnique; class QParameter; class QShaderProgram; +class QShaderProgramBuilder; class QRenderPass; } // namespace Qt3DRender @@ -101,7 +102,9 @@ public: Qt3DRender::QRenderPass *m_normalDiffuseGL2RenderPass; Qt3DRender::QRenderPass *m_normalDiffuseES2RenderPass; Qt3DRender::QShaderProgram *m_normalDiffuseGL3Shader; + Qt3DRender::QShaderProgramBuilder *m_normalDiffuseGL3ShaderBuilder; Qt3DRender::QShaderProgram *m_normalDiffuseGL2ES2Shader; + Qt3DRender::QShaderProgramBuilder *m_normalDiffuseGL2ES2ShaderBuilder; Qt3DRender::QFilterKey *m_filterKey; Q_DECLARE_PUBLIC(QNormalDiffuseMapMaterial) diff --git a/src/extras/defaults/qnormaldiffusespecularmapmaterial.cpp b/src/extras/defaults/qnormaldiffusespecularmapmaterial.cpp index eaa1491a0..7665c07a7 100644 --- a/src/extras/defaults/qnormaldiffusespecularmapmaterial.cpp +++ b/src/extras/defaults/qnormaldiffusespecularmapmaterial.cpp @@ -46,6 +46,7 @@ #include <Qt3DRender/qtexture.h> #include <Qt3DRender/qtechnique.h> #include <Qt3DRender/qshaderprogram.h> +#include <Qt3DRender/qshaderprogrambuilder.h> #include <Qt3DRender/qparameter.h> #include <Qt3DRender/qrenderpass.h> #include <Qt3DRender/qgraphicsapifilter.h> @@ -78,7 +79,9 @@ QNormalDiffuseSpecularMapMaterialPrivate::QNormalDiffuseSpecularMapMaterialPriva , m_normalDiffuseSpecularGL2RenderPass(new QRenderPass()) , m_normalDiffuseSpecularES2RenderPass(new QRenderPass()) , m_normalDiffuseSpecularGL3Shader(new QShaderProgram()) + , m_normalDiffuseSpecularGL3ShaderBuilder(new QShaderProgramBuilder()) , m_normalDiffuseSpecularGL2ES2Shader(new QShaderProgram()) + , m_normalDiffuseSpecularGL2ES2ShaderBuilder(new QShaderProgramBuilder()) , m_filterKey(new QFilterKey) { m_diffuseTexture->setMagnificationFilter(QAbstractTexture::Linear); @@ -102,6 +105,8 @@ QNormalDiffuseSpecularMapMaterialPrivate::QNormalDiffuseSpecularMapMaterialPriva void QNormalDiffuseSpecularMapMaterialPrivate::init() { + Q_Q(QNormalDiffuseSpecularMapMaterial); + connect(m_ambientParameter, &Qt3DRender::QParameter::valueChanged, this, &QNormalDiffuseSpecularMapMaterialPrivate::handleAmbientChanged); connect(m_diffuseParameter, &Qt3DRender::QParameter::valueChanged, @@ -116,9 +121,20 @@ void QNormalDiffuseSpecularMapMaterialPrivate::init() this, &QNormalDiffuseSpecularMapMaterialPrivate::handleTextureScaleChanged); m_normalDiffuseSpecularGL3Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/default.vert")))); - m_normalDiffuseSpecularGL3Shader->setFragmentShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/normaldiffusespecularmap.frag")))); + m_normalDiffuseSpecularGL3ShaderBuilder->setParent(q); + m_normalDiffuseSpecularGL3ShaderBuilder->setShaderProgram(m_normalDiffuseSpecularGL3Shader); + m_normalDiffuseSpecularGL3ShaderBuilder->setFragmentShaderGraph(QUrl(QStringLiteral("qrc:/shaders/graphs/phong.frag.json"))); + m_normalDiffuseSpecularGL3ShaderBuilder->setEnabledLayers({QStringLiteral("diffuseTexture"), + QStringLiteral("specularTexture"), + QStringLiteral("normalTexture")}); + m_normalDiffuseSpecularGL2ES2Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/default.vert")))); - m_normalDiffuseSpecularGL2ES2Shader->setFragmentShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/normaldiffusespecularmap.frag")))); + m_normalDiffuseSpecularGL2ES2ShaderBuilder->setParent(q); + m_normalDiffuseSpecularGL2ES2ShaderBuilder->setShaderProgram(m_normalDiffuseSpecularGL2ES2Shader); + m_normalDiffuseSpecularGL2ES2ShaderBuilder->setFragmentShaderGraph(QUrl(QStringLiteral("qrc:/shaders/graphs/phong.frag.json"))); + m_normalDiffuseSpecularGL2ES2ShaderBuilder->setEnabledLayers({QStringLiteral("diffuseTexture"), + QStringLiteral("specularTexture"), + QStringLiteral("normalTexture")}); m_normalDiffuseSpecularGL3Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL); m_normalDiffuseSpecularGL3Technique->graphicsApiFilter()->setMajorVersion(3); @@ -135,7 +151,6 @@ void QNormalDiffuseSpecularMapMaterialPrivate::init() m_normalDiffuseSpecularES2Technique->graphicsApiFilter()->setMinorVersion(0); m_normalDiffuseSpecularES2Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::NoProfile); - Q_Q(QNormalDiffuseSpecularMapMaterial); m_filterKey->setParent(q); m_filterKey->setName(QStringLiteral("renderingStyle")); m_filterKey->setValue(QStringLiteral("forward")); diff --git a/src/extras/defaults/qnormaldiffusespecularmapmaterial_p.h b/src/extras/defaults/qnormaldiffusespecularmapmaterial_p.h index 3316044ff..e02451cc0 100644 --- a/src/extras/defaults/qnormaldiffusespecularmapmaterial_p.h +++ b/src/extras/defaults/qnormaldiffusespecularmapmaterial_p.h @@ -63,6 +63,7 @@ class QAbstractTexture; class QTechnique; class QParameter; class QShaderProgram; +class QShaderProgramBuilder; class QRenderPass; } // namespace Qt3DRender @@ -102,7 +103,9 @@ public: Qt3DRender::QRenderPass *m_normalDiffuseSpecularGL2RenderPass; Qt3DRender::QRenderPass *m_normalDiffuseSpecularES2RenderPass; Qt3DRender::QShaderProgram *m_normalDiffuseSpecularGL3Shader; + Qt3DRender::QShaderProgramBuilder *m_normalDiffuseSpecularGL3ShaderBuilder; Qt3DRender::QShaderProgram *m_normalDiffuseSpecularGL2ES2Shader; + Qt3DRender::QShaderProgramBuilder *m_normalDiffuseSpecularGL2ES2ShaderBuilder; Qt3DRender::QFilterKey *m_filterKey; Q_DECLARE_PUBLIC(QNormalDiffuseSpecularMapMaterial) diff --git a/src/extras/defaults/qorbitcameracontroller.cpp b/src/extras/defaults/qorbitcameracontroller.cpp index 03e9a290b..c4f976f89 100644 --- a/src/extras/defaults/qorbitcameracontroller.cpp +++ b/src/extras/defaults/qorbitcameracontroller.cpp @@ -182,7 +182,7 @@ void QOrbitCameraController::moveCamera(const QAbstractCameraController::InputSt } else if (state.shiftKeyActive) { if (zoomDistance(camera()->position(), theCamera->viewCenter()) > d->m_zoomInLimit * d->m_zoomInLimit) { // Dolly - theCamera->translate(QVector3D(0, 0, state.tyAxisValue), theCamera->DontTranslateViewCenter); + theCamera->translate(QVector3D(0, 0, state.tyAxisValue * linearSpeed() * dt), theCamera->DontTranslateViewCenter); } else { theCamera->translate(QVector3D(0, 0, -0.5), theCamera->DontTranslateViewCenter); } diff --git a/src/extras/defaults/qphongalphamaterial.cpp b/src/extras/defaults/qphongalphamaterial.cpp index fd8c52525..fb0871ee4 100644 --- a/src/extras/defaults/qphongalphamaterial.cpp +++ b/src/extras/defaults/qphongalphamaterial.cpp @@ -45,6 +45,7 @@ #include <Qt3DRender/qeffect.h> #include <Qt3DRender/qtechnique.h> #include <Qt3DRender/qshaderprogram.h> +#include <Qt3DRender/qshaderprogrambuilder.h> #include <Qt3DRender/qparameter.h> #include <Qt3DRender/qrenderpass.h> #include <Qt3DRender/qgraphicsapifilter.h> @@ -75,7 +76,9 @@ QPhongAlphaMaterialPrivate::QPhongAlphaMaterialPrivate() , m_phongAlphaGL2RenderPass(new QRenderPass()) , m_phongAlphaES2RenderPass(new QRenderPass()) , m_phongAlphaGL3Shader(new QShaderProgram()) + , m_phongAlphaGL3ShaderBuilder(new QShaderProgramBuilder()) , m_phongAlphaGL2ES2Shader(new QShaderProgram()) + , m_phongAlphaGL2ES2ShaderBuilder(new QShaderProgramBuilder()) , m_noDepthMask(new QNoDepthMask()) , m_blendState(new QBlendEquationArguments()) , m_blendEquation(new QBlendEquation()) @@ -86,6 +89,8 @@ QPhongAlphaMaterialPrivate::QPhongAlphaMaterialPrivate() // TODO: Define how lights are properties are set in the shaders. Ideally using a QShaderData void QPhongAlphaMaterialPrivate::init() { + Q_Q(QPhongAlphaMaterial); + connect(m_ambientParameter, &Qt3DRender::QParameter::valueChanged, this, &QPhongAlphaMaterialPrivate::handleAmbientChanged); connect(m_diffuseParameter, &Qt3DRender::QParameter::valueChanged, @@ -96,9 +101,20 @@ void QPhongAlphaMaterialPrivate::init() this, &QPhongAlphaMaterialPrivate::handleShininessChanged); m_phongAlphaGL3Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/default.vert")))); - m_phongAlphaGL3Shader->setFragmentShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/phong.frag")))); + m_phongAlphaGL3ShaderBuilder->setParent(q); + m_phongAlphaGL3ShaderBuilder->setShaderProgram(m_phongAlphaGL3Shader); + m_phongAlphaGL3ShaderBuilder->setFragmentShaderGraph(QUrl(QStringLiteral("qrc:/shaders/graphs/phong.frag.json"))); + m_phongAlphaGL3ShaderBuilder->setEnabledLayers({QStringLiteral("diffuse"), + QStringLiteral("specular"), + QStringLiteral("normal")}); + m_phongAlphaGL2ES2Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/default.vert")))); - m_phongAlphaGL2ES2Shader->setFragmentShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/phong.frag")))); + m_phongAlphaGL2ES2ShaderBuilder->setParent(q); + m_phongAlphaGL2ES2ShaderBuilder->setShaderProgram(m_phongAlphaGL2ES2Shader); + m_phongAlphaGL2ES2ShaderBuilder->setFragmentShaderGraph(QUrl(QStringLiteral("qrc:/shaders/graphs/phong.frag.json"))); + m_phongAlphaGL2ES2ShaderBuilder->setEnabledLayers({QStringLiteral("diffuse"), + QStringLiteral("specular"), + QStringLiteral("normal")}); m_phongAlphaGL3Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL); m_phongAlphaGL3Technique->graphicsApiFilter()->setMajorVersion(3); @@ -115,7 +131,6 @@ void QPhongAlphaMaterialPrivate::init() m_phongAlphaES2Technique->graphicsApiFilter()->setMinorVersion(0); m_phongAlphaES2Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::NoProfile); - Q_Q(QPhongAlphaMaterial); m_filterKey->setParent(q); m_filterKey->setName(QStringLiteral("renderingStyle")); m_filterKey->setValue(QStringLiteral("forward")); diff --git a/src/extras/defaults/qphongalphamaterial_p.h b/src/extras/defaults/qphongalphamaterial_p.h index 84e2eead3..97eaf7bc4 100644 --- a/src/extras/defaults/qphongalphamaterial_p.h +++ b/src/extras/defaults/qphongalphamaterial_p.h @@ -62,6 +62,7 @@ class QEffect; class QTechnique; class QParameter; class QShaderProgram; +class QShaderProgramBuilder; class QRenderPass; class QNoDepthMask; class QBlendEquationArguments; @@ -97,7 +98,9 @@ public: Qt3DRender::QRenderPass *m_phongAlphaGL2RenderPass; Qt3DRender::QRenderPass *m_phongAlphaES2RenderPass; Qt3DRender::QShaderProgram *m_phongAlphaGL3Shader; + Qt3DRender::QShaderProgramBuilder *m_phongAlphaGL3ShaderBuilder; Qt3DRender::QShaderProgram *m_phongAlphaGL2ES2Shader; + Qt3DRender::QShaderProgramBuilder *m_phongAlphaGL2ES2ShaderBuilder; Qt3DRender::QNoDepthMask *m_noDepthMask; Qt3DRender::QBlendEquationArguments *m_blendState; Qt3DRender::QBlendEquation *m_blendEquation; diff --git a/src/extras/defaults/qphongmaterial.cpp b/src/extras/defaults/qphongmaterial.cpp index 25dbf3c85..c76e3a6ef 100644 --- a/src/extras/defaults/qphongmaterial.cpp +++ b/src/extras/defaults/qphongmaterial.cpp @@ -45,6 +45,7 @@ #include <Qt3DRender/qeffect.h> #include <Qt3DRender/qtechnique.h> #include <Qt3DRender/qshaderprogram.h> +#include <Qt3DRender/qshaderprogrambuilder.h> #include <Qt3DRender/qparameter.h> #include <Qt3DRender/qrenderpass.h> #include <Qt3DRender/qgraphicsapifilter.h> @@ -73,13 +74,17 @@ QPhongMaterialPrivate::QPhongMaterialPrivate() , m_phongGL2RenderPass(new QRenderPass()) , m_phongES2RenderPass(new QRenderPass()) , m_phongGL3Shader(new QShaderProgram()) + , m_phongGL3ShaderBuilder(new QShaderProgramBuilder()) , m_phongGL2ES2Shader(new QShaderProgram()) + , m_phongGL2ES2ShaderBuilder(new QShaderProgramBuilder()) , m_filterKey(new QFilterKey) { } void QPhongMaterialPrivate::init() { + Q_Q(QPhongMaterial); + connect(m_ambientParameter, &Qt3DRender::QParameter::valueChanged, this, &QPhongMaterialPrivate::handleAmbientChanged); connect(m_diffuseParameter, &Qt3DRender::QParameter::valueChanged, @@ -90,9 +95,20 @@ void QPhongMaterialPrivate::init() this, &QPhongMaterialPrivate::handleShininessChanged); m_phongGL3Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/default.vert")))); - m_phongGL3Shader->setFragmentShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/phong.frag")))); + m_phongGL3ShaderBuilder->setParent(q); + m_phongGL3ShaderBuilder->setShaderProgram(m_phongGL3Shader); + m_phongGL3ShaderBuilder->setFragmentShaderGraph(QUrl(QStringLiteral("qrc:/shaders/graphs/phong.frag.json"))); + m_phongGL3ShaderBuilder->setEnabledLayers({QStringLiteral("diffuse"), + QStringLiteral("specular"), + QStringLiteral("normal")}); + m_phongGL2ES2Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/default.vert")))); - m_phongGL2ES2Shader->setFragmentShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/phong.frag")))); + m_phongGL2ES2ShaderBuilder->setParent(q); + m_phongGL2ES2ShaderBuilder->setShaderProgram(m_phongGL2ES2Shader); + m_phongGL2ES2ShaderBuilder->setFragmentShaderGraph(QUrl(QStringLiteral("qrc:/shaders/graphs/phong.frag.json"))); + m_phongGL2ES2ShaderBuilder->setEnabledLayers({QStringLiteral("diffuse"), + QStringLiteral("specular"), + QStringLiteral("normal")}); m_phongGL3Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL); m_phongGL3Technique->graphicsApiFilter()->setMajorVersion(3); @@ -117,7 +133,6 @@ void QPhongMaterialPrivate::init() m_phongGL2Technique->addRenderPass(m_phongGL2RenderPass); m_phongES2Technique->addRenderPass(m_phongES2RenderPass); - Q_Q(QPhongMaterial); m_filterKey->setParent(q); m_filterKey->setName(QStringLiteral("renderingStyle")); m_filterKey->setValue(QStringLiteral("forward")); diff --git a/src/extras/defaults/qphongmaterial_p.h b/src/extras/defaults/qphongmaterial_p.h index bc6d0ce44..f1e55242b 100644 --- a/src/extras/defaults/qphongmaterial_p.h +++ b/src/extras/defaults/qphongmaterial_p.h @@ -62,6 +62,7 @@ class QEffect; class QTechnique; class QParameter; class QShaderProgram; +class QShaderProgramBuilder; class QRenderPass; } // namespace Qt3DRender @@ -94,7 +95,9 @@ public: Qt3DRender::QRenderPass *m_phongGL2RenderPass; Qt3DRender::QRenderPass *m_phongES2RenderPass; Qt3DRender::QShaderProgram *m_phongGL3Shader; + Qt3DRender::QShaderProgramBuilder *m_phongGL3ShaderBuilder; Qt3DRender::QShaderProgram *m_phongGL2ES2Shader; + Qt3DRender::QShaderProgramBuilder *m_phongGL2ES2ShaderBuilder; Qt3DRender::QFilterKey *m_filterKey; Q_DECLARE_PUBLIC(QPhongMaterial) diff --git a/src/extras/defaults/qt3dwindow.cpp b/src/extras/defaults/qt3dwindow.cpp index 635d81956..baa2aeddb 100644 --- a/src/extras/defaults/qt3dwindow.cpp +++ b/src/extras/defaults/qt3dwindow.cpp @@ -125,6 +125,9 @@ Qt3DWindow::~Qt3DWindow() delete d->m_aspectEngine; } +/*! + Registers the specified \a aspect. +*/ void Qt3DWindow::registerAspect(Qt3DCore::QAbstractAspect *aspect) { Q_ASSERT(!isVisible()); @@ -132,6 +135,9 @@ void Qt3DWindow::registerAspect(Qt3DCore::QAbstractAspect *aspect) d->m_aspectEngine->registerAspect(aspect); } +/*! + Registers the specified aspect \a name. +*/ void Qt3DWindow::registerAspect(const QString &name) { Q_ASSERT(!isVisible()); @@ -139,6 +145,9 @@ void Qt3DWindow::registerAspect(const QString &name) d->m_aspectEngine->registerAspect(name); } +/*! + Sets the specified \a root entity of the scene. +*/ void Qt3DWindow::setRootEntity(Qt3DCore::QEntity *root) { Q_D(Qt3DWindow); @@ -151,18 +160,27 @@ void Qt3DWindow::setRootEntity(Qt3DCore::QEntity *root) } } +/*! + Activates the specified \a activeFrameGraph. +*/ void Qt3DWindow::setActiveFrameGraph(Qt3DRender::QFrameGraphNode *activeFrameGraph) { Q_D(Qt3DWindow); d->m_renderSettings->setActiveFrameGraph(activeFrameGraph); } +/*! + Returns the node of the active frame graph. +*/ Qt3DRender::QFrameGraphNode *Qt3DWindow::activeFrameGraph() const { Q_D(const Qt3DWindow); return d->m_renderSettings->activeFrameGraph(); } +/*! + Returns the node of the default framegraph +*/ Qt3DExtras::QForwardRenderer *Qt3DWindow::defaultFrameGraph() const { Q_D(const Qt3DWindow); @@ -175,12 +193,18 @@ Qt3DRender::QCamera *Qt3DWindow::camera() const return d->m_defaultCamera; } +/*! + Returns the render settings of the 3D Window. +*/ Qt3DRender::QRenderSettings *Qt3DWindow::renderSettings() const { Q_D(const Qt3DWindow); return d->m_renderSettings; } +/*! + Manages the display events specified in \a e. +*/ void Qt3DWindow::showEvent(QShowEvent *e) { Q_D(Qt3DWindow); @@ -194,7 +218,9 @@ void Qt3DWindow::showEvent(QShowEvent *e) QWindow::showEvent(e); } - +/*! + Resets the aspect ratio of the 3D window. +*/ void Qt3DWindow::resizeEvent(QResizeEvent *) { Q_D(Qt3DWindow); diff --git a/src/extras/extras.qrc b/src/extras/extras.qrc index f3619fdb7..bfb14f3f9 100644 --- a/src/extras/extras.qrc +++ b/src/extras/extras.qrc @@ -1,6 +1,7 @@ <RCC> <qresource prefix="/"> <file>shaders/graphs/metalrough.frag.json</file> + <file>shaders/graphs/phong.frag.json</file> <file>shaders/gl3/light.inc.frag</file> <file>shaders/es2/light.inc.frag</file> <file>shaders/es2/light.inc.frag100</file> @@ -10,16 +11,6 @@ <file>shaders/gl3/metalrough.inc.frag</file> <file>shaders/gl3/coordinatesystems.inc</file> <file>shaders/es2/coordinatesystems.inc</file> - <file>shaders/gl3/phong.frag</file> - <file>shaders/es2/phong.frag</file> - <file>shaders/gl3/normaldiffusespecularmap.frag</file> - <file>shaders/gl3/diffusemap.frag</file> - <file>shaders/es2/normaldiffusespecularmap.frag</file> - <file>shaders/es2/diffusemap.frag</file> - <file>shaders/es2/normaldiffusemap.frag</file> - <file>shaders/gl3/normaldiffusemap.frag</file> - <file>shaders/es2/diffusespecularmap.frag</file> - <file>shaders/gl3/diffusespecularmap.frag</file> <file>shaders/gl3/default.vert</file> <file>shaders/es2/default.vert</file> <file>shaders/gl3/pervertexcolor.frag</file> diff --git a/src/extras/shaders/es2/diffusemap.frag b/src/extras/shaders/es2/diffusemap.frag deleted file mode 100644 index 6ac9bd5a3..000000000 --- a/src/extras/shaders/es2/diffusemap.frag +++ /dev/null @@ -1,22 +0,0 @@ -#define FP highp - -uniform FP vec4 ka; // Ambient reflectivity -uniform FP vec4 ks; // Specular reflectivity -uniform FP float shininess; // Specular shininess factor - -uniform FP vec3 eyePosition; - -uniform sampler2D diffuseTexture; - -varying FP vec3 worldPosition; -varying FP vec3 worldNormal; -varying FP vec2 texCoord; - -#pragma include phong.inc.frag - -void main() -{ - FP vec4 diffuseTextureColor = texture2D( diffuseTexture, texCoord ); - FP vec3 worldView = normalize(eyePosition - worldPosition); - gl_FragColor = phongFunction(ka, diffuseTextureColor, ks, shininess, worldPosition, worldView, worldNormal); -} diff --git a/src/extras/shaders/es2/diffusespecularmap.frag b/src/extras/shaders/es2/diffusespecularmap.frag deleted file mode 100644 index 99183aaf4..000000000 --- a/src/extras/shaders/es2/diffusespecularmap.frag +++ /dev/null @@ -1,24 +0,0 @@ -#define FP highp - -// TODO: Replace with a struct -uniform FP vec4 ka; // Ambient reflectivity -uniform FP float shininess; // Specular shininess factor - -uniform FP vec3 eyePosition; - -uniform sampler2D diffuseTexture; -uniform sampler2D specularTexture; - -varying FP vec3 worldPosition; -varying FP vec3 worldNormal; -varying FP vec2 texCoord; - -#pragma include phong.inc.frag - -void main() -{ - FP vec4 diffuseTextureColor = texture2D( diffuseTexture, texCoord ); - FP vec4 specularTextureColor = texture2D( specularTexture, texCoord ); - FP vec3 worldView = normalize(eyePosition - worldPosition); - gl_FragColor = phongFunction(ka, diffuseTextureColor, specularTextureColor, shininess, worldPosition, worldView, worldNormal); -} diff --git a/src/extras/shaders/es2/normaldiffusemap.frag b/src/extras/shaders/es2/normaldiffusemap.frag deleted file mode 100644 index 0bf4c5630..000000000 --- a/src/extras/shaders/es2/normaldiffusemap.frag +++ /dev/null @@ -1,34 +0,0 @@ -#define FP highp - -varying FP vec3 worldPosition; -varying FP vec3 worldNormal; -varying FP vec4 worldTangent; -varying FP vec2 texCoord; - -uniform sampler2D diffuseTexture; -uniform sampler2D normalTexture; - -// TODO: Replace with a struct -uniform FP vec4 ka; // Ambient reflectivity -uniform FP vec4 ks; // Specular reflectivity -uniform FP float shininess; // Specular shininess factor - -uniform FP vec3 eyePosition; - -#pragma include phong.inc.frag -#pragma include coordinatesystems.inc - -void main() -{ - // Sample the textures at the interpolated texCoords - FP vec4 diffuseTextureColor = texture2D( diffuseTexture, texCoord ); - FP vec3 tNormal = 2.0 * texture2D( normalTexture, texCoord ).rgb - vec3( 1.0 ); - - FP mat3 tangentMatrix = calcWorldSpaceToTangentSpaceMatrix(worldNormal, worldTangent); - FP mat3 invertTangentMatrix = transpose(tangentMatrix); - - FP vec3 wNormal = normalize(invertTangentMatrix * tNormal); - FP vec3 worldView = normalize(eyePosition - worldPosition); - - gl_FragColor = phongFunction(ka, diffuseTextureColor, ks, shininess, worldPosition, worldView, wNormal); -} diff --git a/src/extras/shaders/es2/normaldiffusespecularmap.frag b/src/extras/shaders/es2/normaldiffusespecularmap.frag deleted file mode 100644 index 0541c8902..000000000 --- a/src/extras/shaders/es2/normaldiffusespecularmap.frag +++ /dev/null @@ -1,35 +0,0 @@ -#define FP highp - -varying FP vec3 worldPosition; -varying FP vec3 worldNormal; -varying FP vec4 worldTangent; -varying FP vec2 texCoord; - -uniform sampler2D diffuseTexture; -uniform sampler2D specularTexture; -uniform sampler2D normalTexture; - -// TODO: Replace with a struct -uniform FP vec4 ka; // Ambient reflectivity -uniform FP float shininess; // Specular shininess factor - -uniform FP vec3 eyePosition; - -#pragma include phong.inc.frag -#pragma include coordinatesystems.inc - -void main() -{ - // Sample the textures at the interpolated texCoords - FP vec4 diffuseTextureColor = texture2D( diffuseTexture, texCoord ); - FP vec4 specularTextureColor = texture2D( specularTexture, texCoord ); - FP vec3 tNormal = 2.0 * texture2D( normalTexture, texCoord ).rgb - vec3( 1.0 ); - - FP mat3 tangentMatrix = calcWorldSpaceToTangentSpaceMatrix(worldNormal, worldTangent); - FP mat3 invertTangentMatrix = transpose(tangentMatrix); - - FP vec3 wNormal = normalize(invertTangentMatrix * tNormal); - FP vec3 worldView = normalize(eyePosition - worldPosition); - - gl_FragColor = phongFunction(ka, diffuseTextureColor, specularTextureColor, shininess, worldPosition, worldView, wNormal); -} diff --git a/src/extras/shaders/es2/phong.frag b/src/extras/shaders/es2/phong.frag deleted file mode 100644 index 6b8ab7111..000000000 --- a/src/extras/shaders/es2/phong.frag +++ /dev/null @@ -1,19 +0,0 @@ -#define FP highp - -uniform FP vec4 ka; // Ambient reflectivity -uniform FP vec4 kd; // Diffuse reflectivity -uniform FP vec4 ks; // Specular reflectivity -uniform FP float shininess; // Specular shininess factor - -uniform FP vec3 eyePosition; - -varying FP vec3 worldPosition; -varying FP vec3 worldNormal; - -#pragma include phong.inc.frag - -void main() -{ - FP vec3 worldView = normalize(eyePosition - worldPosition); - gl_FragColor = phongFunction(ka, kd, ks, shininess, worldPosition, worldView, worldNormal); -} diff --git a/src/extras/shaders/gl3/diffusemap.frag b/src/extras/shaders/gl3/diffusemap.frag deleted file mode 100644 index 34fef5a43..000000000 --- a/src/extras/shaders/gl3/diffusemap.frag +++ /dev/null @@ -1,24 +0,0 @@ -#version 150 core - -uniform vec4 ka; // Ambient reflectivity -uniform vec4 ks; // Specular reflectivity -uniform float shininess; // Specular shininess factor - -uniform vec3 eyePosition; - -uniform sampler2D diffuseTexture; - -in vec3 worldPosition; -in vec3 worldNormal; -in vec2 texCoord; - -out vec4 fragColor; - -#pragma include phong.inc.frag - -void main() -{ - vec4 diffuseTextureColor = texture( diffuseTexture, texCoord ); - vec3 worldView = normalize(eyePosition - worldPosition); - fragColor = phongFunction(ka, diffuseTextureColor, ks, shininess, worldPosition, worldView, worldNormal); -} diff --git a/src/extras/shaders/gl3/diffusespecularmap.frag b/src/extras/shaders/gl3/diffusespecularmap.frag deleted file mode 100644 index 8673a5121..000000000 --- a/src/extras/shaders/gl3/diffusespecularmap.frag +++ /dev/null @@ -1,26 +0,0 @@ -#version 150 core - -// TODO: Replace with a struct -uniform vec4 ka; // Ambient reflectivity -uniform float shininess; // Specular shininess factor - -uniform vec3 eyePosition; - -uniform sampler2D diffuseTexture; -uniform sampler2D specularTexture; - -in vec3 worldPosition; -in vec3 worldNormal; -in vec2 texCoord; - -out vec4 fragColor; - -#pragma include phong.inc.frag - -void main() -{ - vec4 diffuseTextureColor = texture( diffuseTexture, texCoord ); - vec4 specularTextureColor = texture( specularTexture, texCoord ); - vec3 worldView = normalize(eyePosition - worldPosition); - fragColor = phongFunction(ka, diffuseTextureColor, specularTextureColor, shininess, worldPosition, worldView, worldNormal); -} diff --git a/src/extras/shaders/gl3/normaldiffusemap.frag b/src/extras/shaders/gl3/normaldiffusemap.frag deleted file mode 100644 index bac776738..000000000 --- a/src/extras/shaders/gl3/normaldiffusemap.frag +++ /dev/null @@ -1,36 +0,0 @@ -#version 150 core - -in vec3 worldPosition; -in vec3 worldNormal; -in vec4 worldTangent; -in vec2 texCoord; - -uniform sampler2D diffuseTexture; -uniform sampler2D normalTexture; - -// TODO: Replace with a struct -uniform vec4 ka; // Ambient reflectivity -uniform vec4 ks; // Specular reflectivity -uniform float shininess; // Specular shininess factor - -uniform vec3 eyePosition; - -out vec4 fragColor; - -#pragma include phong.inc.frag -#pragma include coordinatesystems.inc - -void main() -{ - // Sample the textures at the interpolated texCoords - vec4 diffuseTextureColor = texture( diffuseTexture, texCoord ); - vec3 tNormal = 2.0 * texture( normalTexture, texCoord ).rgb - vec3( 1.0 ); - - mat3 tangentMatrix = calcWorldSpaceToTangentSpaceMatrix(worldNormal, worldTangent); - mat3 invertTangentMatrix = transpose(tangentMatrix); - - vec3 wNormal = normalize(invertTangentMatrix * tNormal); - - vec3 worldView = normalize(eyePosition - worldPosition); - fragColor = phongFunction(ka, diffuseTextureColor, ks, shininess, worldPosition, worldView, wNormal); -} diff --git a/src/extras/shaders/gl3/normaldiffusespecularmap.frag b/src/extras/shaders/gl3/normaldiffusespecularmap.frag deleted file mode 100644 index d96b9e747..000000000 --- a/src/extras/shaders/gl3/normaldiffusespecularmap.frag +++ /dev/null @@ -1,35 +0,0 @@ -#version 150 core - -in vec3 worldPosition; -in vec3 worldNormal; -in vec4 worldTangent; -in vec2 texCoord; - -out vec4 fragColor; - -uniform sampler2D diffuseTexture; -uniform sampler2D specularTexture; -uniform sampler2D normalTexture; - -uniform vec4 ka; // Ambient reflectivity -uniform float shininess; // Specular shininess factor -uniform vec3 eyePosition; - -#pragma include phong.inc.frag -#pragma include coordinatesystems.inc - -void main() -{ - // Sample the textures at the interpolated texCoords - vec4 diffuseTextureColor = texture( diffuseTexture, texCoord ); - vec4 specularTextureColor = texture( specularTexture, texCoord ); - vec3 tNormal = 2.0 * texture( normalTexture, texCoord ).rgb - vec3( 1.0 ); - - mat3 tangentMatrix = calcWorldSpaceToTangentSpaceMatrix(worldNormal, worldTangent); - mat3 invertTangentMatrix = transpose(tangentMatrix); - - vec3 wNormal = normalize(invertTangentMatrix * tNormal); - - vec3 worldView = normalize(eyePosition - worldPosition); - fragColor = phongFunction(ka, diffuseTextureColor, specularTextureColor, shininess, worldPosition, worldView, wNormal); -} diff --git a/src/extras/shaders/gl3/phong.frag b/src/extras/shaders/gl3/phong.frag deleted file mode 100644 index 3652672b5..000000000 --- a/src/extras/shaders/gl3/phong.frag +++ /dev/null @@ -1,21 +0,0 @@ -#version 150 core - -uniform vec4 ka; // Ambient reflectivity -uniform vec4 kd; // Diffuse reflectivity -uniform vec4 ks; // Specular reflectivity -uniform float shininess; // Specular shininess factor - -uniform vec3 eyePosition; - -in vec3 worldPosition; -in vec3 worldNormal; - -out vec4 fragColor; - -#pragma include phong.inc.frag - -void main() -{ - vec3 worldView = normalize(eyePosition - worldPosition); - fragColor = phongFunction(ka, kd, ks, shininess, worldPosition, worldView, worldNormal); -} diff --git a/src/extras/shaders/graphs/metalrough.frag.json b/src/extras/shaders/graphs/metalrough.frag.json index 825679d3e..b40044d1b 100644 --- a/src/extras/shaders/graphs/metalrough.frag.json +++ b/src/extras/shaders/graphs/metalrough.frag.json @@ -85,6 +85,7 @@ { "uuid": "{00000000-0000-0000-0000-000000000007}", "type": "sampleTexture", + "layers": ["baseColorMap"], "parameters": { "name": "baseColorMap" } diff --git a/src/extras/shaders/graphs/phong.frag.json b/src/extras/shaders/graphs/phong.frag.json new file mode 100644 index 000000000..dedeb1067 --- /dev/null +++ b/src/extras/shaders/graphs/phong.frag.json @@ -0,0 +1,466 @@ +{ + "nodes": [ + { + "uuid": "{00000000-0000-0000-0000-000000000001}", + "type": "input", + "parameters": { + "name": "worldPosition", + "qualifier": { + "type": "QShaderLanguage::StorageQualifier", + "value": "QShaderLanguage::Input" + }, + "type": { + "type": "QShaderLanguage::VariableType", + "value": "QShaderLanguage::Vec3" + } + } + }, + { + "uuid": "{00000000-0000-0000-0000-000000000002}", + "type": "eyePosition" + }, + { + "uuid": "{00000000-0000-0000-0000-000000000003}", + "type": "input", + "parameters": { + "name": "worldNormal", + "qualifier": { + "type": "QShaderLanguage::StorageQualifier", + "value": "QShaderLanguage::Input" + }, + "type": { + "type": "QShaderLanguage::VariableType", + "value": "QShaderLanguage::Vec3" + } + } + }, + { + "uuid": "{00000000-0000-0000-0000-000000000004}", + "type": "input", + "layers": ["normalTexture"], + "parameters": { + "name": "worldTangent", + "qualifier": { + "type": "QShaderLanguage::StorageQualifier", + "value": "QShaderLanguage::Input" + }, + "type": { + "type": "QShaderLanguage::VariableType", + "value": "QShaderLanguage::Vec4" + } + } + }, + { + "uuid": "{00000000-0000-0000-0000-000000000005}", + "type": "input", + "layers": ["diffuseTexture", "specularTexture", "normalTexture"], + "parameters": { + "name": "texCoord", + "qualifier": { + "type": "QShaderLanguage::StorageQualifier", + "value": "QShaderLanguage::Input" + }, + "type": { + "type": "QShaderLanguage::VariableType", + "value": "QShaderLanguage::Vec2" + } + } + }, + { + "uuid": "{00000000-0000-0000-0000-000000000006}", + "type": "input", + "parameters": { + "name": "ka", + "qualifier": { + "type": "QShaderLanguage::StorageQualifier", + "value": "QShaderLanguage::Uniform" + }, + "type": { + "type": "QShaderLanguage::VariableType", + "value": "QShaderLanguage::Vec4" + } + } + }, + { + "uuid": "{00000000-0000-0000-0000-000000000007}", + "type": "input", + "layers": ["diffuse"], + "parameters": { + "name": "kd", + "qualifier": { + "type": "QShaderLanguage::StorageQualifier", + "value": "QShaderLanguage::Uniform" + }, + "type": { + "type": "QShaderLanguage::VariableType", + "value": "QShaderLanguage::Vec4" + } + } + }, + { + "uuid": "{00000000-0000-0000-0000-000000000008}", + "type": "sampleTexture", + "layers": ["diffuseTexture"], + "parameters": { + "name": "diffuseTexture" + } + }, + { + "uuid": "{00000000-0000-0000-0000-000000000009}", + "type": "input", + "layers": ["specular"], + "parameters": { + "name": "ks", + "qualifier": { + "type": "QShaderLanguage::StorageQualifier", + "value": "QShaderLanguage::Uniform" + }, + "type": { + "type": "QShaderLanguage::VariableType", + "value": "QShaderLanguage::Vec4" + } + } + }, + { + "uuid": "{00000000-0000-0000-0000-000000000010}", + "layers": ["specularTexture"], + "type": "sampleTexture", + "parameters": { + "name": "specularTexture" + } + }, + { + "uuid": "{00000000-0000-0000-0000-000000000011}", + "type": "input", + "parameters": { + "name": "shininess", + "qualifier": { + "type": "QShaderLanguage::StorageQualifier", + "value": "QShaderLanguage::Uniform" + }, + "type": { + "type": "QShaderLanguage::VariableType", + "value": "QShaderLanguage::Float" + } + } + }, + { + "uuid": "{00000000-0000-0000-0000-000000000012}", + "type": "subtract", + "parameters": { + "type": { + "type": "QShaderLanguage::VariableType", + "value": "QShaderLanguage::Vec3" + } + } + }, + { + "uuid": "{00000000-0000-0000-0000-000000000013}", + "type": "normalize", + "parameters": { + "type": { + "type": "QShaderLanguage::VariableType", + "value": "QShaderLanguage::Vec3" + } + } + }, + { + "uuid": "{00000000-0000-0000-0000-000000000014}", + "type": "normalize", + "parameters": { + "type": { + "type": "QShaderLanguage::VariableType", + "value": "QShaderLanguage::Vec3" + } + } + }, + { + "uuid": "{00000000-0000-0000-0000-000000000015}", + "type": "worldSpaceToTangentSpaceMatrix", + "layers": ["normalTexture"] + }, + { + "uuid": "{00000000-0000-0000-0000-000000000016}", + "type": "transpose", + "layers": ["normalTexture"], + "parameters": { + "type": { + "type": "QShaderLanguage::VariableType", + "value": "QShaderLanguage::Mat3" + } + } + }, + { + "uuid": "{00000000-0000-0000-0000-000000000017}", + "type": "sampleTexture", + "layers": ["normalTexture"], + "parameters": { + "name": "normalTexture" + } + }, + { + "uuid": "{00000000-0000-0000-0000-000000000018}", + "type": "swizzle", + "layers": ["normalTexture"], + "parameters": { + "fields": "rgb", + "type": { + "type": "QShaderLanguage::VariableType", + "value": "QShaderLanguage::Vec3" + } + } + }, + { + "uuid": "{00000000-0000-0000-0000-000000000019}", + "type": "constant", + "layers": ["normalTexture"], + "parameters": { + "constant": "2.0", + "type": { + "type": "QShaderLanguage::VariableType", + "value": "QShaderLanguage::Float" + } + } + }, + { + "uuid": "{00000000-0000-0000-0000-000000000020}", + "type": "multiply", + "layers": ["normalTexture"], + "parameters": { + "type": { + "type": "QShaderLanguage::VariableType", + "value": "QShaderLanguage::Vec3" + } + } + }, + { + "uuid": "{00000000-0000-0000-0000-000000000021}", + "type": "constant", + "layers": ["normalTexture"], + "parameters": { + "constant": "1.0", + "type": { + "type": "QShaderLanguage::VariableType", + "value": "QShaderLanguage::Vec3" + } + } + }, + { + "uuid": "{00000000-0000-0000-0000-000000000022}", + "type": "subtract", + "parameters": { + "type": { + "type": "QShaderLanguage::VariableType", + "value": "QShaderLanguage::Vec3" + } + } + }, + { + "uuid": "{00000000-0000-0000-0000-000000000023}", + "type": "multiply", + "parameters": { + "type": { + "type": "QShaderLanguage::VariableType", + "value": "QShaderLanguage::Vec3" + } + } + }, + { + "uuid": "{00000000-0000-0000-0000-000000000024}", + "type": "phongFunction" + }, + { + "uuid": "{00000000-0000-0000-0000-000000000025}", + "type": "fragColor" + } + ], + "edges": [ + { + "sourceUuid": "{00000000-0000-0000-0000-000000000001}", + "sourcePort": "value", + "targetUuid": "{00000000-0000-0000-0000-000000000024}", + "targetPort": "worldPosition" + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000001}", + "sourcePort": "value", + "targetUuid": "{00000000-0000-0000-0000-000000000012}", + "targetPort": "subtrahend" + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000002}", + "sourcePort": "eyePosition", + "targetUuid": "{00000000-0000-0000-0000-000000000012}", + "targetPort": "minuend" + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000012}", + "sourcePort": "difference", + "targetUuid": "{00000000-0000-0000-0000-000000000013}", + "targetPort": "input" + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000013}", + "sourcePort": "output", + "targetUuid": "{00000000-0000-0000-0000-000000000024}", + "targetPort": "worldView" + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000003}", + "sourcePort": "value", + "targetUuid": "{00000000-0000-0000-0000-000000000014}", + "targetPort": "input", + "layers": ["normal"] + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000003}", + "sourcePort": "value", + "targetUuid": "{00000000-0000-0000-0000-000000000015}", + "targetPort": "worldNormal", + "layers": ["normalTexture"] + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000004}", + "sourcePort": "value", + "targetUuid": "{00000000-0000-0000-0000-000000000015}", + "targetPort": "worldTangent", + "layers": ["normalTexture"] + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000015}", + "sourcePort": "matrix", + "targetUuid": "{00000000-0000-0000-0000-000000000016}", + "targetPort": "input", + "layers": ["normalTexture"] + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000016}", + "sourcePort": "output", + "targetUuid": "{00000000-0000-0000-0000-000000000023}", + "targetPort": "first", + "layers": ["normalTexture"] + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000005}", + "sourcePort": "value", + "targetUuid": "{00000000-0000-0000-0000-000000000017}", + "targetPort": "coord", + "layers": ["normalTexture"] + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000017}", + "sourcePort": "color", + "targetUuid": "{00000000-0000-0000-0000-000000000018}", + "targetPort": "input", + "layers": ["normalTexture"] + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000018}", + "sourcePort": "output", + "targetUuid": "{00000000-0000-0000-0000-000000000020}", + "targetPort": "first", + "layers": ["normalTexture"] + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000019}", + "sourcePort": "value", + "targetUuid": "{00000000-0000-0000-0000-000000000020}", + "targetPort": "second", + "layers": ["normalTexture"] + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000020}", + "sourcePort": "product", + "targetUuid": "{00000000-0000-0000-0000-000000000022}", + "targetPort": "minuend", + "layers": ["normalTexture"] + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000021}", + "sourcePort": "value", + "targetUuid": "{00000000-0000-0000-0000-000000000022}", + "targetPort": "subtrahend", + "layers": ["normalTexture"] + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000022}", + "sourcePort": "difference", + "targetUuid": "{00000000-0000-0000-0000-000000000023}", + "targetPort": "second", + "layers": ["normalTexture"] + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000023}", + "sourcePort": "product", + "targetUuid": "{00000000-0000-0000-0000-000000000014}", + "targetPort": "input", + "layers": ["normalTexture"] + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000014}", + "sourcePort": "output", + "targetUuid": "{00000000-0000-0000-0000-000000000024}", + "targetPort": "worldNormal" + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000006}", + "sourcePort": "value", + "targetUuid": "{00000000-0000-0000-0000-000000000024}", + "targetPort": "ambient" + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000007}", + "sourcePort": "value", + "targetUuid": "{00000000-0000-0000-0000-000000000024}", + "targetPort": "diffuse", + "layers": ["diffuse"] + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000005}", + "sourcePort": "value", + "targetUuid": "{00000000-0000-0000-0000-000000000008}", + "targetPort": "coord", + "layers": ["diffuseTexture"] + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000008}", + "sourcePort": "color", + "targetUuid": "{00000000-0000-0000-0000-000000000024}", + "targetPort": "diffuse", + "layers": ["diffuseTexture"] + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000009}", + "sourcePort": "value", + "targetUuid": "{00000000-0000-0000-0000-000000000024}", + "targetPort": "specular", + "layers": ["specular"] + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000005}", + "sourcePort": "value", + "targetUuid": "{00000000-0000-0000-0000-000000000010}", + "targetPort": "coord", + "layers": ["specularTexture"] + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000010}", + "sourcePort": "color", + "targetUuid": "{00000000-0000-0000-0000-000000000024}", + "targetPort": "specular", + "layers": ["specularTexture"] + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000011}", + "sourcePort": "value", + "targetUuid": "{00000000-0000-0000-0000-000000000024}", + "targetPort": "shininess" + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000024}", + "sourcePort": "outputColor", + "targetUuid": "{00000000-0000-0000-0000-000000000025}", + "targetPort": "fragColor" + } + ] +} diff --git a/src/input/frontend/qmousehandler.cpp b/src/input/frontend/qmousehandler.cpp index 9f30810a9..895cbc49a 100644 --- a/src/input/frontend/qmousehandler.cpp +++ b/src/input/frontend/qmousehandler.cpp @@ -60,7 +60,7 @@ QMouseHandlerPrivate::QMouseHandlerPrivate() m_shareable = false; m_pressAndHoldTimer->setSingleShot(true); m_pressAndHoldTimer->setInterval(500); - QObject::connect(m_pressAndHoldTimer.data(), &QTimer::timeout, [this] { + QObject::connect(m_pressAndHoldTimer, &QTimer::timeout, [this] { emit q_func()->pressAndHold(m_lastPressedEvent.data()); }); } diff --git a/src/input/frontend/qmousehandler_p.h b/src/input/frontend/qmousehandler_p.h index 3b2f2284d..6c7f8b204 100644 --- a/src/input/frontend/qmousehandler_p.h +++ b/src/input/frontend/qmousehandler_p.h @@ -74,7 +74,7 @@ public: QMouseDevice *m_mouseDevice; bool m_containsMouse; - QScopedPointer<QTimer> m_pressAndHoldTimer; + QTimer *m_pressAndHoldTimer = nullptr; QMouseEventPtr m_lastPressedEvent; void mouseEvent(const QMouseEventPtr &event); diff --git a/src/plugins/geometryloaders/default/plygeometryloader.cpp b/src/plugins/geometryloaders/default/plygeometryloader.cpp index 8564b0423..9b3042ec5 100644 --- a/src/plugins/geometryloaders/default/plygeometryloader.cpp +++ b/src/plugins/geometryloaders/default/plygeometryloader.cpp @@ -217,6 +217,11 @@ bool PlyGeometryLoader::doLoad(QIODevice *ioDev, const QString &subMesh) return true; } +/*! + Read and parse the header of the PLY format file. + Returns \c false if one of the lines is wrongly + formatted. +*/ bool PlyGeometryLoader::parseHeader(QIODevice *ioDev) { Format format = FormatUnknown; @@ -424,6 +429,59 @@ bool PlyGeometryLoader::parseMesh(QIODevice *ioDev) return true; } +/*! + \enum Qt3DRender::PlyGeometryLoader::DataType + + Specifies the data type specified in the parsed file. + + \value Int8 + \value Uint8 + \value Int16 + \value Uint16 + \value Int32 + \value Uint32 + \value Float32 + \value Float64 + \value TypeList + \value TypeUnknown +*/ +/*! + \enum Qt3DRender::PlyGeometryLoader::Format + + Specifies the format mentioned in the header of the parsed file. + + \value FormatAscii + \value FormatBinaryLittleEndian + \value FormatBinaryBigEndian + \value FormatUnknown +*/ +/*! + \enum Qt3DRender::PlyGeometryLoader::ElementType + + Specifies the element type mentioned in the header of the file. + + \value ElementVertex + \value ElementFace + \value ElementUnknown + +*/ +/*! + \enum Qt3DRender::PlyGeometryLoader::PropertyType + + Specifies the property type from the PLY format file that has been loaded. + + \value PropertyVertexIndex Property name in header is \c vertex_index + \value PropertyX Property name in header is \c X + \value PropertyY Property name in header is \c Y + \value PropertyZ Property name in header is \c Z + \value PropertyNormalX Property name in header is \c NormalX + \value PropertyNormalY Property name in header is \c NormalY + \value PropertyNormalZ Property name in header is \c NormalZ + \value PropertyTextureU Property name in header is \c TextureU + \value PropertyTextureV Property name in header is \c TextureV + \value PropertyUnknown Property name in header is unknown + +*/ } // namespace Qt3DRender QT_END_NAMESPACE diff --git a/src/plugins/geometryloaders/fbx/fbxgeometryloader.cpp b/src/plugins/geometryloaders/fbx/fbxgeometryloader.cpp index 7b1b8e4ee..10870dde8 100644 --- a/src/plugins/geometryloaders/fbx/fbxgeometryloader.cpp +++ b/src/plugins/geometryloaders/fbx/fbxgeometryloader.cpp @@ -234,12 +234,20 @@ FbxGeometryLoader::~FbxGeometryLoader() m_manager->Destroy(); } -QGeometry *FbxGeometryLoader::geometry() const +/*! + Give the list of attributes that can be used to render + a 3D form. + Returns a pointer to the geometry object. +*/ +QGeometry *Qt3DRender::FbxGeometryLoader::geometry() const { return m_geometry; } -bool FbxGeometryLoader::load(QIODevice *ioDev, const QString &subMesh) +/*! + Load the specified \a subMesh using device \a ioDev. +*/ +bool Qt3DRender::FbxGeometryLoader::load(QIODevice *ioDev, const QString &subMesh) { if (m_scene) m_scene->Destroy(); @@ -310,6 +318,10 @@ bool FbxGeometryLoader::load(QIODevice *ioDev, const QString &subMesh) return wasImported; } +/*! + Traverse the node hierarchy and process the children of each + node. +*/ void FbxGeometryLoader::recurseNodes() { Q_ASSERT(m_scene); @@ -323,8 +335,12 @@ void FbxGeometryLoader::recurseNodes() processNode(node->GetChild(i)); } } - -void FbxGeometryLoader::processNode(FbxNode *node) +/*! + If the parameter \a node has the attribute eMesh, + process the Mesh. If not, process the children + of that node. +*/ +void Qt3DRender::FbxGeometryLoader::processNode(FbxNode *node) { auto attr = node->GetNodeAttribute(); if (!attr) @@ -347,8 +363,10 @@ void FbxGeometryLoader::processNode(FbxNode *node) for (int i = 0; i < node->GetChildCount(); ++i) processNode(node->GetChild(i)); } - -void FbxGeometryLoader::processMesh(FbxMesh *mesh) +/*! + Process all vertices of the specified \a mesh. +*/ +void Qt3DRender::FbxGeometryLoader::processMesh(FbxMesh *mesh) { const int normalCount = mesh->GetElementNormalCount(); const int polygonCount = mesh->GetPolygonCount(); diff --git a/src/plugins/geometryloaders/gltf/gltfgeometryloader.cpp b/src/plugins/geometryloaders/gltf/gltfgeometryloader.cpp index 0a2d38687..ecb3824c9 100644 --- a/src/plugins/geometryloaders/gltf/gltfgeometryloader.cpp +++ b/src/plugins/geometryloaders/gltf/gltfgeometryloader.cpp @@ -350,8 +350,6 @@ void GLTFGeometryLoader::processJSONBufferViewV2(const QJsonObject &json) case GL_ARRAY_BUFFER: ty = Qt3DRender::QBuffer::VertexBuffer; break; case GL_ELEMENT_ARRAY_BUFFER: ty = Qt3DRender::QBuffer::IndexBuffer; break; default: - qCWarning(GLTFGeometryLoaderLog, "buffer %d unsupported target: %d", - bufferIndex, target); return; } diff --git a/src/render/backend/nodemanagers.cpp b/src/render/backend/nodemanagers.cpp index bcaa6f3bf..f5de64dae 100644 --- a/src/render/backend/nodemanagers.cpp +++ b/src/render/backend/nodemanagers.cpp @@ -144,6 +144,7 @@ NodeManagers::~NodeManagers() delete m_renderStateManager; delete m_renderNodesManager; delete m_armatureManager; + delete m_skeletonManager; delete m_jointManager; } diff --git a/src/render/backend/renderer.cpp b/src/render/backend/renderer.cpp index 1ba178a3a..eb64677c1 100644 --- a/src/render/backend/renderer.cpp +++ b/src/render/backend/renderer.cpp @@ -1768,7 +1768,8 @@ bool Renderer::executeCommandsSubmission(const RenderView *rv) { Profiling::GLTimeRecorder recorder(Profiling::UniformUpdate); //// Update program uniforms - m_graphicsContext->setParameters(command->m_parameterPack); + if (!m_graphicsContext->setParameters(command->m_parameterPack)) + allCommandsIssued = false; } //// OpenGL State diff --git a/src/render/backend/renderview.cpp b/src/render/backend/renderview.cpp index 07311824e..bdf7605db 100644 --- a/src/render/backend/renderview.cpp +++ b/src/render/backend/renderview.cpp @@ -596,7 +596,12 @@ QVector<RenderCommand *> RenderView::buildDrawRenderCommands(const QVector<Entit for (const RenderPassParameterData &passData : renderPassData) { // Add the RenderPass Parameters RenderCommand *command = new RenderCommand(); - command->m_depth = m_data.m_eyePos.distanceToPoint(entity->worldBoundingVolume()->center()); + + // Project the camera-to-object-center vector onto the camera + // view vector. This gives a depth value suitable as the key + // for BackToFront sorting. + command->m_depth = QVector3D::dotProduct(entity->worldBoundingVolume()->center() - m_data.m_eyePos, m_data.m_eyeViewDir); + command->m_geometry = geometryHandle; command->m_geometryRenderer = geometryRendererHandle; command->m_material = materialHandle; @@ -754,6 +759,12 @@ void RenderView::updateMatrices() const QMatrix4x4 inverseWorldTransform = viewMatrix().inverted(); const QVector3D eyePosition(inverseWorldTransform.column(3)); setEyePosition(eyePosition); + + // Get the viewing direction of the camera. Use the normal matrix to + // ensure non-uniform scale works too. + QMatrix3x3 normalMat = m_data.m_viewMatrix.normalMatrix(); + // dir = normalize(QVector3D(0, 0, -1) * normalMat) + setEyeViewDirection(QVector3D(-normalMat(2, 0), -normalMat(2, 1), -normalMat(2, 2)).normalized()); } } diff --git a/src/render/backend/renderview_p.h b/src/render/backend/renderview_p.h index 8c733fc3a..342afd64c 100644 --- a/src/render/backend/renderview_p.h +++ b/src/render/backend/renderview_p.h @@ -162,6 +162,9 @@ public: inline void setEyePosition(const QVector3D &eyePos) Q_DECL_NOTHROW { m_data.m_eyePos = eyePos; } inline QVector3D eyePosition() const Q_DECL_NOTHROW { return m_data.m_eyePos; } + inline void setEyeViewDirection(const QVector3D &dir) Q_DECL_NOTHROW { m_data.m_eyeViewDir = dir; } + inline QVector3D eyeViewDirection() const Q_DECL_NOTHROW { return m_data.m_eyeViewDir; } + inline void appendLayerFilter(const Qt3DCore::QNodeId layerFilterId) Q_DECL_NOTHROW { m_data.m_layerFilterIds.push_back(layerFilterId); } inline Qt3DCore::QNodeIdVector layerFilters() const Q_DECL_NOTHROW { return m_data.m_layerFilterIds; } @@ -262,6 +265,7 @@ public: Qt3DCore::QNodeIdVector m_layerFilterIds; QVector<Qt3DRender::QSortPolicy::SortType> m_sortingTypes; QVector3D m_eyePos; + QVector3D m_eyeViewDir; Qt3DCore::QNodeIdVector m_proximityFilterIds; }; diff --git a/src/render/framegraph/qbuffercapture.cpp b/src/render/framegraph/qbuffercapture.cpp index 602ad5d6d..d1d301077 100644 --- a/src/render/framegraph/qbuffercapture.cpp +++ b/src/render/framegraph/qbuffercapture.cpp @@ -58,6 +58,11 @@ QBufferCapturePrivate::QBufferCapturePrivate() } +/*! + \class Qt3DRender::QBufferCapture + \inmodule Qt3DRender + \brief Exchanges buffer data between GPU and CPU. +*/ QBufferCapture::QBufferCapture(Qt3DCore::QNode *parent) : QFrameGraphNode(*new QBufferCapturePrivate, parent) { diff --git a/src/render/framegraph/qframegraphnodecreatedchange.cpp b/src/render/framegraph/qframegraphnodecreatedchange.cpp index 1f04a099d..ef51d5228 100644 --- a/src/render/framegraph/qframegraphnodecreatedchange.cpp +++ b/src/render/framegraph/qframegraphnodecreatedchange.cpp @@ -48,6 +48,12 @@ QFrameGraphNodeCreatedChangeBasePrivate::QFrameGraphNodeCreatedChangeBasePrivate { } +/*! + \class Qt3DRender::QFrameGraphNodeCreatedChangeBase + \inmodule Qt3DRender + + \brief A base class for changes in the FrameGraphNode. +*/ QFrameGraphNodeCreatedChangeBase::QFrameGraphNodeCreatedChangeBase(const QFrameGraphNode *node) : Qt3DCore::QNodeCreatedChangeBase(*new QFrameGraphNodeCreatedChangeBasePrivate(node), node) { diff --git a/src/render/framegraph/qsortpolicy.cpp b/src/render/framegraph/qsortpolicy.cpp index cdacd63f2..e5a6e096c 100644 --- a/src/render/framegraph/qsortpolicy.cpp +++ b/src/render/framegraph/qsortpolicy.cpp @@ -88,11 +88,20 @@ QSortPolicyPrivate::QSortPolicyPrivate() /*! \enum QSortPolicy::SortType - This enum type describes sort types that can be employed - \value StateChangeCost sort the objects so as to minimize the cost of changing from the currently rendered state - \value BackToFront sort the objects from back to front inverted z order + This enum type describes the available sort types. + + \value StateChangeCost sort the objects so as to minimize the cost of + changing from the currently rendered state + + \value BackToFront sort the objects from back to front based on inverted z + order. More accurately, the sorting key is the z component of the + projection of the camera-to-object-center vector onto the camera's view + vector. + \value Material sort the objects based on their material value - \value FrontToBack sort the objects from front to back + + \value FrontToBack sort the objects from front to back. The opposite of + BackToFront. */ /*! diff --git a/src/render/graphicshelpers/graphicscontext.cpp b/src/render/graphicshelpers/graphicscontext.cpp index 814429504..9a20c77e7 100644 --- a/src/render/graphicshelpers/graphicscontext.cpp +++ b/src/render/graphicshelpers/graphicscontext.cpp @@ -1175,10 +1175,11 @@ void GraphicsContext::setRenderer(Renderer *renderer) // It will be easier if the QGraphicContext applies the QUniformPack // than the other way around -void GraphicsContext::setParameters(ShaderParameterPack ¶meterPack) +bool GraphicsContext::setParameters(ShaderParameterPack ¶meterPack) { // Activate textures and update TextureUniform in the pack // with the correct textureUnit + bool allValid = true; // Set the pinned texture of the previous material texture // to pinable so that we should easily find an available texture unit @@ -1198,6 +1199,10 @@ void GraphicsContext::setParameters(ShaderParameterPack ¶meterPack) Q_ASSERT(texUniform.valueType() == UniformValue::TextureValue); const int texUnit = activateTexture(TextureScopeMaterial, t); texUniform.data<UniformValue::Texture>()->textureId = texUnit; + // if the texture data from generators may not be available yet, + // make sure that the next frame is rendered + if (texUnit == -1) + allValid = false; } } } @@ -1218,11 +1223,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 } @@ -1238,11 +1238,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 } @@ -1262,6 +1257,8 @@ void GraphicsContext::setParameters(ShaderParameterPack ¶meterPack) applyUniform(uniform, v); } + // if not all data is valid, the next frame will be rendered immediately + return allValid; } void GraphicsContext::readBuffer(GLenum mode) diff --git a/src/render/graphicshelpers/graphicscontext_p.h b/src/render/graphicshelpers/graphicscontext_p.h index 1b9438a6f..b07a11c7e 100644 --- a/src/render/graphicshelpers/graphicscontext_p.h +++ b/src/render/graphicshelpers/graphicscontext_p.h @@ -177,7 +177,7 @@ public: void memoryBarrier(QMemoryBarrier::Operations barriers); - void setParameters(ShaderParameterPack ¶meterPack); + bool setParameters(ShaderParameterPack ¶meterPack); void readBuffer(GLenum mode); void drawBuffer(GLenum mode); diff --git a/src/render/texture/qabstracttexture.cpp b/src/render/texture/qabstracttexture.cpp index b4d33acf2..76886f438 100644 --- a/src/render/texture/qabstracttexture.cpp +++ b/src/render/texture/qabstracttexture.cpp @@ -120,6 +120,209 @@ void QAbstractTexturePrivate::setDataFunctor(const QTextureGeneratorPtr &generat */ /*! + \enum Qt3DRender::QAbstractTexture::TextureFormat + + This list describes all possible texture formats + + \value NoFormat + GL_NONE + \value Automatic + automatically_determines_format + \value R8_UNorm + GL_R8 + \value RG8_UNorm + GL_RG8 + \value RGB8_UNorm + GL_RGB8 + \value RGBA8_UNorm + GL_RGBA8 + \value R16_UNorm + GL_R16 + \value RG16_UNorm + GL_RG16 + \value RGB16_UNorm + GL_RGB16 + \value RGBA16_UNorm + GL_RGBA16 + \value R8_SNorm + GL_R8_SNORM + \value RG8_SNorm + GL_RG8_SNORM + \value RGB8_SNorm + GL_RGB8_SNORM + \value RGBA8_SNorm + GL_RGBA8_SNORM + \value R16_SNorm + GL_R16_SNORM + \value RG16_SNorm + GL_RG16_SNORM + \value RGB16_SNorm + GL_RGB16_SNORM + \value RGBA16_SNorm + GL_RGBA16_SNORM + \value R8U + GL_R8UI + \value RG8U + GL_RG8UI + \value RGB8U + GL_RGB8UI + \value RGBA8U + GL_RGBA8UI + \value R16U + GL_R16UI + \value RG16U + GL_RG16UI + \value RGB16U + GL_RGB16UI + \value RGBA16U + GL_RGBA16UI + \value R32U + GL_R32UI + \value RG32U + GL_RG32UI + \value RGB32U + GL_RGB32UI + \value RGBA32U + GL_RGBA32UI + \value R8I + GL_R8I + \value RG8I + GL_RG8I + \value RGB8I + GL_RGB8I + \value RGBA8I + GL_RGBA8I + \value R16I + GL_R16I + \value RG16I + GL_RG16I + \value RGB16I + GL_RGB16I + \value RGBA16I + GL_RGBA16I + \value R32I + GL_R32I + \value RG32I + GL_RG32I + \value RGB32I + GL_RGB32I + \value RGBA32I + GL_RGBA32I + \value R16F + GL_R16F + \value RG16F + GL_RG16F + \value RGB16F + GL_RGB16F + \value RGBA16F + GL_RGBA16F + \value R32F + GL_R32F + \value RG32F + GL_RG32F + \value RGB32F + GL_RGB32F + \value RGBA32F + GL_RGBA32F + \value RGB9E5 + GL_RGB9_E5 + \value RG11B10F + GL_R11F_G11F_B10F + \value RG3B2 + GL_R3_G3_B2 + \value R5G6B5 + GL_RGB565 + \value RGB5A1 + GL_RGB5_A1 + \value RGBA4 + GL_RGBA4 + \value RGB10A2 + GL_RGB10_A2UI + \value D16 + GL_DEPTH_COMPONENT16 + \value D24 + GL_DEPTH_COMPONENT24 + \value D24S8 + GL_DEPTH24_STENCIL8 + \value D32 + GL_DEPTH_COMPONENT32 + \value D32F + GL_DEPTH_COMPONENT32F + \value D32FS8X24 + GL_DEPTH32F_STENCIL8 + \value RGB_DXT1 + GL_COMPRESSED_RGB_S3TC_DXT1_EXT + \value RGBA_DXT1 + GL_COMPRESSED_RGBA_S3TC_DXT1_EXT + \value RGBA_DXT3 + GL_COMPRESSED_RGBA_S3TC_DXT3_EXT + \value RGBA_DXT5 + GL_COMPRESSED_RGBA_S3TC_DXT5_EXT + \value R_ATI1N_UNorm + GL_COMPRESSED_RED_RGTC1 + \value R_ATI1N_SNorm + GL_COMPRESSED_SIGNED_RED_RGTC1 + \value RG_ATI2N_UNorm + GL_COMPRESSED_RG_RGTC2 + \value RG_ATI2N_SNorm + GL_COMPRESSED_SIGNED_RG_RGTC2 + \value RGB_BP_UNSIGNED_FLOAT + GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB + \value RGB_BP_SIGNED_FLOAT + GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB + \value RGB_BP_UNorm + GL_COMPRESSED_RGBA_BPTC_UNORM_ARB + \value R11_EAC_UNorm + GL_COMPRESSED_R11_EAC + \value R11_EAC_SNorm + GL_COMPRESSED_SIGNED_R11_EAC + \value RG11_EAC_UNorm + GL_COMPRESSED_RG11_EAC + \value RG11_EAC_SNorm + GL_COMPRESSED_SIGNED_RG11_EAC + \value RGB8_ETC2 + GL_COMPRESSED_RGB8_ETC2 + \value SRGB8_ETC2 + GL_COMPRESSED_SRGB8_ETC2 + \value RGB8_PunchThrough_Alpha1_ETC2 + GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 + \value SRGB8_PunchThrough_Alpha1_ETC2 + GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 + \value RGBA8_ETC2_EAC + GL_COMPRESSED_RGBA8_ETC2_EAC + \value SRGB8_Alpha8_ETC2_EAC + GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC + \value RGB8_ETC1 + GL_ETC1_RGB8_OES + \value SRGB8 + GL_SRGB8 + \value SRGB8_Alpha8 + GL_SRGB8_ALPHA8 + \value SRGB_DXT1 + GL_COMPRESSED_SRGB_S3TC_DXT1_EXT + \value SRGB_Alpha_DXT1 + GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT + \value SRGB_Alpha_DXT3 + GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT + \value SRGB_Alpha_DXT5 + GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT + \value SRGB_BP_UNorm + GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB + \value DepthFormat + GL_DEPTH_COMPONENT + \value AlphaFormat + GL_ALPHA + \value RGBFormat + GL_RGB + \value RGBAFormat + GL_RGBA + \value LuminanceFormat + GL_LUMINANCE + \value LuminanceAlphaFormat + 0x190A +*/ + +/*! * The constructor creates a new QAbstractTexture::QAbstractTexture * instance with the specified \a parent. */ @@ -164,6 +367,9 @@ void QAbstractTexture::setSize(int w, int h, int d) Holds the width of the texture provider. */ +/*! + Set the width of the texture provider to \a width. +*/ void QAbstractTexture::setWidth(int width) { Q_D(QAbstractTexture); @@ -178,6 +384,9 @@ void QAbstractTexture::setWidth(int width) Holds the height of the texture provider. */ +/*! + Set the height to \a height. +*/ void QAbstractTexture::setHeight(int height) { Q_D(QAbstractTexture); @@ -192,6 +401,9 @@ void QAbstractTexture::setHeight(int height) Holds the depth of the texture provider. */ +/*! + Set the depth of the texture to \a depth. +*/ void QAbstractTexture::setDepth(int depth) { Q_D(QAbstractTexture); @@ -237,6 +449,9 @@ int QAbstractTexture::depth() const \note this has a meaning only for texture providers that have 3D or array target formats. */ +/*! + Set the maximum layer count to \a layers. +*/ void QAbstractTexture::setLayers(int layers) { Q_D(QAbstractTexture); @@ -267,6 +482,9 @@ int QAbstractTexture::layers() const \note this has a meaning only for texture providers that have multisample formats. */ +/*! + Set the number of samples per texel to \a samples. +*/ void QAbstractTexture::setSamples(int samples) { Q_D(QAbstractTexture); @@ -293,6 +511,9 @@ int QAbstractTexture::samples() const Holds the format of the texture provider. */ +/*! + Set the texture format to \a format. +*/ void QAbstractTexture::setFormat(TextureFormat format) { Q_D(QAbstractTexture); @@ -303,7 +524,7 @@ void QAbstractTexture::setFormat(TextureFormat format) } /*! - \return the texture provider's format. + Returns the texture provider's format. */ QAbstractTexture::TextureFormat QAbstractTexture::format() const { @@ -316,6 +537,20 @@ QAbstractTexture::TextureFormat QAbstractTexture::format() const Holds the current status of the texture provider. */ + +/*! + \enum Qt3DRender::QAbstractTexture::Status + + Contains the status of the texture provider. + + \value None + \value Loading + \value Ready + \value Error +*/ +/*! + Set the status of the texture provider to the specified \a status. +*/ void QAbstractTexture::setStatus(Status status) { Q_D(QAbstractTexture); @@ -326,7 +561,7 @@ void QAbstractTexture::setStatus(Status status) } /*! - * \return the current status + * \return the current status of the texture provider. */ QAbstractTexture::Status QAbstractTexture::status() const { @@ -341,6 +576,38 @@ QAbstractTexture::Status QAbstractTexture::status() const \note The target format can only be set once. */ +/*! + \enum Qt3DRender::QAbstractTexture::Target + + \value TargetAutomatic + Target will be determined by the Qt3D engine + \value Target1D + GL_TEXTURE_1D + \value Target1DArray + GL_TEXTURE_1D_ARRAY + \value Target2D + GL_TEXTURE_2D + \value Target2DArray + GL_TEXTURE_2D_ARRAY + \value Target3D + GL_TEXTURE_3D + \value TargetCubeMap + GL_TEXTURE_CUBE_MAP + \value TargetCubeMapArray + GL_TEXTURE_CUBE_MAP_ARRAY + \value Target2DMultisample + GL_TEXTURE_2D_MULTISAMPLE + \value Target2DMultisampleArray + GL_TEXTURE_2D_MULTISAMPLE_ARRAY + \value TargetRectangle + GL_TEXTURE_RECTANGLE + \value TargetBuffer + GL_TEXTURE_BUFFER +*/ + +/*! + Returns the target format of the texture provider. +*/ QAbstractTexture::Target QAbstractTexture::target() const { Q_D(const QAbstractTexture); @@ -412,6 +679,10 @@ QVector<QAbstractTextureImage *> QAbstractTexture::textureImages() const Holds whether the texture provider should auto generate mipmaps. */ +/*! + Boolean parameter \a gen sets a flag indicating whether the + texture provider should generate mipmaps or not. +*/ void QAbstractTexture::setGenerateMipMaps(bool gen) { Q_D(QAbstractTexture); @@ -432,6 +703,9 @@ bool QAbstractTexture::generateMipMaps() const Holds the minification filter of the texture provider. */ +/*! + Set the minification filter to the specified value \a f. +*/ void QAbstractTexture::setMinificationFilter(Filter f) { Q_D(QAbstractTexture); @@ -440,12 +714,32 @@ void QAbstractTexture::setMinificationFilter(Filter f) emit minificationFilterChanged(f); } } +/*! + \enum Qt3DRender::QAbstractTexture::Filter + + Holds the filter type of the texture provider. + \value Nearest + GL_NEAREST + \value Linear + GL_LINEAR + \value NearestMipMapNearest + GL_NEAREST_MIPMAP_NEAREST + \value NearestMipMapLinear + GL_NEAREST_MIPMAP_LINEAR + \value LinearMipMapNearest + GL_LINEAR_MIPMAP_NEAREST + \value LinearMipMapLinear + GL_LINEAR_MIPMAP_LINEAR +*/ /*! \property Qt3DRender::QAbstractTexture::magnificationFilter Holds the magnification filter of the texture provider. */ +/*! + Set the magnification filter to \a f. +*/ void QAbstractTexture::setMagnificationFilter(Filter f) { Q_D(QAbstractTexture); @@ -472,6 +766,9 @@ QAbstractTexture::Filter QAbstractTexture::magnificationFilter() const Holds the wrap mode of the texture provider. */ +/*! + Set the wrapmode to the value specified in \a wrapMode. +*/ void QAbstractTexture::setWrapMode(const QTextureWrapMode &wrapMode) { Q_D(QAbstractTexture); @@ -509,6 +806,9 @@ QTextureWrapMode *QAbstractTexture::wrapMode() Holds the maximum anisotropy of the texture provider. */ +/*! + Sets the maximum anisotropy to \a anisotropy. +*/ void QAbstractTexture::setMaximumAnisotropy(float anisotropy) { Q_D(QAbstractTexture); @@ -532,6 +832,9 @@ float QAbstractTexture::maximumAnisotropy() const Holds the comparison function of the texture provider. */ +/*! + Set the comparison function to \a function. +*/ void QAbstractTexture::setComparisonFunction(QAbstractTexture::ComparisonFunction function) { Q_D(QAbstractTexture); @@ -555,6 +858,9 @@ QAbstractTexture::ComparisonFunction QAbstractTexture::comparisonFunction() cons Holds the comparison mode of the texture provider. */ +/*! + Set the comparison mode to \a mode. +*/ void QAbstractTexture::setComparisonMode(QAbstractTexture::ComparisonMode mode) { Q_D(QAbstractTexture); diff --git a/src/render/texture/qpaintedtextureimage.cpp b/src/render/texture/qpaintedtextureimage.cpp index af0e74d4b..8d2dd1436 100644 --- a/src/render/texture/qpaintedtextureimage.cpp +++ b/src/render/texture/qpaintedtextureimage.cpp @@ -51,7 +51,7 @@ namespace Qt3DRender { \class Qt3DRender::QPaintedTextureImage \inmodule Qt3DRender \since 5.8 - \brief A QAbstractTextureImage that can be written through a QPainter + \brief A QAbstractTextureImage that can be written through a QPainter. A QPaintedTextureImage provides a way to specify a texture image (and thus an OpenGL texture) through a QPainter. The width and height of the @@ -205,6 +205,11 @@ void QPaintedTextureImage::update(const QRect &rect) d->repaint(); } +/*! + \fn Qt3DRender::QPaintedTextureImage::paint(QPainter *painter) + + Paints the texture image with the specified QPainter object \a painter. +*/ QTextureImageDataGeneratorPtr QPaintedTextureImage::dataGenerator() const { Q_D(const QPaintedTextureImage); diff --git a/src/render/texture/qtexture.cpp b/src/render/texture/qtexture.cpp index e583345c8..b9e1d83fe 100644 --- a/src/render/texture/qtexture.cpp +++ b/src/render/texture/qtexture.cpp @@ -1241,6 +1241,11 @@ void QTextureLoaderPrivate::updateGenerator() } /*! + \class Qt3DRender::QTextureLoader + \inmodule Qt3DRender + \brief Handles the texture loading and setting the texture's properties. +*/ +/*! * Constructs a new Qt3DRender::QTextureLoader instance with \a parent as parent. * * Note that by default, if not contradicted by the file metadata, the loaded texture @@ -1276,8 +1281,10 @@ QTextureLoader::~QTextureLoader() } /*! - * \return the current texture source. - */ + \property QTextureLoader::source + + Returns the current texture source. +*/ QUrl QTextureLoader::source() const { Q_D(const QTextureLoader); diff --git a/src/render/texture/qtexturegenerator.cpp b/src/render/texture/qtexturegenerator.cpp index 32b785128..5e350af2d 100644 --- a/src/render/texture/qtexturegenerator.cpp +++ b/src/render/texture/qtexturegenerator.cpp @@ -43,6 +43,10 @@ QT_BEGIN_NAMESPACE namespace Qt3DRender { +/*! class Qt3DRender::QTextureGenerator + \inmodule Qt3DRender + \brief Generates the necessary information to create an OpenGL texture image. +*/ QTextureGenerator::~QTextureGenerator() { } @@ -53,6 +57,16 @@ QTextureGenerator::~QTextureGenerator() \inmodule Qt3DRender \brief Provides the image data for a texture. */ +/*! + \fn QTextureDataPtr Qt3DRender::QTextureGenerator::operator()() + + Returns the texture data. +*/ +/*! + \fn bool Qt3DRender::QTextureGenerator::operator==(const QTextureGenerator &other) const = 0 + + Compare these texture data to \a other. Returns \c true if both are equal. +*/ } // Qt3DRender QT_END_NAMESPACE diff --git a/src/render/texture/qtexturewrapmode.cpp b/src/render/texture/qtexturewrapmode.cpp index ee831f409..cb9272895 100644 --- a/src/render/texture/qtexturewrapmode.cpp +++ b/src/render/texture/qtexturewrapmode.cpp @@ -108,6 +108,8 @@ void QTextureWrapMode::setX(WrapMode x) } /*! + \property QTextureWrapMode::x + Returns the wrap mode of the x dimension. */ QTextureWrapMode::WrapMode QTextureWrapMode::x() const @@ -117,6 +119,19 @@ QTextureWrapMode::WrapMode QTextureWrapMode::x() const } /*! + \enum Qt3DRender::QTextureWrapMode::WrapMode + + Specifies the type of text wrapping. + Possible values: + + \value Repeat + \value MirroredRepeat + \value ClampToEdge + \value ClampToBorder +*/ + + +/*! Sets the wrap mode of the y dimension to \a y. \note this is not available on 1D textures. */ @@ -130,6 +145,8 @@ void QTextureWrapMode::setY(WrapMode y) } /*! + \property QTextureWrapMode::y + Returns the wrap mode of the y dimension. */ QTextureWrapMode::WrapMode QTextureWrapMode::y() const @@ -152,6 +169,8 @@ void QTextureWrapMode::setZ(WrapMode z) } /*! + \property QTextureWrapMode::z + Returns the wrap mode of the z dimension. */ QTextureWrapMode::WrapMode QTextureWrapMode::z() const diff --git a/tests/auto/animation/animationutils/tst_animationutils.cpp b/tests/auto/animation/animationutils/tst_animationutils.cpp index 1e55a29b5..584406a71 100644 --- a/tests/auto/animation/animationutils/tst_animationutils.cpp +++ b/tests/auto/animation/animationutils/tst_animationutils.cpp @@ -549,336 +549,137 @@ private Q_SLOTS: delete handler; } - void checkLocalTimeFromGlobalTime_data() + void checkLocalTimeFromElapsedTime_data() { - QTest::addColumn<double>("globalTime"); - QTest::addColumn<double>("globalStartTime"); + QTest::addColumn<double>("elapsedTime"); + QTest::addColumn<double>("currentTime"); QTest::addColumn<double>("playbackRate"); QTest::addColumn<double>("duration"); QTest::addColumn<int>("loopCount"); + QTest::addColumn<int>("currentLoop"); QTest::addColumn<double>("expectedLocalTime"); QTest::addColumn<int>("expectedCurrentLoop"); - double globalTime; - double globalStartTime; + double elapsedTime; + double currentTime; double playbackRate; double duration; int loopCount; + int currentLoop; double expectedLocalTime; int expectedCurrentLoop; - globalTime = 0.0; - globalStartTime = 0.0; + elapsedTime = 0.0; + currentTime = 0.0; playbackRate = 1.0; duration = 1.0; loopCount = 1; + currentLoop = 0; expectedLocalTime = 0.0; expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = 0") - << globalTime << globalStartTime << playbackRate << duration << loopCount + QTest::newRow("simple, t_current = 0, t_elapsed = 0, loop_current = 0") + << elapsedTime << currentTime << playbackRate << duration << loopCount << currentLoop << expectedLocalTime << expectedCurrentLoop; - globalTime = 0.5; - globalStartTime = 0.0; + elapsedTime = 0.5; + currentTime = 0.0; playbackRate = 1.0; duration = 1.0; loopCount = 1; + currentLoop = 0; expectedLocalTime = 0.5; expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = 0.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount + QTest::newRow("simple, t_current = 0, t_elapsed = 0.5, loop_current = 0") + << elapsedTime << currentTime << playbackRate << duration << loopCount << currentLoop << expectedLocalTime << expectedCurrentLoop; - globalTime = 1.0; - globalStartTime = 0.0; + elapsedTime = 1.5; + currentTime = 0.0; playbackRate = 1.0; duration = 1.0; loopCount = 1; + currentLoop = 0; expectedLocalTime = 1.0; expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = 1.0") - << globalTime << globalStartTime << playbackRate << duration << loopCount + QTest::newRow("simple, t_current = 0, t_elapsed = 1.5, loop_current = 0") + << elapsedTime << currentTime << playbackRate << duration << loopCount << currentLoop << expectedLocalTime << expectedCurrentLoop; - globalTime = -0.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 1; - expectedLocalTime = 0.0; - expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = -0.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedLocalTime << expectedCurrentLoop; - - globalTime = 1.5; - globalStartTime = 0.0; + elapsedTime = 0.5; + currentTime = 0.6; playbackRate = 1.0; duration = 1.0; loopCount = 1; + currentLoop = 0; expectedLocalTime = 1.0; expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = 1.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedLocalTime << expectedCurrentLoop; - - globalTime = 0.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 2; - expectedLocalTime = 0.5; - expectedCurrentLoop = 0; - QTest::newRow("simple, loopCount = 2, t_global = 0.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount + QTest::newRow("simple, t_current = 0.5, t_elapsed = 0.6, loop_current = 0") + << elapsedTime << currentTime << playbackRate << duration << loopCount << currentLoop << expectedLocalTime << expectedCurrentLoop; - globalTime = 1.5; - globalStartTime = 0.0; + elapsedTime = 0.5; + currentTime = 0.6; playbackRate = 1.0; duration = 1.0; loopCount = 2; - expectedLocalTime = 0.5; + currentLoop = 0; + expectedLocalTime = 0.1; expectedCurrentLoop = 1; - QTest::newRow("simple, loopCount = 2, t_global = 1.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount + QTest::newRow("simple, t_current = 0.5, t_elapsed = 0.6, loop_current = 0, loop_count = 2") + << elapsedTime << currentTime << playbackRate << duration << loopCount << currentLoop << expectedLocalTime << expectedCurrentLoop; - globalTime = 3.5; - globalStartTime = 0.0; + elapsedTime = 0.5; + currentTime = 0.6; playbackRate = 1.0; - duration = 2.0; - loopCount = 2; - expectedLocalTime = 1.5; - expectedCurrentLoop = 1; - QTest::newRow("duration = 2, loopCount = 2, t_global = 3.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedLocalTime << expectedCurrentLoop; - - globalTime = 4.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 2.0; + duration = 1.0; loopCount = 2; - expectedLocalTime = 2.0; - expectedCurrentLoop = 1; - QTest::newRow("duration = 2, loopCount = 2, t_global = 4.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount + currentLoop = 1; + expectedLocalTime = 1.0; + expectedCurrentLoop = 1; // We clamp at end of final loop + QTest::newRow("simple, t_current = 0.5, t_elapsed = 0.6, loop_current = 1, loop_count = 2") + << elapsedTime << currentTime << playbackRate << duration << loopCount << currentLoop << expectedLocalTime << expectedCurrentLoop; - globalTime = 1.5; - globalStartTime = 0.0; - playbackRate = 1.0; + elapsedTime = 0.5; + currentTime = 0.6; + playbackRate = 0.1; duration = 1.0; - loopCount = -1; - expectedLocalTime = 0.5; + loopCount = 2; + currentLoop = 1; + expectedLocalTime = 0.65; expectedCurrentLoop = 1; - QTest::newRow("simple, loopCount = inf, t_global = 1.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedLocalTime << expectedCurrentLoop; - - globalTime = 10.2; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = -1; - expectedLocalTime = 0.2; - expectedCurrentLoop = 10; - QTest::newRow("simple, loopCount = inf, t_global = 10.2") - << globalTime << globalStartTime << playbackRate << duration << loopCount + QTest::newRow("simple, t_current = 0.5, t_elapsed = 0.6, loop_current = 1, loop_count = 2") + << elapsedTime << currentTime << playbackRate << duration << loopCount << currentLoop << expectedLocalTime << expectedCurrentLoop; } - void checkLocalTimeFromGlobalTime() + void checkLocalTimeFromElapsedTime() { // GIVEN - QFETCH(double, globalTime); - QFETCH(double, globalStartTime); + QFETCH(double, elapsedTime); + QFETCH(double, currentTime); QFETCH(double, playbackRate); QFETCH(double, duration); QFETCH(int, loopCount); + QFETCH(int, currentLoop); QFETCH(double, expectedLocalTime); QFETCH(int, expectedCurrentLoop); // WHEN - int actualCurrentLoop = 0; - double actualLocalTime = localTimeFromGlobalTime(globalTime, - globalStartTime, - playbackRate, - duration, - loopCount, - actualCurrentLoop); + int actualCurrentLoop = currentLoop; + double actualLocalTime = localTimeFromElapsedTime(currentTime, + elapsedTime, + playbackRate, + duration, + loopCount, + actualCurrentLoop); // THEN QCOMPARE(actualCurrentLoop, expectedCurrentLoop); QCOMPARE(actualLocalTime, expectedLocalTime); } - void checkPhaseFromGlobalTime_data() - { - QTest::addColumn<double>("globalTime"); - QTest::addColumn<double>("globalStartTime"); - QTest::addColumn<double>("playbackRate"); - QTest::addColumn<double>("duration"); - QTest::addColumn<int>("loopCount"); - QTest::addColumn<double>("expectedPhase"); - QTest::addColumn<int>("expectedCurrentLoop"); - - double globalTime; - double globalStartTime; - double playbackRate; - double duration; - int loopCount; - double expectedPhase; - int expectedCurrentLoop; - - globalTime = 0.0; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 1; - expectedPhase = 0.0; - expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = 0") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 0.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 1; - expectedPhase = 0.5; - expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = 0.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 1.0; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 1; - expectedPhase = 1.0; - expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = 1.0") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = -0.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 1; - expectedPhase = 0.0; - expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = -0.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 1.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 1; - expectedPhase = 1.0; - expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = 1.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 0.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 2; - expectedPhase = 0.5; - expectedCurrentLoop = 0; - QTest::newRow("simple, loopCount = 2, t_global = 0.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 1.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 2; - expectedPhase = 0.5; - expectedCurrentLoop = 1; - QTest::newRow("simple, loopCount = 2, t_global = 1.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 3.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 2.0; - loopCount = 2; - expectedPhase = 0.75; - expectedCurrentLoop = 1; - QTest::newRow("duration = 2, loopCount = 2, t_global = 3.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 4.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 2.0; - loopCount = 2; - expectedPhase = 1.0; - expectedCurrentLoop = 1; - QTest::newRow("duration = 2, loopCount = 2, t_global = 4.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 1.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = -1; - expectedPhase = 0.5; - expectedCurrentLoop = 1; - QTest::newRow("simple, loopCount = inf, t_global = 1.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 10.2; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = -1; - expectedPhase = 0.2; - expectedCurrentLoop = 10; - QTest::newRow("simple, loopCount = inf, t_global = 10.2") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - } - - void checkPhaseFromGlobalTime() - { - // GIVEN - QFETCH(double, globalTime); - QFETCH(double, globalStartTime); - QFETCH(double, playbackRate); - QFETCH(double, duration); - QFETCH(int, loopCount); - QFETCH(double, expectedPhase); - QFETCH(int, expectedCurrentLoop); - - // WHEN - int actualCurrentLoop = 0; - double actualPhase = phaseFromGlobalTime(globalTime, - globalStartTime, - playbackRate, - duration, - loopCount, - actualCurrentLoop); - - // THEN - QCOMPARE(actualCurrentLoop, expectedCurrentLoop); - QCOMPARE(actualPhase, expectedPhase); - } - void checkPreparePropertyChanges_data() { QTest::addColumn<Qt3DCore::QNodeId>("animatorId"); @@ -1880,11 +1681,13 @@ private Q_SLOTS: const qint64 globalStartTimeNS = 0; const int loops = 1; auto animator = createClipAnimator(handler, globalStartTimeNS, loops); - const qint64 globalTimeNS = 0; - animatorData = evaluationDataForAnimator(animator, clock, globalTimeNS); // Tested elsewhere + animator->setCurrentLoop(0); + clipData.currentLoop = animator->currentLoop(); + const qint64 elapsedTimeNS = 0; + animatorData = evaluationDataForAnimator(animator, clock, elapsedTimeNS); // Tested elsewhere - clipData.localTime = localTimeFromGlobalTime(animatorData.globalTime, - animatorData.startTime, + clipData.localTime = localTimeFromElapsedTime(animatorData.currentTime, + animatorData.elapsedTime, animatorData.playbackRate, clip->duration(), animatorData.loopCount, @@ -1901,18 +1704,20 @@ private Q_SLOTS: const qint64 globalStartTimeNS = 0; const int loops = 1; auto animator = createClipAnimator(handler, globalStartTimeNS, loops); - const qint64 globalTimeNS = (clip->duration() + 1.0) * 1.0e9; // +1 to ensure beyond end of clip - animatorData = evaluationDataForAnimator(animator, nullptr, globalTimeNS); // Tested elsewhere + animator->setCurrentLoop(0); + clipData.currentLoop = animator->currentLoop(); + const qint64 elapsedTimeNS = (clip->duration()+1)*1e09; // +1 to ensure beyond end + animatorData = evaluationDataForAnimator(animator, nullptr, elapsedTimeNS); // Tested elsewhere - clipData.localTime = localTimeFromGlobalTime(animatorData.globalTime, - animatorData.startTime, + clipData.localTime = localTimeFromElapsedTime(animatorData.currentTime, + animatorData.elapsedTime, animatorData.playbackRate, clip->duration(), animatorData.loopCount, clipData.currentLoop); // Tested elsewhere clipData.isFinalFrame = true; - QTest::newRow("clip1.json, globalTime = duration") + QTest::newRow("clip1.json, elapsedTime = duration + 1") << handler << clip << animatorData << clipData; } @@ -1922,18 +1727,43 @@ private Q_SLOTS: const qint64 globalStartTimeNS = 0; const int loops = 0; // Infinite loops auto animator = createClipAnimator(handler, globalStartTimeNS, loops); - const qint64 globalTimeNS = 2.0 * clip->duration() * 1.0e9; - animatorData = evaluationDataForAnimator(animator, clock, globalTimeNS); // Tested elsewhere + animator->setCurrentLoop(0); + clipData.currentLoop = animator->currentLoop(); + const qint64 elapsedTimeNS = 2.0 * clip->duration() * 1.0e9; + animatorData = evaluationDataForAnimator(animator, clock, elapsedTimeNS); // Tested elsewhere - clipData.localTime = localTimeFromGlobalTime(animatorData.globalTime, - animatorData.startTime, + clipData.localTime = localTimeFromElapsedTime(animatorData.currentTime, + animatorData.elapsedTime, animatorData.playbackRate, clip->duration(), animatorData.loopCount, clipData.currentLoop); // Tested elsewhere clipData.isFinalFrame = false; - QTest::newRow("clip1.json, globalTime = 2 * duration, loops = infinite") + QTest::newRow("clip1.json, elapsedTime = 2 * duration, loops = infinite") + << handler << clip << animatorData << clipData; + } + + { + handler = new Handler(); + clip = createAnimationClipLoader(handler, QUrl("qrc:/clip1.json")); + const qint64 globalStartTimeNS = 0; + const int loops = 2; + auto animator = createClipAnimator(handler, globalStartTimeNS, loops); + animator->setCurrentLoop(0); + clipData.currentLoop = animator->currentLoop(); + const qint64 elapsedTimeNS = (2.0 * clip->duration() + 1.0) * 1.0e9; // +1 to ensure beyond end of clip + animatorData = evaluationDataForAnimator(animator, nullptr, elapsedTimeNS); // Tested elsewhere + + clipData.localTime = localTimeFromElapsedTime(animatorData.currentTime, + animatorData.elapsedTime, + animatorData.playbackRate, + clip->duration(), + animatorData.loopCount, + clipData.currentLoop); // Tested elsewhere + clipData.isFinalFrame = true; + + QTest::newRow("clip1.json, elapsedTime = 2 * duration + 1, loops = 2") << handler << clip << animatorData << clipData; } @@ -1943,18 +1773,20 @@ private Q_SLOTS: const qint64 globalStartTimeNS = 0; const int loops = 2; auto animator = createClipAnimator(handler, globalStartTimeNS, loops); - const qint64 globalTimeNS = (2.0 * clip->duration() + 1.0) * 1.0e9; // +1 to ensure beyond end of clip - animatorData = evaluationDataForAnimator(animator, nullptr, globalTimeNS); // Tested elsewhere + animator->setCurrentLoop(1); + clipData.currentLoop = animator->currentLoop(); + const qint64 elapsedTimeNS = (clip->duration() + 1.0) * 1.0e9; // +1 to ensure beyond end of clip + animatorData = evaluationDataForAnimator(animator, nullptr, elapsedTimeNS); // Tested elsewhere - clipData.localTime = localTimeFromGlobalTime(animatorData.globalTime, - animatorData.startTime, + clipData.localTime = localTimeFromElapsedTime(animatorData.currentTime, + animatorData.elapsedTime, animatorData.playbackRate, clip->duration(), animatorData.loopCount, clipData.currentLoop); // Tested elsewhere clipData.isFinalFrame = true; - QTest::newRow("clip1.json, globalTime = 2 * duration + 1, loops = 2") + QTest::newRow("clip1.json, elapsedTime = duration + 1, loops = 2, current_loop = 1") << handler << clip << animatorData << clipData; } } @@ -1983,12 +1815,12 @@ private Q_SLOTS: { QTest::addColumn<Handler *>("handler"); QTest::addColumn<ClipAnimator *>("animator"); - QTest::addColumn<qint64>("globalTimeNS"); + QTest::addColumn<qint64>("elapsedTime"); QTest::addColumn<AnimatorEvaluationData>("expectedAnimatorData"); Handler *handler; ClipAnimator *animator; - qint64 globalTimeNS; + qint64 elapsedTimeNS; AnimatorEvaluationData expectedAnimatorData; { @@ -1996,15 +1828,14 @@ private Q_SLOTS: const qint64 globalStartTimeNS = 0; const int loops = 1; animator = createClipAnimator(handler, globalStartTimeNS, loops); - globalTimeNS = 0; + elapsedTimeNS = 0; expectedAnimatorData.loopCount = loops; expectedAnimatorData.playbackRate = 1.0; // hard-wired for now - expectedAnimatorData.startTime = 0.0; - expectedAnimatorData.globalTime = 0.0; + expectedAnimatorData.elapsedTime = 0.0; - QTest::newRow("globalStartTime = 0, globalTime = 0, loops = 1") - << handler << animator << globalTimeNS << expectedAnimatorData; + QTest::newRow("globalStartTime = 0, elapsedTime = 0, loops = 1") + << handler << animator << elapsedTimeNS << expectedAnimatorData; } { @@ -2012,15 +1843,14 @@ private Q_SLOTS: const qint64 globalStartTimeNS = 0; const int loops = 5; animator = createClipAnimator(handler, globalStartTimeNS, loops); - globalTimeNS = 0; + elapsedTimeNS = 0; expectedAnimatorData.loopCount = loops; expectedAnimatorData.playbackRate = 1.0; // hard-wired for now - expectedAnimatorData.startTime = 0.0; - expectedAnimatorData.globalTime = 0.0; + expectedAnimatorData.elapsedTime = 0.0; - QTest::newRow("globalStartTime = 0, globalTime = 0, loops = 5") - << handler << animator << globalTimeNS << expectedAnimatorData; + QTest::newRow("globalStartTime = 0, elapsedTime = 0, loops = 5") + << handler << animator << elapsedTimeNS << expectedAnimatorData; } { @@ -2028,15 +1858,14 @@ private Q_SLOTS: const qint64 globalStartTimeNS = 0; const int loops = 1; animator = createClipAnimator(handler, globalStartTimeNS, loops); - globalTimeNS = 5000000000; + elapsedTimeNS = 5000000000; expectedAnimatorData.loopCount = loops; expectedAnimatorData.playbackRate = 1.0; // hard-wired for now - expectedAnimatorData.startTime = 0.0; - expectedAnimatorData.globalTime = 5.0; + expectedAnimatorData.elapsedTime = 5.0; - QTest::newRow("globalStartTime = 0, globalTime = 5, loops = 1") - << handler << animator << globalTimeNS << expectedAnimatorData; + QTest::newRow("globalStartTime = 0, elapsedTime = 5, loops = 1") + << handler << animator << elapsedTimeNS << expectedAnimatorData; } { @@ -2044,15 +1873,14 @@ private Q_SLOTS: const qint64 globalStartTimeNS = 3000000000; const int loops = 1; animator = createClipAnimator(handler, globalStartTimeNS, loops); - globalTimeNS = 5000000000; + elapsedTimeNS = 2000000000; expectedAnimatorData.loopCount = loops; expectedAnimatorData.playbackRate = 1.0; // hard-wired for now - expectedAnimatorData.startTime = 3.0; - expectedAnimatorData.globalTime = 5.0; + expectedAnimatorData.elapsedTime = 2.0; - QTest::newRow("globalStartTime = 3, globalTime = 5, loops = 1") - << handler << animator << globalTimeNS << expectedAnimatorData; + QTest::newRow("globalStartTime = 3, elapsedTime = 2, loops = 1") + << handler << animator << elapsedTimeNS << expectedAnimatorData; } } @@ -2061,17 +1889,16 @@ private Q_SLOTS: // GIVEN QFETCH(Handler *, handler); QFETCH(ClipAnimator *, animator); - QFETCH(qint64, globalTimeNS); + QFETCH(qint64, elapsedTime); QFETCH(AnimatorEvaluationData, expectedAnimatorData); // WHEN - AnimatorEvaluationData actualAnimatorData = evaluationDataForAnimator(animator, nullptr, globalTimeNS); + AnimatorEvaluationData actualAnimatorData = evaluationDataForAnimator(animator, nullptr, elapsedTime); // THEN QCOMPARE(actualAnimatorData.loopCount, expectedAnimatorData.loopCount); QVERIFY(fuzzyCompare(actualAnimatorData.playbackRate, expectedAnimatorData.playbackRate) == true); - QVERIFY(fuzzyCompare(actualAnimatorData.startTime, expectedAnimatorData.startTime) == true); - QVERIFY(fuzzyCompare(actualAnimatorData.globalTime, expectedAnimatorData.globalTime) == true); + QVERIFY(fuzzyCompare(actualAnimatorData.elapsedTime, expectedAnimatorData.elapsedTime) == true); // Cleanup delete handler; diff --git a/tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp b/tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp index 3265de167..c0e1581f9 100644 --- a/tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp +++ b/tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp @@ -63,7 +63,8 @@ private Q_SLOTS: QCOMPARE(backendBlendedClipAnimator.blendTreeRootId(), Qt3DCore::QNodeId()); QCOMPARE(backendBlendedClipAnimator.mapperId(), Qt3DCore::QNodeId()); QCOMPARE(backendBlendedClipAnimator.isRunning(), false); - QCOMPARE(backendBlendedClipAnimator.startTime(), 0); + QCOMPARE(backendBlendedClipAnimator.lastLocalTime(), 0.0); + QCOMPARE(backendBlendedClipAnimator.nsSincePreviousFrame(0), 0); QCOMPARE(backendBlendedClipAnimator.currentLoop(), 0); QCOMPARE(backendBlendedClipAnimator.loops(), 1); @@ -82,6 +83,7 @@ private Q_SLOTS: backendBlendedClipAnimator.setMapperId(Qt3DCore::QNodeId::createId()); backendBlendedClipAnimator.setRunning(true); backendBlendedClipAnimator.setStartTime(28); + backendBlendedClipAnimator.setLastLocalTime(0.28); backendBlendedClipAnimator.cleanup(); // THEN @@ -89,7 +91,8 @@ private Q_SLOTS: QCOMPARE(backendBlendedClipAnimator.blendTreeRootId(), Qt3DCore::QNodeId()); QCOMPARE(backendBlendedClipAnimator.mapperId(), Qt3DCore::QNodeId()); QCOMPARE(backendBlendedClipAnimator.isRunning(), false); - QCOMPARE(backendBlendedClipAnimator.startTime(), 0); + QCOMPARE(backendBlendedClipAnimator.lastLocalTime(), 0.0); + QCOMPARE(backendBlendedClipAnimator.nsSincePreviousFrame(0), 0); QCOMPARE(backendBlendedClipAnimator.currentLoop(), 0); QCOMPARE(backendBlendedClipAnimator.loops(), 1); } diff --git a/tests/auto/core/qjoint/tst_qjoint.cpp b/tests/auto/core/qjoint/tst_qjoint.cpp index a63d275c5..ec1a45f90 100644 --- a/tests/auto/core/qjoint/tst_qjoint.cpp +++ b/tests/auto/core/qjoint/tst_qjoint.cpp @@ -65,6 +65,7 @@ private Q_SLOTS: { // WHEN + joint.setToIdentity(); QSignalSpy spy(&joint, SIGNAL(scaleChanged(QVector3D))); const QVector3D newValue(2.5f, 2.0f, 1.3f); joint.setScale(newValue); @@ -85,6 +86,7 @@ private Q_SLOTS: { // WHEN + joint.setToIdentity(); QSignalSpy spy(&joint, SIGNAL(rotationChanged(QQuaternion))); const auto newValue = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, 45.0f); joint.setRotation(newValue); @@ -105,6 +107,7 @@ private Q_SLOTS: { // WHEN + joint.setToIdentity(); QSignalSpy spy(&joint, SIGNAL(translationChanged(QVector3D))); const QVector3D newValue(1.0f, 2.0f, 3.0f); joint.setTranslation(newValue); @@ -125,6 +128,7 @@ private Q_SLOTS: { // WHEN + joint.setToIdentity(); QSignalSpy spy(&joint, SIGNAL(inverseBindMatrixChanged(QMatrix4x4))); QMatrix4x4 newValue; newValue.scale(3.5f); @@ -146,6 +150,7 @@ private Q_SLOTS: { // WHEN + joint.setToIdentity(); QSignalSpy spy(&joint, SIGNAL(rotationChanged(QQuaternion))); QSignalSpy spyEuler(&joint, SIGNAL(rotationXChanged(float))); const auto newValue = 45.0f; @@ -176,6 +181,7 @@ private Q_SLOTS: { // WHEN + joint.setToIdentity(); QSignalSpy spy(&joint, SIGNAL(rotationChanged(QQuaternion))); QSignalSpy spyEuler(&joint, SIGNAL(rotationYChanged(float))); const auto newValue = 45.0f; @@ -206,6 +212,7 @@ private Q_SLOTS: { // WHEN + joint.setToIdentity(); QSignalSpy spy(&joint, SIGNAL(rotationChanged(QQuaternion))); QSignalSpy spyEuler(&joint, SIGNAL(rotationZChanged(float))); const auto newValue = 45.0f; diff --git a/tests/auto/render/filtercompatibletechniquejob/BLACKLIST b/tests/auto/render/filtercompatibletechniquejob/BLACKLIST new file mode 100644 index 000000000..22cb59fab --- /dev/null +++ b/tests/auto/render/filtercompatibletechniquejob/BLACKLIST @@ -0,0 +1,5 @@ +#[checkRunRendererNotRunning] +#windows +#[checkRunRendererRunning] +#QTBUG-64271 +windows diff --git a/tests/auto/render/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp b/tests/auto/render/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp index c26394c69..83e816861 100644 --- a/tests/auto/render/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp +++ b/tests/auto/render/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp @@ -85,7 +85,8 @@ public: Qt3DRender::Render::NodeManagers *nodeManagers() const { - return d_func()->m_renderer->nodeManagers(); + return d_func()->m_renderer + ? d_func()->m_renderer->nodeManagers() : nullptr; } void initializeRenderer() @@ -198,7 +199,11 @@ private Q_SLOTS: Qt3DRender::TestAspect testAspect(buildTestScene()); // WHEN - backendFilterCompatibleTechniqueJob.setManager(testAspect.nodeManagers()->techniqueManager()); + Qt3DRender::Render::NodeManagers *nodeManagers = testAspect.nodeManagers(); + QVERIFY(nodeManagers); + Qt3DRender::Render::TechniqueManager *techniqueManager = nodeManagers->techniqueManager(); + QVERIFY(techniqueManager); + backendFilterCompatibleTechniqueJob.setManager(techniqueManager); backendFilterCompatibleTechniqueJob.setRenderer(testAspect.renderer()); testAspect.initializeRenderer(); testAspect.renderer()->shutdown(); @@ -223,7 +228,11 @@ private Q_SLOTS: Qt3DRender::TestAspect testAspect(buildTestScene()); // WHEN - backendFilterCompatibleTechniqueJob.setManager(testAspect.nodeManagers()->techniqueManager()); + Qt3DRender::Render::NodeManagers *nodeManagers = testAspect.nodeManagers(); + QVERIFY(nodeManagers); + Qt3DRender::Render::TechniqueManager *techniqueManager = nodeManagers->techniqueManager(); + QVERIFY(techniqueManager); + backendFilterCompatibleTechniqueJob.setManager(techniqueManager); backendFilterCompatibleTechniqueJob.setRenderer(testAspect.renderer()); testAspect.initializeRenderer(); diff --git a/tests/benchmarks/render/layerfiltering/tst_bench_layerfiltering.cpp b/tests/benchmarks/render/layerfiltering/tst_bench_layerfiltering.cpp index d1ef468b2..2f88043a4 100644 --- a/tests/benchmarks/render/layerfiltering/tst_bench_layerfiltering.cpp +++ b/tests/benchmarks/render/layerfiltering/tst_bench_layerfiltering.cpp @@ -107,7 +107,7 @@ Qt3DCore::QEntity *buildTestScene(int layersCount, Qt3DCore::QEntity *entity = new Qt3DCore::QEntity(root); if (layersCount > 0) - entity->addComponent(layers.at(QRandomGenerator::bounded(layersCount))); + entity->addComponent(layers.at(QRandomGenerator::global()->bounded(layersCount))); if (!alwaysEnabled && i % 128 == 0) entity->setEnabled(false); diff --git a/tests/manual/animation-keyframe-blendtree/main.qml b/tests/manual/animation-keyframe-blendtree/main.qml index 23aba4b79..3d7fa47e5 100644 --- a/tests/manual/animation-keyframe-blendtree/main.qml +++ b/tests/manual/animation-keyframe-blendtree/main.qml @@ -75,16 +75,36 @@ DefaultSceneEntity { shininess: 50 }, ObjectPicker { - onClicked: blendedAnimator.running = true + onClicked: { + if (blendedAnimator.running == false) { + blendedAnimator.running = true; + } else { + switch (pick.button) { + case PickEvent.RightButton: + animatorClock.playbackRate *= 2.0; + break; + case PickEvent.LeftButton: + animatorClock.playbackRate /= 2.0; + break; + default: + break; + } + } + } }, BlendedClipAnimator { id: blendedAnimator - loops: 2 + loops: 3 + + clock: Clock { + id: animatorClock + playbackRate: 0.5 + } onRunningChanged: console.log("running = " + running) blendTree: LerpClipBlend { - blendFactor: 0.2 + blendFactor: 0.8 startClip: ClipBlendValue { clip: AnimationClipLoader { source: "sliding-cube.json" } } diff --git a/tests/manual/animation-keyframe-simple/main.qml b/tests/manual/animation-keyframe-simple/main.qml index 79fb75fbd..9246f2467 100644 --- a/tests/manual/animation-keyframe-simple/main.qml +++ b/tests/manual/animation-keyframe-simple/main.qml @@ -75,13 +75,33 @@ DefaultSceneEntity { shininess: 50 }, ObjectPicker { - onClicked: animator.running = true + onClicked: { + if (animator.running == false) { + animator.running = true; + } else { + switch (pick.button) { + case PickEvent.RightButton: + animationClock.playbackRate *= 2.0; + break; + case PickEvent.LeftButton: + animationClock.playbackRate /= 2.0; + break; + default: + break; + } + } + } }, ClipAnimator { id: animator loops: 3 onRunningChanged: console.log("running = " + running) + clock: Clock { + id: animationClock + playbackRate: 1 + } + clip: AnimationClipLoader { source: "cubeanimation.json" onDurationChanged: console.log("duration = " + duration) 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); |