summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Nichols <andy.nichols@qt.io>2017-11-13 13:56:39 +0100
committerAndy Nichols <andy.nichols@qt.io>2017-11-13 13:56:39 +0100
commitab2d05d06b37fe875d360f92fe67e103ae17d80b (patch)
tree770a5c8a08f80baafe96cc349686ce6deadcd8b7
parent18ce3e68e6db896e9c01cf4df0dd7e9fa714b37c (diff)
parent764b715b5f682ddb1bdb52f67b5a35d85af7ccf1 (diff)
Merge remote-tracking branch 'origin/5.10' into dev
-rw-r--r--dist/changes-5.9.239
-rw-r--r--examples/qt3d/planets-qml/images/solarsystemscope/qt_attribution.json2
-rw-r--r--examples/qt3d/scene2d/main.qml4
-rw-r--r--examples/qt3d/widgets-scene3d/main.cpp14
-rw-r--r--src/animation/backend/animationclip.cpp58
-rw-r--r--src/animation/backend/animationutils.cpp103
-rw-r--r--src/animation/backend/animationutils_p.h35
-rw-r--r--src/animation/backend/backend.pri6
-rw-r--r--src/animation/backend/blendedclipanimator.cpp27
-rw-r--r--src/animation/backend/blendedclipanimator_p.h13
-rw-r--r--src/animation/backend/clipanimator.cpp23
-rw-r--r--src/animation/backend/clipanimator_p.h12
-rw-r--r--src/animation/backend/evaluateblendclipanimatorjob.cpp30
-rw-r--r--src/animation/backend/evaluateblendclipanimatorjob_p.h3
-rw-r--r--src/animation/backend/evaluateclipanimatorjob.cpp14
-rw-r--r--src/animation/backend/evaluateclipanimatorjob_p.h3
-rw-r--r--src/animation/backend/fcurve_p.h25
-rw-r--r--src/animation/backend/gltfimporter.cpp852
-rw-r--r--src/animation/backend/gltfimporter_p.h232
-rw-r--r--src/animation/frontend/qanimationclip.cpp6
-rw-r--r--src/animation/frontend/qclipanimator.cpp1
-rw-r--r--src/core/transforms/qjoint.cpp54
-rw-r--r--src/core/transforms/qjoint.h1
-rw-r--r--src/extras/defaults/defaults.pri1
-rw-r--r--src/extras/defaults/qabstractcameracontroller.cpp2
-rw-r--r--src/extras/defaults/qdiffusemapmaterial.cpp21
-rw-r--r--src/extras/defaults/qdiffusemapmaterial_p.h3
-rw-r--r--src/extras/defaults/qdiffusespecularmapmaterial.cpp21
-rw-r--r--src/extras/defaults/qdiffusespecularmapmaterial_p.h3
-rw-r--r--src/extras/defaults/qmetalroughmaterial.cpp2
-rw-r--r--src/extras/defaults/qnormaldiffusemapalphamaterial.cpp19
-rw-r--r--src/extras/defaults/qnormaldiffusemapmaterial.cpp21
-rw-r--r--src/extras/defaults/qnormaldiffusemapmaterial_p.h3
-rw-r--r--src/extras/defaults/qnormaldiffusespecularmapmaterial.cpp21
-rw-r--r--src/extras/defaults/qnormaldiffusespecularmapmaterial_p.h3
-rw-r--r--src/extras/defaults/qorbitcameracontroller.cpp2
-rw-r--r--src/extras/defaults/qphongalphamaterial.cpp21
-rw-r--r--src/extras/defaults/qphongalphamaterial_p.h3
-rw-r--r--src/extras/defaults/qphongmaterial.cpp21
-rw-r--r--src/extras/defaults/qphongmaterial_p.h3
-rw-r--r--src/extras/defaults/qt3dwindow.cpp28
-rw-r--r--src/extras/extras.qrc11
-rw-r--r--src/extras/shaders/es2/diffusemap.frag22
-rw-r--r--src/extras/shaders/es2/diffusespecularmap.frag24
-rw-r--r--src/extras/shaders/es2/normaldiffusemap.frag34
-rw-r--r--src/extras/shaders/es2/normaldiffusespecularmap.frag35
-rw-r--r--src/extras/shaders/es2/phong.frag19
-rw-r--r--src/extras/shaders/gl3/diffusemap.frag24
-rw-r--r--src/extras/shaders/gl3/diffusespecularmap.frag26
-rw-r--r--src/extras/shaders/gl3/normaldiffusemap.frag36
-rw-r--r--src/extras/shaders/gl3/normaldiffusespecularmap.frag35
-rw-r--r--src/extras/shaders/gl3/phong.frag21
-rw-r--r--src/extras/shaders/graphs/metalrough.frag.json1
-rw-r--r--src/extras/shaders/graphs/phong.frag.json466
-rw-r--r--src/input/frontend/qmousehandler.cpp2
-rw-r--r--src/input/frontend/qmousehandler_p.h2
-rw-r--r--src/plugins/geometryloaders/default/plygeometryloader.cpp58
-rw-r--r--src/plugins/geometryloaders/fbx/fbxgeometryloader.cpp30
-rw-r--r--src/plugins/geometryloaders/gltf/gltfgeometryloader.cpp2
-rw-r--r--src/render/backend/nodemanagers.cpp1
-rw-r--r--src/render/backend/renderer.cpp3
-rw-r--r--src/render/backend/renderview.cpp13
-rw-r--r--src/render/backend/renderview_p.h4
-rw-r--r--src/render/framegraph/qbuffercapture.cpp5
-rw-r--r--src/render/framegraph/qframegraphnodecreatedchange.cpp6
-rw-r--r--src/render/framegraph/qsortpolicy.cpp17
-rw-r--r--src/render/graphicshelpers/graphicscontext.cpp19
-rw-r--r--src/render/graphicshelpers/graphicscontext_p.h2
-rw-r--r--src/render/texture/qabstracttexture.cpp310
-rw-r--r--src/render/texture/qpaintedtextureimage.cpp7
-rw-r--r--src/render/texture/qtexture.cpp11
-rw-r--r--src/render/texture/qtexturegenerator.cpp14
-rw-r--r--src/render/texture/qtexturewrapmode.cpp19
-rw-r--r--tests/auto/animation/animationutils/tst_animationutils.cpp435
-rw-r--r--tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp7
-rw-r--r--tests/auto/core/qjoint/tst_qjoint.cpp7
-rw-r--r--tests/auto/render/filtercompatibletechniquejob/BLACKLIST5
-rw-r--r--tests/auto/render/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp15
-rw-r--r--tests/benchmarks/render/layerfiltering/tst_bench_layerfiltering.cpp2
-rw-r--r--tests/manual/animation-keyframe-blendtree/main.qml26
-rw-r--r--tests/manual/animation-keyframe-simple/main.qml22
-rw-r--r--tests/manual/bigscene-cpp/entity.cpp33
-rw-r--r--tests/manual/bigscene-cpp/entity.h14
-rw-r--r--tests/manual/bigscene-cpp/main.cpp30
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 &currentLoop)
+double localTimeFromElapsedTime(double t_current_local,
+ double t_elapsed_global,
+ double playbackRate,
+ double duration,
+ int loopCount,
+ int &currentLoop)
{
- 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 &currentLoop)
+double phaseFromElapsedTime(double t_current_local,
+ double t_elapsed_global,
+ double playbackRate,
+ double duration,
+ int loopCount,
+ int &currentLoop)
{
- 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 &currentLoop);
+double localTimeFromElapsedTime(double t_current_local, double t_elapsed_global,
+ double playbackRate, double duration,
+ int loopCount, int &currentLoop);
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 &currentLoop);
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 &parameterPack)
+bool GraphicsContext::setParameters(ShaderParameterPack &parameterPack)
{
// 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 &parameterPack)
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 &parameterPack)
// 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 &parameterPack)
// 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 &parameterPack)
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 &parameterPack);
+ bool setParameters(ShaderParameterPack &parameterPack);
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);