diff options
author | Liang Qi <liang.qi@qt.io> | 2017-10-05 20:34:44 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2017-10-05 20:47:59 +0200 |
commit | 8e67fb1f148b2f3c795d230faad7aee20389878a (patch) | |
tree | 34358c0ee9ab4816d20d58d84bdab20093b1d423 | |
parent | ba5bc93b95d28a28a72e60281f765a6f031129a5 (diff) | |
parent | d4fb24c0871320667640f100b743f34f702db6cf (diff) |
Merge remote-tracking branch 'origin/5.10' into dev
Conflicts:
src/animation/backend/channelmapper_p.h
Change-Id: I4e0f59c6648925ba45d30ccc2405524a9e901a0e
129 files changed, 7694 insertions, 2281 deletions
diff --git a/examples/qt3d/advancedcustommaterial/shaders/es2/water.frag b/examples/qt3d/advancedcustommaterial/shaders/es2/water.frag index ea54a87f1..f471504fa 100644 --- a/examples/qt3d/advancedcustommaterial/shaders/es2/water.frag +++ b/examples/qt3d/advancedcustommaterial/shaders/es2/water.frag @@ -1,6 +1,8 @@ #define FP highp varying FP vec3 worldPosition; +varying FP vec3 worldNormal; +varying FP vec4 worldTangent; varying FP vec2 texCoord; varying FP vec2 waveTexCoord; varying FP vec2 movtexCoord; @@ -9,7 +11,6 @@ varying FP vec2 skyTexCoord; varying FP vec3 vpos; -varying FP mat3 tangentMatrix; varying FP vec3 color; uniform FP sampler2D diffuseTexture; @@ -23,13 +24,13 @@ uniform FP float offsetx; uniform FP float offsety; uniform FP float specularity; uniform FP float waveStrenght; -uniform FP vec3 ka; -uniform FP vec3 specularColor; +uniform FP vec4 ka; uniform FP float shininess; uniform FP float normalAmount; uniform FP vec3 eyePosition; -#pragma include light.inc.frag +#pragma include phong.inc.frag +#pragma include coordinatesystems.inc void main() { @@ -50,21 +51,24 @@ void main() // 2 Animated Layers of specularTexture mixed with the newCoord FP vec4 specularTextureColor = texture2D( specularTexture, multexCoord+newCoord) + (texture2D( specularTexture, movtexCoord+newCoord )); // 2 Animated Layers of normalTexture mixed with the newCoord - FP vec3 normal = normalAmount * texture2D( normalTexture, movtexCoord+newCoord ).rgb - vec3( 1.0 )+(normalAmount * texture2D( normalTexture, multexCoord+newCoord ).rgb - vec3( 1.0 )); + FP vec3 tNormal = normalAmount * texture2D( normalTexture, movtexCoord+newCoord ).rgb - vec3( 1.0 )+(normalAmount * texture2D( normalTexture, multexCoord+newCoord ).rgb - vec3( 1.0 )); // Animated skyTexture layer FP vec4 skycolor = texture2D(skyTexture, skyTexCoord); skycolor = skycolor * 0.4; //Animated foamTexture layer FP vec4 foamTextureColor = texture2D(foamTexture, texCoord); - // Calculate the lighting model, keeping the specular component separate - FP vec3 diffuseColor, specularColor; - adsModelNormalMapped(worldPosition, normal, eyePosition, shininess, tangentMatrix, diffuseColor, specularColor); + FP mat3 tangentMatrix = calcWorldSpaceToTangentSpaceMatrix(worldNormal, worldTangent); + FP mat3 invertTangentMatrix = transpose(tangentMatrix); - // Combine final fragment color - FP vec4 outputColor = vec4(((skycolor.rgb + ka + diffuseTextureColor.rgb * (diffuseColor))+(specularColor * specularTextureColor.a*specularity)), vpos.y ); + FP vec3 wNormal = normalize(invertTangentMatrix * tNormal); + FP vec3 worldView = normalize(eyePosition - worldPosition); + FP vec4 diffuse = vec4(diffuseTextureColor.rgb, vpos.y); + FP vec4 specular = vec4(specularTextureColor.a*specularity); + FP vec4 outputColor = phongFunction(ka, diffuse, specular, shininess, worldPosition, worldView, wNormal); + outputColor += vec4(skycolor.rgb, vpos.y); outputColor += (foamTextureColor.rgba*vpos.y); gl_FragColor = vec4(outputColor.rgb,1.0); diff --git a/examples/qt3d/advancedcustommaterial/shaders/es2/water.vert b/examples/qt3d/advancedcustommaterial/shaders/es2/water.vert index 1a7d46a46..76dd3f8c0 100644 --- a/examples/qt3d/advancedcustommaterial/shaders/es2/water.vert +++ b/examples/qt3d/advancedcustommaterial/shaders/es2/water.vert @@ -6,12 +6,13 @@ attribute FP vec2 vertexTexCoord; attribute FP vec4 vertexTangent; varying FP vec3 worldPosition; +varying FP vec3 worldNormal; +varying FP vec4 worldTangent; varying FP vec2 texCoord; varying FP vec2 movtexCoord; varying FP vec2 multexCoord; varying FP vec2 waveTexCoord; varying FP vec2 skyTexCoord; -varying FP mat3 tangentMatrix; varying FP vec3 vpos; uniform FP mat4 modelMatrix; @@ -42,25 +43,9 @@ void main() // Transform position, normal, and tangent to world coords worldPosition = vec3(modelMatrix * vec4(vertexPosition, 1.0)); - FP vec3 normal = normalize(modelNormalMatrix * vertexNormal); - FP vec3 tangent = normalize(vec3(modelMatrix * vec4(vertexTangent.xyz, 0.0))); - - // Make the tangent truly orthogonal to the normal by using Gram-Schmidt. - // This allows to build the tangentMatrix below by simply transposing the - // tangent -> world space matrix (which would now be orthogonal) - tangent = normalize(tangent - dot(tangent, normal) * normal); - - // Calculate binormal vector. No "real" need to renormalize it, - // as built by crossing two normal vectors. - // To orient the binormal correctly, use the fourth coordinate of the tangent, - // which is +1 for a right hand system, and -1 for a left hand system. - FP vec3 binormal = cross(normal, tangent) * vertexTangent.w; - - // Construct matrix to transform from eye coords to tangent space - tangentMatrix = mat3( - tangent.x, binormal.x, normal.x, - tangent.y, binormal.y, normal.y, - tangent.z, binormal.z, normal.z); + worldNormal = normalize(modelNormalMatrix * vertexNormal); + worldTangent.xyz = normalize(vec3(modelMatrix * vec4(vertexTangent.xyz, 0.0))); + worldTangent.w = vertexTangent.w; // Calculate animated vertex positions diff --git a/examples/qt3d/advancedcustommaterial/shaders/gl3/water.frag b/examples/qt3d/advancedcustommaterial/shaders/gl3/water.frag index 9657cc63a..6e9722314 100644 --- a/examples/qt3d/advancedcustommaterial/shaders/gl3/water.frag +++ b/examples/qt3d/advancedcustommaterial/shaders/gl3/water.frag @@ -1,6 +1,8 @@ #version 150 core in vec3 worldPosition; +in vec3 worldNormal; +in vec4 worldTangent; in vec2 texCoord; in vec2 waveTexCoord; in vec2 movtexCoord; @@ -9,7 +11,6 @@ in vec2 skyTexCoord; in vec3 vpos; -in mat3 tangentMatrix; in vec3 color; uniform sampler2D diffuseTexture; @@ -23,7 +24,7 @@ uniform float offsetx; uniform float offsety; uniform float specularity; uniform float waveStrenght; -uniform vec3 ka; +uniform vec4 ka; uniform vec3 specularColor; uniform float shininess; uniform float normalAmount; @@ -31,7 +32,8 @@ uniform vec3 eyePosition; out vec4 fragColor; -#pragma include light.inc.frag +#pragma include phong.inc.frag +#pragma include coordinatesystems.inc void main() { @@ -52,21 +54,24 @@ void main() // 2 Animated Layers of specularTexture mixed with the newCoord vec4 specularTextureColor = texture( specularTexture, multexCoord+newCoord) + (texture( specularTexture, movtexCoord+newCoord )); // 2 Animated Layers of normalTexture mixed with the newCoord - vec3 normal = normalAmount * texture( normalTexture, movtexCoord+newCoord ).rgb - vec3( 1.0 )+(normalAmount * texture( normalTexture, multexCoord+newCoord ).rgb - vec3( 1.0 )); + vec3 tNormal = normalAmount * texture( normalTexture, movtexCoord+newCoord ).rgb - vec3( 1.0 )+(normalAmount * texture( normalTexture, multexCoord+newCoord ).rgb - vec3( 1.0 )); // Animated skyTexture layer vec4 skycolor = texture(skyTexture, skyTexCoord); skycolor = skycolor * 0.4; //Animated foamTexture layer vec4 foamTextureColor = texture(foamTexture, texCoord); - // Calculate the lighting model, keeping the specular component separate - vec3 diffuseColor, specularColor; - adsModelNormalMapped(worldPosition, normal, eyePosition, shininess, tangentMatrix, diffuseColor, specularColor); + mat3 tangentMatrix = calcWorldSpaceToTangentSpaceMatrix(worldNormal, worldTangent); + mat3 invertTangentMatrix = transpose(tangentMatrix); - // Combine final fragment color - vec4 outputColor = vec4(((skycolor.rgb + ka + diffuseTextureColor.rgb * (diffuseColor))+(specularColor * specularTextureColor.a*specularity)), vpos.y ); + vec3 wNormal = normalize(invertTangentMatrix * tNormal); + vec3 worldView = normalize(eyePosition - worldPosition); + vec4 diffuse = vec4(diffuseTextureColor.rgb, vpos.y); + vec4 specular = vec4(specularTextureColor.a*specularity); + vec4 outputColor = phongFunction(ka, diffuse, specular, shininess, worldPosition, worldView, wNormal); + outputColor += vec4(skycolor.rgb, vpos.y); outputColor += (foamTextureColor.rgba*vpos.y); fragColor = vec4(outputColor.rgb,1.0); diff --git a/examples/qt3d/advancedcustommaterial/shaders/gl3/water.vert b/examples/qt3d/advancedcustommaterial/shaders/gl3/water.vert index a4ddcf62b..3af37e9a5 100644 --- a/examples/qt3d/advancedcustommaterial/shaders/gl3/water.vert +++ b/examples/qt3d/advancedcustommaterial/shaders/gl3/water.vert @@ -6,12 +6,13 @@ in vec2 vertexTexCoord; in vec4 vertexTangent; out vec3 worldPosition; +out vec3 worldNormal; +out vec4 worldTangent; out vec2 texCoord; out vec2 movtexCoord; out vec2 multexCoord; out vec2 waveTexCoord; out vec2 skyTexCoord; -out mat3 tangentMatrix; out vec3 vpos; uniform mat4 modelMatrix; @@ -42,25 +43,9 @@ void main() // Transform position, normal, and tangent to world coords worldPosition = vec3(modelMatrix * vec4(vertexPosition, 1.0)); - vec3 normal = normalize(modelNormalMatrix * vertexNormal); - vec3 tangent = normalize(vec3(modelMatrix * vec4(vertexTangent.xyz, 0.0))); - - // Make the tangent truly orthogonal to the normal by using Gram-Schmidt. - // This allows to build the tangentMatrix below by simply transposing the - // tangent -> world space matrix (which would now be orthogonal) - tangent = normalize(tangent - dot(tangent, normal) * normal); - - // Calculate binormal vector. No "real" need to renormalize it, - // as built by crossing two normal vectors. - // To orient the binormal correctly, use the fourth coordinate of the tangent, - // which is +1 for a right hand system, and -1 for a left hand system. - vec3 binormal = cross(normal, tangent) * vertexTangent.w; - - // Construct matrix to transform from eye coords to tangent space - tangentMatrix = mat3( - tangent.x, binormal.x, normal.x, - tangent.y, binormal.y, normal.y, - tangent.z, binormal.z, normal.z); + worldNormal = normalize(modelNormalMatrix * vertexNormal); + worldTangent.xyz = normalize(vec3(modelMatrix * vec4(vertexTangent.xyz, 0.0))); + worldTangent.w = vertexTangent.w; // Calculate animated vertex positions diff --git a/examples/qt3d/phong-cubes/CubeEntity.qml b/examples/qt3d/phong-cubes/CubeEntity.qml new file mode 100644 index 000000000..558f53327 --- /dev/null +++ b/examples/qt3d/phong-cubes/CubeEntity.qml @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 as Quick +import Qt3D.Core 2.0 +import Qt3D.Render 2.0 +import Qt3D.Extras 2.0 + +Entity { + id: root + property vector3d position: Qt.vector3d() + property Material material + + components: [mesh, material, transform] + + CuboidMesh { + id: mesh + xExtent: 0.5 + yExtent: xExtent + zExtent: xExtent + } + + Transform { + id: transform + translation: root.position + rotationZ: 45 + + Quick.NumberAnimation on rotationY { + from: 0; to: 360 + loops: Quick.Animation.Infinite + duration: 5000 + } + } +} diff --git a/examples/qt3d/phong-cubes/main.cpp b/examples/qt3d/phong-cubes/main.cpp new file mode 100644 index 000000000..dba6e0bff --- /dev/null +++ b/examples/qt3d/phong-cubes/main.cpp @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <Qt3DQuickExtras/qt3dquickwindow.h> +#include <QGuiApplication> + +int main(int argc, char* argv[]) +{ + QGuiApplication app(argc, argv); + Qt3DExtras::Quick::Qt3DQuickWindow view; + + view.setSource(QUrl("qrc:/main.qml")); + view.show(); + + return app.exec(); +} diff --git a/examples/qt3d/phong-cubes/main.qml b/examples/qt3d/phong-cubes/main.qml new file mode 100644 index 000000000..0e067fdad --- /dev/null +++ b/examples/qt3d/phong-cubes/main.qml @@ -0,0 +1,152 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import Qt3D.Core 2.0 +import Qt3D.Render 2.0 +import Qt3D.Input 2.0 +import Qt3D.Extras 2.0 + +Entity { + components: [ + RenderSettings { + activeFrameGraph: ForwardRenderer { + clearColor: "white" + camera: mainCamera + } + }, + InputSettings { } + ] + + Camera { + id: mainCamera + position: Qt.vector3d(0.0, 0.0, 7.0) + upVector: Qt.vector3d(0.0, 1.0, 0.0) + viewCenter: Qt.vector3d(0.0, 0.0, 0.0) + } + + FirstPersonCameraController { + camera: mainCamera + } + + Entity { + components: [ + PointLight {}, + Transform { translation: mainCamera.position } + ] + } + + CubeEntity { + position: Qt.vector3d(-1, 1, 0) + material: PhongMaterial {} + } + + CubeEntity { + position: Qt.vector3d(0, 1, 0) + material: DiffuseMapMaterial { + diffuse: TextureLoader { source: "qrc:/assets/textures/pattern_09/diffuse.webp" } + } + } + + CubeEntity { + position: Qt.vector3d(1, 1, 0) + material: DiffuseSpecularMapMaterial { + diffuse: TextureLoader { source: "qrc:/assets/textures/pattern_09/diffuse.webp" } + specular: TextureLoader { source: "qrc:/assets/textures/pattern_09/specular.webp" } + } + } + + CubeEntity { + position: Qt.vector3d(-1, 0, 0) + material: PhongAlphaMaterial {} + } + + CubeEntity { + position: Qt.vector3d(0, 0, 0) + material: NormalDiffuseMapMaterial { + normal: TextureLoader { source: "qrc:/assets/textures/pattern_09/normal.webp" } + diffuse: TextureLoader { source: "qrc:/assets/textures/pattern_09/diffuse.webp" } + } + } + + CubeEntity { + position: Qt.vector3d(1, 0, 0) + material: NormalDiffuseMapAlphaMaterial { + normal: TextureLoader { source: "qrc:/assets/textures/pattern_09/normal.webp" } + diffuse: TextureLoader { source: "qrc:/assets/textures/pattern_09/diffuse.webp" } + } + } + + CubeEntity { + position: Qt.vector3d(-1, -1, 0) + material: NormalDiffuseSpecularMapMaterial { + normal: TextureLoader { source: "qrc:/assets/textures/pattern_09/normal.webp" } + diffuse: TextureLoader { source: "qrc:/assets/textures/pattern_09/diffuse.webp" } + specular: TextureLoader { source: "qrc:/assets/textures/pattern_09/specular.webp" } + } + } + + CubeEntity { + position: Qt.vector3d(0, -1, 0) + material: NormalDiffuseSpecularMapMaterial { + normal: TextureLoader { source: "qrc:/assets/textures/pattern_09/normal.webp" } + diffuse: TextureLoader { source: "qrc:/assets/textures/pattern_09/diffuse.webp" } + specular: TextureLoader { source: "qrc:/assets/textures/pattern_09/specular.webp" } + } + } + + CubeEntity { + position: Qt.vector3d(1, -1, 0) + material: NormalDiffuseSpecularMapMaterial { + normal: TextureLoader { source: "qrc:/assets/textures/pattern_09/normal.webp" } + diffuse: TextureLoader { source: "qrc:/assets/textures/pattern_09/diffuse.webp" } + specular: TextureLoader { source: "qrc:/assets/textures/pattern_09/specular.webp" } + } + } +} diff --git a/examples/qt3d/phong-cubes/phong-cubes.pro b/examples/qt3d/phong-cubes/phong-cubes.pro new file mode 100644 index 000000000..e099b336d --- /dev/null +++ b/examples/qt3d/phong-cubes/phong-cubes.pro @@ -0,0 +1,18 @@ +!include( ../examples.pri ) { + error( "Couldn't find the examples.pri file!" ) +} + +SOURCE += main.cpp + +QT += qml quick 3dcore 3drender 3dinput 3dquick 3dquickextras + +OTHER_FILES += \ + main.qml \ + CubeEntity.qml + +SOURCES += \ + main.cpp + +RESOURCES += \ + phong-cubes.qrc \ + ../exampleresources/textures.qrc diff --git a/examples/qt3d/phong-cubes/phong-cubes.qrc b/examples/qt3d/phong-cubes/phong-cubes.qrc new file mode 100644 index 000000000..84cec1121 --- /dev/null +++ b/examples/qt3d/phong-cubes/phong-cubes.qrc @@ -0,0 +1,6 @@ +<RCC> + <qresource prefix="/"> + <file>main.qml</file> + <file>CubeEntity.qml</file> + </qresource> +</RCC> diff --git a/examples/qt3d/qt3d.pro b/examples/qt3d/qt3d.pro index 7ac55bfd2..74049b129 100644 --- a/examples/qt3d/qt3d.pro +++ b/examples/qt3d/qt3d.pro @@ -20,7 +20,8 @@ SUBDIRS += \ qardboard \ advancedcustommaterial \ simplecustommaterial \ - scene2d + scene2d \ + phong-cubes qtHaveModule(multimedia): SUBDIRS += audio-visualizer-qml diff --git a/src/animation/backend/animationutils.cpp b/src/animation/backend/animationutils.cpp index f421a8025..d05d96f38 100644 --- a/src/animation/backend/animationutils.cpp +++ b/src/animation/backend/animationutils.cpp @@ -48,6 +48,7 @@ #include <QtGui/qquaternion.h> #include <QtGui/qcolor.h> #include <QtCore/qvariant.h> +#include <QtCore/qvarlengtharray.h> #include <Qt3DAnimation/private/animationlogging_p.h> #include <numeric> @@ -292,13 +293,45 @@ QVector<Qt3DCore::QSceneChangePtr> preparePropertyChanges(Qt3DCore::QNodeId anim bool finalFrame) { QVector<Qt3DCore::QSceneChangePtr> changes; + QVarLengthArray<Skeleton *, 4> dirtySkeletons; + // Iterate over the mappings for (const MappingData &mappingData : mappingDataVec) { if (!mappingData.propertyName) continue; + // Build the new value from the channel/fcurve evaluation results const QVariant v = buildPropertyValue(mappingData, channelResults); - if (v.isValid()) { + if (!v.isValid()) + continue; + + // TODO: Avoid wrapping joint transform components up in a variant, just + // to immediately unwrap them again. Refactor buildPropertyValue() to call + // helper functions that we can call directly here for joints. + if (mappingData.skeleton && mappingData.jointIndex != -1) { + // Remember that this skeleton is dirty. We will ask each dirty skeleton + // to send its set of local poses to observers below. + if (!dirtySkeletons.contains(mappingData.skeleton)) + dirtySkeletons.push_back(mappingData.skeleton); + + switch (mappingData.jointTransformComponent) { + case MappingData::Scale: + mappingData.skeleton->setJointScale(mappingData.jointIndex, v.value<QVector3D>()); + break; + + case MappingData::Rotation: + mappingData.skeleton->setJointRotation(mappingData.jointIndex, v.value<QQuaternion>()); + break; + + case MappingData::Translation: + mappingData.skeleton->setJointTranslation(mappingData.jointIndex, v.value<QVector3D>()); + break; + + default: + Q_UNREACHABLE(); + break; + } + } else { // Construct a property update change, set target, property and delivery options auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(mappingData.targetId); e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); @@ -311,6 +344,8 @@ QVector<Qt3DCore::QSceneChangePtr> preparePropertyChanges(Qt3DCore::QNodeId anim } } + for (const auto skeleton : dirtySkeletons) + skeleton->sendLocalPoses(); // If it's the final frame, notify the frontend that we've stopped if (finalFrame) { @@ -342,96 +377,118 @@ QVector<AnimationCallbackAndValue> prepareCallbacks(const QVector<MappingData> & return callbacks; } -//TODO: Remove this and use new implementation below for both the unblended -// and blended animation cases. -QVector<MappingData> buildPropertyMappings(Handler *handler, - const AnimationClip *clip, - const ChannelMapper *mapper) +// TODO: Optimize this even more by combining the work done here with the functions: +// buildRequiredChannelsAndTypes() and assignChannelComponentIndices(). We are +// currently repeating the iteration over mappings and extracting/generating +// channel names, types and joint indices. +QVector<MappingData> buildPropertyMappings(const QVector<ChannelMapping*> &channelMappings, + const QVector<ChannelNameAndType> &channelNamesAndTypes, + const QVector<ComponentIndices> &channelComponentIndices) { - QVector<MappingData> mappingDataVec; - ChannelMappingManager *mappingManager = handler->channelMappingManager(); - const QVector<Channel> &channels = clip->channels(); - - // Iterate over the mappings in the mapper object - const auto mappingIds = mapper->mappingIds(); - for (const Qt3DCore::QNodeId mappingId : mappingIds) { - // Get the mapping object - ChannelMapping *mapping = mappingManager->lookupResource(mappingId); - Q_ASSERT(mapping); + // Accumulate the required number of mappings + int maxMappingDatas = 0; + for (const auto mapping : channelMappings) { + switch (mapping->mappingType()) { + case ChannelMapping::ChannelMappingType: + case ChannelMapping::CallbackMappingType: + ++maxMappingDatas; + break; - // Populate the data we need, easy stuff first - MappingData mappingData; - mappingData.targetId = mapping->targetId(); - mappingData.propertyName = mapping->propertyName(); - mappingData.type = mapping->type(); - mappingData.callback = mapping->callback(); - mappingData.callbackFlags = mapping->callbackFlags(); - - if (mappingData.type == static_cast<int>(QVariant::Invalid)) { - qWarning() << "Unknown type for node id =" << mappingData.targetId - << "and property =" << mapping->property() - << "and callback =" << mapping->callback(); - continue; + case ChannelMapping::SkeletonMappingType: { + Skeleton *skeleton = mapping->skeleton(); + maxMappingDatas += 3 * skeleton->jointCount(); // S, R, T + break; } + } + } + QVector<MappingData> mappingDataVec; + mappingDataVec.reserve(maxMappingDatas); - // Now the tricky part. Mapping the channel indices onto the property type. - // Try to find a ChannelGroup with matching name - const QString channelName = mapping->channelName(); - int channelGroupIndex = 0; - bool foundMatch = false; - for (const Channel &channel : channels) { - if (channel.name == channelName) { - foundMatch = true; - const int channelBaseIndex = clip->channelComponentBaseIndex(channelGroupIndex); - - // Within this group, match channel names with index ordering - mappingData.channelIndices = channelComponentsToIndices(channel, mappingData.type, channelBaseIndex); + // Iterate over the mappings + for (const auto mapping : channelMappings) { + switch (mapping->mappingType()) { + case ChannelMapping::ChannelMappingType: + case ChannelMapping::CallbackMappingType: { + // Populate the data we need, easy stuff first + MappingData mappingData; + mappingData.targetId = mapping->targetId(); + mappingData.propertyName = mapping->propertyName(); + mappingData.type = mapping->type(); + mappingData.callback = mapping->callback(); + mappingData.callbackFlags = mapping->callbackFlags(); + + if (mappingData.type == static_cast<int>(QVariant::Invalid)) { + qWarning() << "Unknown type for node id =" << mappingData.targetId + << "and property =" << mapping->property() + << "and callback =" << mapping->callback(); + continue; + } - // Store the mapping data + // Try to find matching channel name and type + const ChannelNameAndType nameAndType = { mapping->channelName(), mapping->type() }; + const int index = channelNamesAndTypes.indexOf(nameAndType); + if (index != -1) { + // We got one! + mappingData.channelIndices = channelComponentIndices[index]; mappingDataVec.push_back(mappingData); - - if (foundMatch) - break; } - - ++channelGroupIndex; + break; } - } - return mappingDataVec; -} + case ChannelMapping::SkeletonMappingType: { + const QVector<ChannelNameAndType> jointProperties + = { { QLatin1String("Location"), static_cast<int>(QVariant::Vector3D) }, + { QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion) }, + { QLatin1String("Scale"), static_cast<int>(QVariant::Vector3D) } }; + const QHash<QString, const char *> channelNameToPropertyName + = { { QLatin1String("Location"), "translation" }, + { QLatin1String("Rotation"), "rotation" }, + { QLatin1String("Scale"), "scale" } }; + Skeleton *skeleton = mapping->skeleton(); + const int jointCount = skeleton->jointCount(); + for (int jointIndex = 0; jointIndex < jointCount; ++jointIndex) { + // Populate the data we need, easy stuff first + MappingData mappingData; + mappingData.targetId = mapping->skeletonId(); + mappingData.skeleton = mapping->skeleton(); -QVector<MappingData> buildPropertyMappings(const QVector<ChannelMapping*> &channelMappings, - const QVector<ChannelNameAndType> &channelNamesAndTypes, - const QVector<ComponentIndices> &channelComponentIndices) -{ - QVector<MappingData> mappingDataVec; - mappingDataVec.reserve(channelMappings.size()); + const int propertyCount = jointProperties.size(); + for (int propertyIndex = 0; propertyIndex < propertyCount; ++propertyIndex) { + // Get the name, type and index + ChannelNameAndType nameAndType = jointProperties[propertyIndex]; + nameAndType.jointIndex = jointIndex; - // Iterate over the mappings - for (const auto mapping : channelMappings) { - // Populate the data we need, easy stuff first - MappingData mappingData; - mappingData.targetId = mapping->targetId(); - mappingData.propertyName = mapping->propertyName(); - mappingData.type = mapping->type(); - mappingData.callback = mapping->callback(); - mappingData.callbackFlags = mapping->callbackFlags(); - - if (mappingData.type == static_cast<int>(QVariant::Invalid)) { - qWarning() << "Unknown type for node id =" << mappingData.targetId - << "and property =" << mapping->property() - << "and callback =" << mapping->callback(); - continue; + // Try to find matching channel name and type + const int index = channelNamesAndTypes.indexOf(nameAndType); + + // Do we have any animation data for this channel? If not, don't bother + // adding a mapping for it. + if (channelComponentIndices[index].isEmpty()) + continue; + + if (index != -1) { + // We got one! + mappingData.propertyName = channelNameToPropertyName[nameAndType.name]; + mappingData.type = nameAndType.type; + mappingData.channelIndices = channelComponentIndices[index]; + mappingData.jointIndex = jointIndex; + + // Convert property name for joint transform components to + // an enumerated type so we can avoid the string comparisons + // when sending the change events after evaluation. + if (qstrcmp(mappingData.propertyName, "scale") == 0) + mappingData.jointTransformComponent = MappingData::Scale; + else if (qstrcmp(mappingData.propertyName, "rotation") == 0) + mappingData.jointTransformComponent = MappingData::Rotation; + else if (qstrcmp(mappingData.propertyName, "translation") == 0) + mappingData.jointTransformComponent = MappingData::Translation; + + mappingDataVec.push_back(mappingData); + } + } + } + break; } - - // Try to find matching channel name and type - const ChannelNameAndType nameAndType = { mapping->channelName(), mapping->type() }; - const int index = channelNamesAndTypes.indexOf(nameAndType); - if (index != -1) { - // We got one! - mappingData.channelIndices = channelComponentIndices[index]; - mappingDataVec.push_back(mappingData); } } @@ -539,6 +596,10 @@ QVector<Qt3DCore::QNodeId> gatherValueNodesToEvaluate(Handler *handler, ClipBlendNodeVisitor::VisitOnlyDependencies); auto func = [&clipIds, nodeManager] (ClipBlendNode *blendNode) { + // Check if this is a value node itself + if (blendNode->blendType() == ClipBlendNode::ValueType) + clipIds.append(blendNode->peerId()); + const auto dependencyIds = blendNode->currentDependencyIds(); for (const auto dependencyId : dependencyIds) { // Look up the blend node and if it's a value type (clip), @@ -558,19 +619,18 @@ QVector<Qt3DCore::QNodeId> gatherValueNodesToEvaluate(Handler *handler, } ComponentIndices generateClipFormatIndices(const QVector<ChannelNameAndType> &targetChannels, - const QVector<ComponentIndices> &targetIndices, + QVector<ComponentIndices> &targetIndices, const AnimationClip *clip) { Q_ASSERT(targetChannels.size() == targetIndices.size()); // Reserve enough storage for all the format indices int indexCount = 0; - for (const auto targetIndexVec : qAsConst(targetIndices)) + for (const auto &targetIndexVec : qAsConst(targetIndices)) indexCount += targetIndexVec.size(); ComponentIndices format; format.resize(indexCount); - // Iterate through the target channels const int channelCount = targetChannels.size(); auto formatIt = format.begin(); @@ -579,23 +639,24 @@ ComponentIndices generateClipFormatIndices(const QVector<ChannelNameAndType> &ta const ChannelNameAndType &targetChannel = targetChannels[i]; const int clipChannelIndex = clip->channelIndex(targetChannel.name, targetChannel.jointIndex); - - // TODO: Ensure channel in the clip has enough components to map to the type. - // Requires some improvements to the clip data structure first. - // TODO: I don't think we need the targetIndices, only the number of components - // for each target channel. Check once blend tree is complete. const int componentCount = targetIndices[i].size(); if (clipChannelIndex != -1) { // Found a matching channel in the clip. Get the base channel // component index and populate the format indices for this channel. const int baseIndex = clip->channelComponentBaseIndex(clipChannelIndex); - std::iota(formatIt, formatIt + componentCount, baseIndex); + + // 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. std::fill(formatIt, formatIt + componentCount, -1); + targetIndices[i].clear(); } formatIt += componentCount; diff --git a/src/animation/backend/animationutils_p.h b/src/animation/backend/animationutils_p.h index 7fcd9ead5..4bd3ee64b 100644 --- a/src/animation/backend/animationutils_p.h +++ b/src/animation/backend/animationutils_p.h @@ -71,9 +71,19 @@ typedef QVector<int> ComponentIndices; struct MappingData { + enum JointTransformComponent { + NoTransformComponent = 0, + Scale, + Rotation, + Translation + }; + Qt3DCore::QNodeId targetId; + Skeleton *skeleton = nullptr; + int jointIndex = -1; + JointTransformComponent jointTransformComponent = NoTransformComponent; const char *propertyName; - QAnimationCallback *callback; + QAnimationCallback *callback = nullptr; QAnimationCallback::Flags callbackFlags; int type; ComponentIndices channelIndices; @@ -190,11 +200,6 @@ QVector<AnimationCallbackAndValue> prepareCallbacks(const QVector<MappingData> & const QVector<float> &channelResults); Q_AUTOTEST_EXPORT -QVector<MappingData> buildPropertyMappings(Handler *handler, - const AnimationClip *clip, - const ChannelMapper *mapper); - -Q_AUTOTEST_EXPORT QVector<MappingData> buildPropertyMappings(const QVector<ChannelMapping *> &channelMappings, const QVector<ChannelNameAndType> &channelNamesAndTypes, const QVector<ComponentIndices> &channelComponentIndices); @@ -222,7 +227,7 @@ QVector<Qt3DCore::QNodeId> gatherValueNodesToEvaluate(Handler *handler, Q_AUTOTEST_EXPORT ComponentIndices generateClipFormatIndices(const QVector<ChannelNameAndType> &targetChannels, - const QVector<ComponentIndices> &targetIndices, + QVector<ComponentIndices> &targetIndices, const AnimationClip *clip); Q_AUTOTEST_EXPORT diff --git a/src/animation/backend/channelmapper.cpp b/src/animation/backend/channelmapper.cpp index 0e5555096..48a1335fa 100644 --- a/src/animation/backend/channelmapper.cpp +++ b/src/animation/backend/channelmapper.cpp @@ -38,6 +38,7 @@ #include <Qt3DAnimation/qchannelmapper.h> #include <Qt3DAnimation/private/qchannelmapper_p.h> #include <Qt3DAnimation/private/animationlogging_p.h> +#include <Qt3DAnimation/private/managers_p.h> #include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DCore/qpropertynodeaddedchange.h> #include <Qt3DCore/qpropertynoderemovedchange.h> @@ -50,6 +51,7 @@ namespace Animation { ChannelMapper::ChannelMapper() : BackendNode(ReadOnly) , m_mappingIds() + , m_isDirty(true) { } @@ -58,12 +60,15 @@ void ChannelMapper::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QChannelMapperData>>(change); const auto &data = typedChange->data; m_mappingIds = data.mappingIds; + m_isDirty = true; } void ChannelMapper::cleanup() { setEnabled(false); m_mappingIds.clear(); + m_mappings.clear(); + m_isDirty = true; } void ChannelMapper::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) @@ -74,6 +79,7 @@ void ChannelMapper::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) if (change->propertyName() == QByteArrayLiteral("mappings")) { m_mappingIds.push_back(change->addedNodeId()); setDirty(Handler::ChannelMappingsDirty); + m_isDirty = true; } break; } @@ -83,6 +89,7 @@ void ChannelMapper::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) if (change->propertyName() == QByteArrayLiteral("mappings")) { m_mappingIds.removeOne(change->removedNodeId()); setDirty(Handler::ChannelMappingsDirty); + m_isDirty = true; } break; } @@ -93,6 +100,19 @@ void ChannelMapper::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) QBackendNode::sceneChangeEvent(e); } +void ChannelMapper::updateMappings() const +{ + m_mappings.clear(); + m_mappings.reserve(m_mappingIds.size()); + const auto mappingManager = m_handler->channelMappingManager(); + for (const auto &mappingId : m_mappingIds) { + const auto mapping = mappingManager->lookupResource(mappingId); + Q_ASSERT(mapping); + m_mappings.push_back(mapping); + } + m_isDirty = false; +} + } // namespace Animation } // namespace Qt3DAnimation diff --git a/src/animation/backend/channelmapper_p.h b/src/animation/backend/channelmapper_p.h index cb1a13928..fd99c8dbd 100644 --- a/src/animation/backend/channelmapper_p.h +++ b/src/animation/backend/channelmapper_p.h @@ -74,10 +74,22 @@ public: void setMappingIds(const QVector<Qt3DCore::QNodeId> &mappingIds) { m_mappingIds = mappingIds; } QVector<Qt3DCore::QNodeId> mappingIds() const { return m_mappingIds; } + QVector<ChannelMapping*> mappings() const + { + if (m_isDirty) + updateMappings(); + return m_mappings; + } + private: void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; + void updateMappings() const; QVector<Qt3DCore::QNodeId> m_mappingIds; + + // Cached data + mutable QVector<ChannelMapping*> m_mappings; + mutable bool m_isDirty; }; } // namespace Animation diff --git a/src/animation/backend/channelmapping.cpp b/src/animation/backend/channelmapping.cpp index 417c10a1a..4c263edba 100644 --- a/src/animation/backend/channelmapping.cpp +++ b/src/animation/backend/channelmapping.cpp @@ -40,6 +40,7 @@ #include <Qt3DAnimation/private/qskeletonmapping_p.h> #include <Qt3DAnimation/private/animationlogging_p.h> #include <Qt3DAnimation/private/qchannelmappingcreatedchange_p.h> +#include <Qt3DAnimation/private/managers_p.h> #include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE @@ -137,6 +138,11 @@ void ChannelMapping::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) QBackendNode::sceneChangeEvent(e); } +Skeleton *ChannelMapping::skeleton() const +{ + return m_handler->skeletonManager()->lookupResource(m_skeletonId); +} + } // namespace Animation } // namespace Qt3DAnimation diff --git a/src/animation/backend/channelmapping_p.h b/src/animation/backend/channelmapping_p.h index 92c1d1c28..82de5c7b4 100644 --- a/src/animation/backend/channelmapping_p.h +++ b/src/animation/backend/channelmapping_p.h @@ -101,6 +101,7 @@ public: void setSkeletonId(Qt3DCore::QNodeId skeletonId) { m_skeletonId = skeletonId; } Qt3DCore::QNodeId skeletonId() const { return m_skeletonId; } + Skeleton *skeleton() const; void setMappingType(MappingType mappingType) { m_mappingType = mappingType; } MappingType mappingType() const { return m_mappingType; } diff --git a/src/animation/backend/clipanimator.cpp b/src/animation/backend/clipanimator.cpp index 2f4dca63f..568e2dbb0 100644 --- a/src/animation/backend/clipanimator.cpp +++ b/src/animation/backend/clipanimator.cpp @@ -114,6 +114,7 @@ void ClipAnimator::cleanup() m_clockId = Qt3DCore::QNodeId(); m_running = false; m_loops = 1; + m_formatIndices.clear(); } void ClipAnimator::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) diff --git a/src/animation/backend/clipanimator_p.h b/src/animation/backend/clipanimator_p.h index 0f975093c..ca05afdd3 100644 --- a/src/animation/backend/clipanimator_p.h +++ b/src/animation/backend/clipanimator_p.h @@ -97,6 +97,9 @@ public: void animationClipMarkedDirty() { setDirty(Handler::ClipAnimatorDirty); } + void setFormatIndices(const ComponentIndices &formatIndices) { m_formatIndices = formatIndices; } + ComponentIndices formatIndices() const { return m_formatIndices; } + private: void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; @@ -111,6 +114,7 @@ private: QVector<MappingData> m_mappingData; int m_currentLoop; + ComponentIndices m_formatIndices; }; } // namespace Animation diff --git a/src/animation/backend/clipblendvalue_p.h b/src/animation/backend/clipblendvalue_p.h index f1bdfed3f..f0ae65589 100644 --- a/src/animation/backend/clipblendvalue_p.h +++ b/src/animation/backend/clipblendvalue_p.h @@ -73,7 +73,7 @@ public: inline QVector<Qt3DCore::QNodeId> currentDependencyIds() const override { - return { m_clipId }; + return {}; } double duration() const override; diff --git a/src/animation/backend/evaluateclipanimatorjob.cpp b/src/animation/backend/evaluateclipanimatorjob.cpp index 6dab51d63..d9600c375 100644 --- a/src/animation/backend/evaluateclipanimatorjob.cpp +++ b/src/animation/backend/evaluateclipanimatorjob.cpp @@ -70,7 +70,11 @@ void EvaluateClipAnimatorJob::run() // Prepare for evaluation (convert global time to local time ....) const AnimatorEvaluationData animatorEvaluationData = evaluationDataForAnimator(clipAnimator, clock, globalTime); const ClipEvaluationData preEvaluationDataForClip = evaluationDataForClip(clip, animatorEvaluationData); - const ClipResults channelResults = evaluateClipAtLocalTime(clip, preEvaluationDataForClip.localTime); + const ClipResults rawClipResults = evaluateClipAtLocalTime(clip, preEvaluationDataForClip.localTime); + + // Reformat the clip results into the layout used by this animator/blend tree + ComponentIndices format = clipAnimator->formatIndices(); + ClipResults formattedClipResults = formatClipResults(rawClipResults, format); if (preEvaluationDataForClip.isFinalFrame) clipAnimator->setRunning(false); @@ -80,14 +84,15 @@ void EvaluateClipAnimatorJob::run() // Prepare property changes (if finalFrame it also prepares the change for the running property for the frontend) const QVector<Qt3DCore::QSceneChangePtr> changes = preparePropertyChanges(clipAnimator->peerId(), clipAnimator->mappingData(), - channelResults, + formattedClipResults, preEvaluationDataForClip.isFinalFrame); // Send the property changes clipAnimator->sendPropertyChanges(changes); // Trigger callbacks either on this thread or by notifying the gui thread. - const QVector<AnimationCallbackAndValue> callbacks = prepareCallbacks(clipAnimator->mappingData(), channelResults); + const QVector<AnimationCallbackAndValue> callbacks = prepareCallbacks(clipAnimator->mappingData(), + formattedClipResults); clipAnimator->sendCallbacks(callbacks); } diff --git a/src/animation/backend/findrunningclipanimatorsjob.cpp b/src/animation/backend/findrunningclipanimatorsjob.cpp index a8349eb91..16b84359e 100644 --- a/src/animation/backend/findrunningclipanimatorsjob.cpp +++ b/src/animation/backend/findrunningclipanimatorsjob.cpp @@ -62,24 +62,39 @@ void FindRunningClipAnimatorsJob::run() Q_ASSERT(m_handler); ClipAnimatorManager *clipAnimatorManager = m_handler->clipAnimatorManager(); - for (const auto clipAnimatorHandle : qAsConst(m_clipAnimatorHandles)) { + for (const auto &clipAnimatorHandle : qAsConst(m_clipAnimatorHandles)) { ClipAnimator *clipAnimator = clipAnimatorManager->data(clipAnimatorHandle); Q_ASSERT(clipAnimator); const bool canRun = clipAnimator->canRun(); m_handler->setClipAnimatorRunning(clipAnimatorHandle, canRun); - // The clip animator needs to know how to map fcurve values through to - // properties on QNodes. Now we know this animator can run, build the mapping - // table. - // TODO: Should be possible to parallelise this with the fcurve evaluation as - // sending the property change events doesn't happen until after evaluation - if (canRun) { - const AnimationClip *clip = m_handler->animationClipLoaderManager()->lookupResource(clipAnimator->clipId()); - const ChannelMapper *mapper = m_handler->channelMapperManager()->lookupResource(clipAnimator->mapperId()); - Q_ASSERT(clip && mapper); - const QVector<MappingData> mappingData = buildPropertyMappings(m_handler, clip, mapper); - clipAnimator->setMappingData(mappingData); - } + if (!canRun) + continue; + + // The clip animator needs to know how to map fcurve values through to properties on QNodes. + // Now we know this animator can run, build the mapping table. Even though this could be + // done a little simpler in the non-blended case, we follow the same code path as the + // blended clip animator for consistency and ease of maintenance. + const ChannelMapper *mapper = m_handler->channelMapperManager()->lookupResource(clipAnimator->mapperId()); + Q_ASSERT(mapper); + const QVector<ChannelMapping *> channelMappings = mapper->mappings(); + + const QVector<ChannelNameAndType> channelNamesAndTypes + = buildRequiredChannelsAndTypes(m_handler, mapper); + QVector<ComponentIndices> channelComponentIndices + = assignChannelComponentIndices(channelNamesAndTypes); + + const AnimationClip *clip = m_handler->animationClipLoaderManager()->lookupResource(clipAnimator->clipId()); + Q_ASSERT(clip); + const ComponentIndices formatIndices = generateClipFormatIndices(channelNamesAndTypes, + channelComponentIndices, + clip); + clipAnimator->setFormatIndices(formatIndices); + + const QVector<MappingData> mappingData = buildPropertyMappings(channelMappings, + channelNamesAndTypes, + channelComponentIndices); + clipAnimator->setMappingData(mappingData); } qCDebug(Jobs) << "Running clip animators =" << m_handler->runningClipAnimators(); diff --git a/src/animation/backend/findrunningclipanimatorsjob_p.h b/src/animation/backend/findrunningclipanimatorsjob_p.h index 6c81ee914..f0e30e80c 100644 --- a/src/animation/backend/findrunningclipanimatorsjob_p.h +++ b/src/animation/backend/findrunningclipanimatorsjob_p.h @@ -52,6 +52,10 @@ #include <Qt3DAnimation/private/handle_types_p.h> #include <QtCore/qvector.h> +#if defined(QT_BUILD_INTERNAL) +class tst_FindRunningClipAnimatorsJob; +#endif + QT_BEGIN_NAMESPACE namespace Qt3DAnimation { @@ -59,7 +63,7 @@ namespace Animation { class Handler; -class FindRunningClipAnimatorsJob : public Qt3DCore::QAspectJob +class Q_AUTOTEST_EXPORT FindRunningClipAnimatorsJob : public Qt3DCore::QAspectJob { public: FindRunningClipAnimatorsJob(); @@ -75,6 +79,10 @@ protected: private: QVector<HClipAnimator> m_clipAnimatorHandles; Handler *m_handler; + +#if defined(QT_BUILD_INTERNAL) + friend class ::tst_FindRunningClipAnimatorsJob; +#endif }; } // namespace Animation diff --git a/src/animation/backend/skeleton.cpp b/src/animation/backend/skeleton.cpp index a920e2473..dcfaf55e7 100644 --- a/src/animation/backend/skeleton.cpp +++ b/src/animation/backend/skeleton.cpp @@ -96,6 +96,15 @@ void Skeleton::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) BackendNode::sceneChangeEvent(e); } +void Skeleton::sendLocalPoses() +{ + auto e = QPropertyUpdatedChangePtr::create(peerId()); + e->setDeliveryFlags(Qt3DCore::QSceneChange::BackendNodes); + e->setPropertyName("localPoses"); + e->setValue(QVariant::fromValue(m_jointLocalPoses)); + notifyObservers(e); +} + } // namespace Animation } // namespace Qt3DAnimation diff --git a/src/animation/backend/skeleton_p.h b/src/animation/backend/skeleton_p.h index 19da98261..e26e276d9 100644 --- a/src/animation/backend/skeleton_p.h +++ b/src/animation/backend/skeleton_p.h @@ -66,6 +66,23 @@ public: int jointCount() const { return m_jointLocalPoses.size(); } + void setJointScale(int jointIndex, const QVector3D &scale) + { + m_jointLocalPoses[jointIndex].scale = scale; + } + + void setJointRotation(int jointIndex, const QQuaternion &rotation) + { + m_jointLocalPoses[jointIndex].rotation = rotation; + } + + void setJointTranslation(int jointIndex, const QVector3D &translation) + { + m_jointLocalPoses[jointIndex].translation = translation; + } + + void sendLocalPoses(); + #if defined(QT_BUILD_INTERNAL) void setJointCount(int jointCount) { diff --git a/src/animation/frontend/qanimationaspect.cpp b/src/animation/frontend/qanimationaspect.cpp index 14a0c4f8c..9b23a7b1d 100644 --- a/src/animation/frontend/qanimationaspect.cpp +++ b/src/animation/frontend/qanimationaspect.cpp @@ -95,6 +95,7 @@ QAnimationAspect::QAnimationAspect(QAnimationAspectPrivate &dd, QObject *parent) Q_D(QAnimationAspect); qRegisterMetaType<Qt3DAnimation::QAnimationClipLoader*>(); qRegisterMetaType<Qt3DAnimation::QChannelMapper*>(); + qRegisterMetaType<QVector<Qt3DCore::Sqt>>(); registerBackendType<QAbstractAnimationClip>( QSharedPointer<Animation::NodeFunctor<Animation::AnimationClip, Animation::AnimationClipLoaderManager>>::create(d->m_handler.data(), diff --git a/src/animation/frontend/qblendedclipanimator.cpp b/src/animation/frontend/qblendedclipanimator.cpp index 93cc27f50..785c810d3 100644 --- a/src/animation/frontend/qblendedclipanimator.cpp +++ b/src/animation/frontend/qblendedclipanimator.cpp @@ -40,6 +40,7 @@ #include "qblendedclipanimator_p.h" #include <Qt3DAnimation/qabstractclipblendnode.h> #include <Qt3DAnimation/qchannelmapper.h> +#include <Qt3DAnimation/qclock.h> QT_BEGIN_NAMESPACE @@ -312,6 +313,7 @@ Qt3DCore::QNodeCreatedChangeBasePtr QBlendedClipAnimator::createNodeCreationChan Q_D(const QBlendedClipAnimator); data.blendTreeRootId = Qt3DCore::qIdForNode(d->m_blendTreeRoot); data.mapperId = Qt3DCore::qIdForNode(d->m_mapper); + data.clockId = Qt3DCore::qIdForNode(d->m_clock); data.running = d->m_running; data.loops = d->m_loops; return creationChange; diff --git a/src/core/transforms/sqt_p.h b/src/core/transforms/sqt_p.h index 262e3a645..5fdefccc8 100644 --- a/src/core/transforms/sqt_p.h +++ b/src/core/transforms/sqt_p.h @@ -101,6 +101,7 @@ struct JointNamesAndLocalPoses QT_END_NAMESPACE +Q_DECLARE_METATYPE(QVector<Qt3DCore::Sqt>) Q_DECLARE_METATYPE(Qt3DCore::JointNamesAndLocalPoses) #endif // QT3DCORE_SQT_P_H diff --git a/src/extras/3dtext/qextrudedtextgeometry.cpp b/src/extras/3dtext/qextrudedtextgeometry.cpp index c4c4ba77f..4a81ae44a 100644 --- a/src/extras/3dtext/qextrudedtextgeometry.cpp +++ b/src/extras/3dtext/qextrudedtextgeometry.cpp @@ -166,8 +166,8 @@ void QExtrudedTextGeometryPrivate::init() m_positionAttribute = new Qt3DRender::QAttribute(q); m_normalAttribute = new Qt3DRender::QAttribute(q); m_indexAttribute = new Qt3DRender::QAttribute(q); - m_vertexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, q); - m_indexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::IndexBuffer, q); + m_vertexBuffer = new Qt3DRender::QBuffer(q); + m_indexBuffer = new Qt3DRender::QBuffer(q); const quint32 elementSize = 3 + 3; const quint32 stride = elementSize * sizeof(float); diff --git a/src/extras/defaults/defaults.pri b/src/extras/defaults/defaults.pri index d3fd122ae..2575de1a3 100644 --- a/src/extras/defaults/defaults.pri +++ b/src/extras/defaults/defaults.pri @@ -25,6 +25,8 @@ HEADERS += \ $$PWD/qphongalphamaterial_p.h \ $$PWD/qt3dwindow.h \ $$PWD/qt3dwindow_p.h \ + $$PWD/qabstractcameracontroller.h \ + $$PWD/qabstractcameracontroller_p.h \ $$PWD/qfirstpersoncameracontroller.h \ $$PWD/qfirstpersoncameracontroller_p.h \ $$PWD/qorbitcameracontroller.h \ @@ -58,6 +60,7 @@ SOURCES += \ $$PWD/qgoochmaterial.cpp \ $$PWD/qphongalphamaterial.cpp \ $$PWD/qt3dwindow.cpp \ + $$PWD/qabstractcameracontroller.cpp \ $$PWD/qfirstpersoncameracontroller.cpp \ $$PWD/qorbitcameracontroller.cpp \ $$PWD/qabstractspritesheet.cpp \ diff --git a/src/extras/defaults/qabstractcameracontroller.cpp b/src/extras/defaults/qabstractcameracontroller.cpp new file mode 100644 index 000000000..8bf57f5fa --- /dev/null +++ b/src/extras/defaults/qabstractcameracontroller.cpp @@ -0,0 +1,436 @@ +/**************************************************************************** +** +** Copyright (C) 2016 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 "qabstractcameracontroller.h" +#include "qabstractcameracontroller_p.h" + +#include <Qt3DRender/QCamera> +#include <Qt3DInput/QAxis> +#include <Qt3DInput/QAnalogAxisInput> +#include <Qt3DInput/QButtonAxisInput> +#include <Qt3DInput/QAction> +#include <Qt3DInput/QActionInput> +#include <Qt3DInput/QLogicalDevice> +#include <Qt3DInput/QKeyboardDevice> +#include <Qt3DInput/QMouseDevice> +#include <Qt3DInput/QMouseEvent> +#include <Qt3DLogic/QFrameAction> +#include <QtCore/QtGlobal> + +QT_BEGIN_NAMESPACE + +namespace Qt3DExtras { + +QAbstractCameraControllerPrivate::QAbstractCameraControllerPrivate() + : Qt3DCore::QEntityPrivate() + , m_camera(nullptr) + , m_leftMouseButtonAction(new Qt3DInput::QAction()) + , m_middleMouseButtonAction(new Qt3DInput::QAction()) + , m_rightMouseButtonAction(new Qt3DInput::QAction()) + , m_altButtonAction(new Qt3DInput::QAction()) + , m_shiftButtonAction(new Qt3DInput::QAction()) + , m_rxAxis(new Qt3DInput::QAxis()) + , m_ryAxis(new Qt3DInput::QAxis()) + , m_txAxis(new Qt3DInput::QAxis()) + , m_tyAxis(new Qt3DInput::QAxis()) + , m_tzAxis(new Qt3DInput::QAxis()) + , m_leftMouseButtonInput(new Qt3DInput::QActionInput()) + , m_middleMouseButtonInput(new Qt3DInput::QActionInput()) + , m_rightMouseButtonInput(new Qt3DInput::QActionInput()) + , m_altButtonInput(new Qt3DInput::QActionInput()) + , m_shiftButtonInput(new Qt3DInput::QActionInput()) + , m_mouseRxInput(new Qt3DInput::QAnalogAxisInput()) + , m_mouseRyInput(new Qt3DInput::QAnalogAxisInput()) + , m_mouseTzXInput(new Qt3DInput::QAnalogAxisInput()) + , m_mouseTzYInput(new Qt3DInput::QAnalogAxisInput()) + , m_keyboardTxPosInput(new Qt3DInput::QButtonAxisInput()) + , m_keyboardTyPosInput(new Qt3DInput::QButtonAxisInput()) + , m_keyboardTzPosInput(new Qt3DInput::QButtonAxisInput()) + , m_keyboardTxNegInput(new Qt3DInput::QButtonAxisInput()) + , m_keyboardTyNegInput(new Qt3DInput::QButtonAxisInput()) + , m_keyboardTzNegInput(new Qt3DInput::QButtonAxisInput()) + , m_keyboardDevice(new Qt3DInput::QKeyboardDevice()) + , m_mouseDevice(new Qt3DInput::QMouseDevice()) + , m_logicalDevice(new Qt3DInput::QLogicalDevice()) + , m_frameAction(new Qt3DLogic::QFrameAction()) + , m_linearSpeed(10.0f) + , m_lookSpeed(180.0f) + , m_acceleration(-1.0f) + , m_deceleration(-1.0f) + , m_sceneUp(0.0f, 1.0f, 0.0f) +{} + +void QAbstractCameraControllerPrivate::init() +{ + //// Actions + + // Left Mouse Button Action + m_leftMouseButtonInput->setButtons(QVector<int>() << Qt::LeftButton); + m_leftMouseButtonInput->setSourceDevice(m_mouseDevice); + m_leftMouseButtonAction->addInput(m_leftMouseButtonInput); + + // Middle Mouse Button Action + m_middleMouseButtonInput->setButtons(QVector<int>() << Qt::MiddleButton); + m_middleMouseButtonInput->setSourceDevice(m_mouseDevice); + m_middleMouseButtonAction->addInput(m_middleMouseButtonInput); + + // Right Mouse Button Action + m_rightMouseButtonInput->setButtons(QVector<int>() << Qt::RightButton); + m_rightMouseButtonInput->setSourceDevice(m_mouseDevice); + m_rightMouseButtonAction->addInput(m_rightMouseButtonInput); + + // Alt Button Action + m_altButtonInput->setButtons(QVector<int>() << Qt::Key_Alt); + m_altButtonInput->setSourceDevice(m_keyboardDevice); + m_altButtonAction->addInput(m_altButtonInput); + + // Shift Button Action + m_shiftButtonInput->setButtons(QVector<int>() << Qt::Key_Shift); + m_shiftButtonInput->setSourceDevice(m_keyboardDevice); + m_shiftButtonAction->addInput(m_shiftButtonInput); + + //// Axes + + // Mouse X + m_mouseRxInput->setAxis(Qt3DInput::QMouseDevice::X); + m_mouseRxInput->setSourceDevice(m_mouseDevice); + m_rxAxis->addInput(m_mouseRxInput); + + // Mouse Y + m_mouseRyInput->setAxis(Qt3DInput::QMouseDevice::Y); + m_mouseRyInput->setSourceDevice(m_mouseDevice); + m_ryAxis->addInput(m_mouseRyInput); + + // Mouse Wheel X + m_mouseTzXInput->setAxis(Qt3DInput::QMouseDevice::WheelX); + m_mouseTzXInput->setSourceDevice(m_mouseDevice); + m_tzAxis->addInput(m_mouseTzXInput); + + // Mouse Wheel Y + m_mouseTzYInput->setAxis(Qt3DInput::QMouseDevice::WheelY); + m_mouseTzYInput->setSourceDevice(m_mouseDevice); + m_tzAxis->addInput(m_mouseTzYInput); + + // Keyboard Pos Tx + m_keyboardTxPosInput->setButtons(QVector<int>() << Qt::Key_Right); + m_keyboardTxPosInput->setScale(1.0f); + m_keyboardTxPosInput->setSourceDevice(m_keyboardDevice); + m_txAxis->addInput(m_keyboardTxPosInput); + + // Keyboard Pos Tz + m_keyboardTzPosInput->setButtons(QVector<int>() << Qt::Key_PageUp); + m_keyboardTzPosInput->setScale(1.0f); + m_keyboardTzPosInput->setSourceDevice(m_keyboardDevice); + m_tzAxis->addInput(m_keyboardTzPosInput); + + // Keyboard Pos Ty + m_keyboardTyPosInput->setButtons(QVector<int>() << Qt::Key_Up); + m_keyboardTyPosInput->setScale(1.0f); + m_keyboardTyPosInput->setSourceDevice(m_keyboardDevice); + m_tyAxis->addInput(m_keyboardTyPosInput); + + // Keyboard Neg Tx + m_keyboardTxNegInput->setButtons(QVector<int>() << Qt::Key_Left); + m_keyboardTxNegInput->setScale(-1.0f); + m_keyboardTxNegInput->setSourceDevice(m_keyboardDevice); + m_txAxis->addInput(m_keyboardTxNegInput); + + // Keyboard Neg Tz + m_keyboardTzNegInput->setButtons(QVector<int>() << Qt::Key_PageDown); + m_keyboardTzNegInput->setScale(-1.0f); + m_keyboardTzNegInput->setSourceDevice(m_keyboardDevice); + m_tzAxis->addInput(m_keyboardTzNegInput); + + // Keyboard Neg Ty + m_keyboardTyNegInput->setButtons(QVector<int>() << Qt::Key_Down); + m_keyboardTyNegInput->setScale(-1.0f); + m_keyboardTyNegInput->setSourceDevice(m_keyboardDevice); + m_tyAxis->addInput(m_keyboardTyNegInput); + + //// Logical Device + + m_logicalDevice->addAction(m_leftMouseButtonAction); + m_logicalDevice->addAction(m_middleMouseButtonAction); + m_logicalDevice->addAction(m_rightMouseButtonAction); + m_logicalDevice->addAction(m_altButtonAction); + m_logicalDevice->addAction(m_shiftButtonAction); + m_logicalDevice->addAxis(m_rxAxis); + m_logicalDevice->addAxis(m_ryAxis); + m_logicalDevice->addAxis(m_txAxis); + m_logicalDevice->addAxis(m_tyAxis); + m_logicalDevice->addAxis(m_tzAxis); + + applyInputAccelerations(); + + Q_Q(QAbstractCameraController); + //// FrameAction + + // Disable the logical device when the entity is disabled + QObject::connect(q, &Qt3DCore::QEntity::enabledChanged, + m_logicalDevice, &Qt3DInput::QLogicalDevice::setEnabled); + + q->addComponent(m_frameAction); + q->addComponent(m_logicalDevice); +} + +void QAbstractCameraControllerPrivate::applyInputAccelerations() +{ + const auto inputs = { + m_keyboardTxPosInput, + m_keyboardTyPosInput, + m_keyboardTzPosInput, + m_keyboardTxNegInput, + m_keyboardTyNegInput, + m_keyboardTzNegInput + }; + + for (auto input : inputs) { + input->setAcceleration(m_acceleration); + input->setDeceleration(m_deceleration); + } +} + +/*! + \class QAbstractCameraController + + \brief The QAbstractCameraController class provides basic + functionality for camera controllers. + + \inmodule Qt3DExtras + \since 5.10 + + QAbstractCameraController sets up and handles input from keyboard, + mouse, and other devices. QAbstractCameraController is an abstract + class and cannot itself be instantiated. It provides a standard + interface for camera controllers. + + Derived classes need only implement the frameActionTriggered() + method to move the camera. +*/ + +/*! + \fn void QAbstractCameraController::moveCamera(const InputState &state, float dt) = 0 + + This method is called whenever a frame action is triggered. Derived + classes must override this method to implement the camera movement + specific to the controller. + + In the base class this is a pure virtual function. +*/ + +QAbstractCameraController::QAbstractCameraController(Qt3DCore::QNode *parent) + : QAbstractCameraController(*new QAbstractCameraControllerPrivate, parent) +{ +} + +/*! \internal + */ +QAbstractCameraController::QAbstractCameraController(QAbstractCameraControllerPrivate &dd, Qt3DCore::QNode *parent) + : Qt3DCore::QEntity(dd, parent) +{ + Q_D(QAbstractCameraController); + d->init(); + + QObject::connect(d->m_frameAction, &Qt3DLogic::QFrameAction::triggered, + this, [=] (float dt) { + InputState state; + + state.rxAxisValue = d->m_rxAxis->value(); + state.ryAxisValue = d->m_ryAxis->value(); + state.txAxisValue = d->m_txAxis->value(); + state.tyAxisValue = d->m_tyAxis->value(); + state.tzAxisValue = d->m_tzAxis->value(); + + state.leftMouseButtonActive = d->m_leftMouseButtonAction->isActive(); + state.middleMouseButtonActive = d->m_middleMouseButtonAction->isActive(); + state.rightMouseButtonActive = d->m_rightMouseButtonAction->isActive(); + + state.altKeyActive = d->m_altButtonAction->isActive(); + state.shiftKeyActive = d->m_shiftButtonAction->isActive(); + + moveCamera(state, dt); + }); +} + +QAbstractCameraController::~QAbstractCameraController() +{ +} + +/*! + \property QAbstractCameraController::camera + + Holds the currently controlled camera. +*/ +Qt3DRender::QCamera *QAbstractCameraController::camera() const +{ + Q_D(const QAbstractCameraController); + return d->m_camera; +} + +/*! + \property QAbstractCameraController::linearSpeed + + Holds the current linear speed of the camera controller. Linear speed determines the + movement speed of the camera. + + The default is 10.0. +*/ +float QAbstractCameraController::linearSpeed() const +{ + Q_D(const QAbstractCameraController); + return d->m_linearSpeed; +} + +/*! + \property QAbstractCameraController::lookSpeed + + Holds the current look speed of the camera controller. The look speed determines the turn rate + of the camera pan and tilt. + + The default is 180.0. +*/ +float QAbstractCameraController::lookSpeed() const +{ + Q_D(const QAbstractCameraController); + return d->m_lookSpeed; +} + +/*! + \property QAbstractCameraController::acceleration + + Holds the current acceleration of the camera controller. +*/ +float QAbstractCameraController::acceleration() const +{ + Q_D(const QAbstractCameraController); + return d->m_acceleration; +} + +/*! + \property QAbstractCameraController::deceleration + + Holds the current deceleration of the camera controller. +*/ +float QAbstractCameraController::deceleration() const +{ + Q_D(const QAbstractCameraController); + return d->m_deceleration; +} + +void QAbstractCameraController::setCamera(Qt3DRender::QCamera *camera) +{ + Q_D(QAbstractCameraController); + if (d->m_camera != camera) { + + if (d->m_camera) + d->unregisterDestructionHelper(d->m_camera); + + if (camera && !camera->parent()) + camera->setParent(this); + + d->m_camera = camera; + + // Ensures proper bookkeeping + if (d->m_camera) + d->registerDestructionHelper(d->m_camera, &QAbstractCameraController::setCamera, d->m_camera); + + emit cameraChanged(); + } +} + +void QAbstractCameraController::setLinearSpeed(float linearSpeed) +{ + Q_D(QAbstractCameraController); + if (d->m_linearSpeed != linearSpeed) { + d->m_linearSpeed = linearSpeed; + emit linearSpeedChanged(); + } +} + +void QAbstractCameraController::setLookSpeed(float lookSpeed) +{ + Q_D(QAbstractCameraController); + if (d->m_lookSpeed != lookSpeed) { + d->m_lookSpeed = lookSpeed; + emit lookSpeedChanged(); + } +} + +void QAbstractCameraController::setAcceleration(float acceleration) +{ + Q_D(QAbstractCameraController); + if (d->m_acceleration != acceleration) { + d->m_acceleration = acceleration; + d->applyInputAccelerations(); + emit accelerationChanged(acceleration); + } +} + +void QAbstractCameraController::setDeceleration(float deceleration) +{ + Q_D(QAbstractCameraController); + if (d->m_deceleration != deceleration) { + d->m_deceleration = deceleration; + d->applyInputAccelerations(); + emit decelerationChanged(deceleration); + } +} + +/*! + Provides access to the keyboard device. +*/ + +Qt3DInput::QKeyboardDevice *QAbstractCameraController::keyboardDevice() const +{ + Q_D(const QAbstractCameraController); + return d->m_keyboardDevice; +} + +/*! + Provides access to the mouse device. +*/ + +Qt3DInput::QMouseDevice *QAbstractCameraController::mouseDevice() const +{ + Q_D(const QAbstractCameraController); + return d->m_mouseDevice; +} + +} // Qt3DExtras + +QT_END_NAMESPACE + +#include "moc_qabstractcameracontroller.cpp" diff --git a/src/extras/defaults/qabstractcameracontroller.h b/src/extras/defaults/qabstractcameracontroller.h new file mode 100644 index 000000000..f13079f5f --- /dev/null +++ b/src/extras/defaults/qabstractcameracontroller.h @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** Copyright (C) 2016 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 QT3DEXTRAS_QABSTRACTCAMERACONTROLLER_H +#define QT3DEXTRAS_QABSTRACTCAMERACONTROLLER_H + +#include <Qt3DCore/QEntity> +#include <Qt3DExtras/qt3dextras_global.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DInput { +class QKeyboardDevice; +class QMouseDevice; +} + +namespace Qt3DRender { +class QCamera; +} + +namespace Qt3DExtras { + +class QAbstractCameraControllerPrivate; + +class QT3DEXTRASSHARED_EXPORT QAbstractCameraController : public Qt3DCore::QEntity +{ + Q_OBJECT + Q_PROPERTY(Qt3DRender::QCamera *camera READ camera WRITE setCamera NOTIFY cameraChanged) + Q_PROPERTY(float linearSpeed READ linearSpeed WRITE setLinearSpeed NOTIFY linearSpeedChanged) + Q_PROPERTY(float lookSpeed READ lookSpeed WRITE setLookSpeed NOTIFY lookSpeedChanged) + Q_PROPERTY(float acceleration READ acceleration WRITE setAcceleration NOTIFY accelerationChanged) + Q_PROPERTY(float deceleration READ deceleration WRITE setDeceleration NOTIFY decelerationChanged) + +public: + ~QAbstractCameraController(); + + Qt3DRender::QCamera *camera() const; + float linearSpeed() const; + float lookSpeed() const; + + float acceleration() const; + float deceleration() const; + + void setCamera(Qt3DRender::QCamera *camera); + void setLinearSpeed(float linearSpeed); + void setLookSpeed(float lookSpeed); + + void setAcceleration(float acceleration); + void setDeceleration(float deceleration); + +Q_SIGNALS: + void cameraChanged(); + void linearSpeedChanged(); + void lookSpeedChanged(); + + void accelerationChanged(float acceleration); + void decelerationChanged(float deceleration); + +protected: + explicit QAbstractCameraController(Qt3DCore::QNode *parent = nullptr); + QAbstractCameraController(QAbstractCameraControllerPrivate &dd, Qt3DCore::QNode *parent = nullptr); + + Qt3DInput::QKeyboardDevice *keyboardDevice() const; + Qt3DInput::QMouseDevice *mouseDevice() const; + + struct InputState + { + float rxAxisValue; + float ryAxisValue; + float txAxisValue; + float tyAxisValue; + float tzAxisValue; + + bool leftMouseButtonActive; + bool middleMouseButtonActive; + bool rightMouseButtonActive; + + bool altKeyActive; + bool shiftKeyActive; + }; + +private: + virtual void moveCamera(const InputState &state, float dt) = 0; + +private: + Q_DECLARE_PRIVATE(QAbstractCameraController) +}; + +} // Qt3DExtras + +QT_END_NAMESPACE + +#endif // QT3DEXTRAS_QABSTRACTCAMERACONTROLLER_H diff --git a/src/extras/defaults/qabstractcameracontroller_p.h b/src/extras/defaults/qabstractcameracontroller_p.h new file mode 100644 index 000000000..00424a55b --- /dev/null +++ b/src/extras/defaults/qabstractcameracontroller_p.h @@ -0,0 +1,141 @@ +/**************************************************************************** +** +** Copyright (C) 2014 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 QT3DEXTRAS_QABSTRACTCAMERACONTROLLER_P_H +#define QT3DEXTRAS_QABSTRACTCAMERACONTROLLER_P_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 <Qt3DExtras/qabstractcameracontroller.h> +#include <QtGui/QVector3D> + +#include <Qt3DCore/private/qentity_p.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { +class QCamera; +} + +namespace Qt3DLogic { +class QFrameAction; +} + +namespace Qt3DInput { +class QKeyboardDevice; +class QMouseDevice; +class QLogicalDevice; +class QAction; +class QActionInput; +class QAxis; +class QAnalogAxisInput; +class QButtonAxisInput; +class QAxisActionHandler; +} + +namespace Qt3DExtras { + +class QAbstractCameraControllerPrivate : public Qt3DCore::QEntityPrivate +{ +public: + QAbstractCameraControllerPrivate(); + + void init(); + void applyInputAccelerations(); + + Qt3DRender::QCamera *m_camera; + + Qt3DInput::QAction *m_leftMouseButtonAction; + Qt3DInput::QAction *m_middleMouseButtonAction; + Qt3DInput::QAction *m_rightMouseButtonAction; + Qt3DInput::QAction *m_altButtonAction; + Qt3DInput::QAction *m_shiftButtonAction; + + Qt3DInput::QAxis *m_rxAxis; + Qt3DInput::QAxis *m_ryAxis; + Qt3DInput::QAxis *m_txAxis; + Qt3DInput::QAxis *m_tyAxis; + Qt3DInput::QAxis *m_tzAxis; + + Qt3DInput::QActionInput *m_leftMouseButtonInput; + Qt3DInput::QActionInput *m_middleMouseButtonInput; + Qt3DInput::QActionInput *m_rightMouseButtonInput; + Qt3DInput::QActionInput *m_altButtonInput; + Qt3DInput::QActionInput *m_shiftButtonInput; + + Qt3DInput::QAnalogAxisInput *m_mouseRxInput; + Qt3DInput::QAnalogAxisInput *m_mouseRyInput; + Qt3DInput::QAnalogAxisInput *m_mouseTzXInput; + Qt3DInput::QAnalogAxisInput *m_mouseTzYInput; + Qt3DInput::QButtonAxisInput *m_keyboardTxPosInput; + Qt3DInput::QButtonAxisInput *m_keyboardTyPosInput; + Qt3DInput::QButtonAxisInput *m_keyboardTzPosInput; + Qt3DInput::QButtonAxisInput *m_keyboardTxNegInput; + Qt3DInput::QButtonAxisInput *m_keyboardTyNegInput; + Qt3DInput::QButtonAxisInput *m_keyboardTzNegInput; + + Qt3DInput::QKeyboardDevice *m_keyboardDevice; + Qt3DInput::QMouseDevice *m_mouseDevice; + + Qt3DInput::QLogicalDevice *m_logicalDevice; + + Qt3DLogic::QFrameAction *m_frameAction; + + float m_linearSpeed; + float m_lookSpeed; + + float m_acceleration; + float m_deceleration; + + QVector3D m_sceneUp; + + Q_DECLARE_PUBLIC(QAbstractCameraController) +}; + +} // namespace Qt3DExtras + +QT_END_NAMESPACE + +#endif // QT3DEXTRAS_QABSTRACTCAMERACONTROLLER_P_H diff --git a/src/extras/defaults/qdiffusemapmaterial.cpp b/src/extras/defaults/qdiffusemapmaterial.cpp index a6da98a2e..930fbbd1f 100644 --- a/src/extras/defaults/qdiffusemapmaterial.cpp +++ b/src/extras/defaults/qdiffusemapmaterial.cpp @@ -98,9 +98,9 @@ void QDiffuseMapMaterialPrivate::init() connect(m_textureScaleParameter, &Qt3DRender::QParameter::valueChanged, this, &QDiffuseMapMaterialPrivate::handleTextureScaleChanged); - m_diffuseMapGL3Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/diffusemap.vert")))); + 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_diffuseMapGL2ES2Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/diffusemap.vert")))); + 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_diffuseMapGL3Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL); diff --git a/src/extras/defaults/qdiffusespecularmapmaterial.cpp b/src/extras/defaults/qdiffusespecularmapmaterial.cpp index 615ee6305..2e98bc8e7 100644 --- a/src/extras/defaults/qdiffusespecularmapmaterial.cpp +++ b/src/extras/defaults/qdiffusespecularmapmaterial.cpp @@ -105,9 +105,9 @@ void QDiffuseSpecularMapMaterialPrivate::init() connect(m_textureScaleParameter, &Qt3DRender::QParameter::valueChanged, this, &QDiffuseSpecularMapMaterialPrivate::handleTextureScaleChanged); - m_diffuseSpecularMapGL3Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/diffusemap.vert")))); + 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_diffuseSpecularMapGL2ES2Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/diffusemap.vert")))); + 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_diffuseSpecularMapGL3Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL); diff --git a/src/extras/defaults/qfirstpersoncameracontroller.cpp b/src/extras/defaults/qfirstpersoncameracontroller.cpp index 5321bfcf2..2ad997d05 100644 --- a/src/extras/defaults/qfirstpersoncameracontroller.cpp +++ b/src/extras/defaults/qfirstpersoncameracontroller.cpp @@ -35,188 +35,13 @@ ****************************************************************************/ #include "qfirstpersoncameracontroller.h" -#include "qfirstpersoncameracontroller_p.h" -#include <Qt3DInput/QAction> -#include <Qt3DInput/QActionInput> -#include <Qt3DInput/QAnalogAxisInput> -#include <Qt3DInput/QAxis> -#include <Qt3DInput/QButtonAxisInput> -#include <Qt3DLogic/QFrameAction> -#include <Qt3DInput/QKeyboardDevice> -#include <Qt3DInput/QLogicalDevice> -#include <Qt3DInput/QMouseDevice> -#include <Qt3DInput/QMouseEvent> #include <Qt3DRender/QCamera> QT_BEGIN_NAMESPACE namespace Qt3DExtras { -QFirstPersonCameraControllerPrivate::QFirstPersonCameraControllerPrivate() - : Qt3DCore::QEntityPrivate() - , m_camera(nullptr) - , m_leftMouseButtonAction(new Qt3DInput::QAction()) - , m_fineMotionAction(new Qt3DInput::QAction()) - , m_rxAxis(new Qt3DInput::QAxis()) - , m_ryAxis(new Qt3DInput::QAxis()) - , m_txAxis(new Qt3DInput::QAxis()) - , m_tyAxis(new Qt3DInput::QAxis()) - , m_tzAxis(new Qt3DInput::QAxis()) - , m_leftMouseButtonInput(new Qt3DInput::QActionInput()) - , m_fineMotionKeyInput(new Qt3DInput::QActionInput()) - , m_mouseRxInput(new Qt3DInput::QAnalogAxisInput()) - , m_mouseRyInput(new Qt3DInput::QAnalogAxisInput()) - , m_mouseTzXInput(new Qt3DInput::QAnalogAxisInput()) - , m_mouseTzYInput(new Qt3DInput::QAnalogAxisInput()) - , m_keyboardTxPosInput(new Qt3DInput::QButtonAxisInput()) - , m_keyboardTyPosInput(new Qt3DInput::QButtonAxisInput()) - , m_keyboardTzPosInput(new Qt3DInput::QButtonAxisInput()) - , m_keyboardTxNegInput(new Qt3DInput::QButtonAxisInput()) - , m_keyboardTyNegInput(new Qt3DInput::QButtonAxisInput()) - , m_keyboardTzNegInput(new Qt3DInput::QButtonAxisInput()) - , m_keyboardDevice(new Qt3DInput::QKeyboardDevice()) - , m_mouseDevice(new Qt3DInput::QMouseDevice()) - , m_logicalDevice(new Qt3DInput::QLogicalDevice()) - , m_frameAction(new Qt3DLogic::QFrameAction()) - , m_linearSpeed(10.0f) - , m_lookSpeed(180.0f) - , m_acceleration(-1.0f) - , m_deceleration(-1.0f) - , m_firstPersonUp(QVector3D(0.0f, 1.0f, 0.0f)) -{} - -void QFirstPersonCameraControllerPrivate::init() -{ - //// Actions - - // Left Mouse Button Action - m_leftMouseButtonInput->setButtons(QVector<int>() << Qt::LeftButton); - m_leftMouseButtonInput->setSourceDevice(m_mouseDevice); - m_leftMouseButtonAction->addInput(m_leftMouseButtonInput); - - // Fine Motion Action - m_fineMotionKeyInput->setButtons(QVector<int>() << Qt::Key_Shift); - m_fineMotionKeyInput->setSourceDevice(m_keyboardDevice); - m_fineMotionAction->addInput(m_fineMotionKeyInput); - - //// Axes - - // Mouse X - m_mouseRxInput->setAxis(Qt3DInput::QMouseDevice::X); - m_mouseRxInput->setSourceDevice(m_mouseDevice); - m_rxAxis->addInput(m_mouseRxInput); - - // Mouse Y - m_mouseRyInput->setAxis(Qt3DInput::QMouseDevice::Y); - m_mouseRyInput->setSourceDevice(m_mouseDevice); - m_ryAxis->addInput(m_mouseRyInput); - - // Mouse Wheel X - m_mouseTzXInput->setAxis(Qt3DInput::QMouseDevice::WheelX); - m_mouseTzXInput->setSourceDevice(m_mouseDevice); - m_tzAxis->addInput(m_mouseTzXInput); - - // Mouse Wheel Y - m_mouseTzYInput->setAxis(Qt3DInput::QMouseDevice::WheelY); - m_mouseTzYInput->setSourceDevice(m_mouseDevice); - m_tzAxis->addInput(m_mouseTzYInput); - - // Keyboard Pos Tx - m_keyboardTxPosInput->setButtons(QVector<int>() << Qt::Key_Right); - m_keyboardTxPosInput->setScale(1.0f); - m_keyboardTxPosInput->setSourceDevice(m_keyboardDevice); - m_txAxis->addInput(m_keyboardTxPosInput); - - // Keyboard Pos Ty - m_keyboardTyPosInput->setButtons(QVector<int>() << Qt::Key_PageUp); - m_keyboardTyPosInput->setScale(1.0f); - m_keyboardTyPosInput->setSourceDevice(m_keyboardDevice); - m_tyAxis->addInput(m_keyboardTyPosInput); - - // Keyboard Pos Tz - m_keyboardTzPosInput->setButtons(QVector<int>() << Qt::Key_Up); - m_keyboardTzPosInput->setScale(1.0f); - m_keyboardTzPosInput->setSourceDevice(m_keyboardDevice); - m_tzAxis->addInput(m_keyboardTzPosInput); - - // Keyboard Neg Tx - m_keyboardTxNegInput->setButtons(QVector<int>() << Qt::Key_Left); - m_keyboardTxNegInput->setScale(-1.0f); - m_keyboardTxNegInput->setSourceDevice(m_keyboardDevice); - m_txAxis->addInput(m_keyboardTxNegInput); - - // Keyboard Neg Ty - m_keyboardTyNegInput->setButtons(QVector<int>() << Qt::Key_PageDown); - m_keyboardTyNegInput->setScale(-1.0f); - m_keyboardTyNegInput->setSourceDevice(m_keyboardDevice); - m_tyAxis->addInput(m_keyboardTyNegInput); - - // Keyboard Neg Tz - m_keyboardTzNegInput->setButtons(QVector<int>() << Qt::Key_Down); - m_keyboardTzNegInput->setScale(-1.0f); - m_keyboardTzNegInput->setSourceDevice(m_keyboardDevice); - m_tzAxis->addInput(m_keyboardTzNegInput); - - //// Logical Device - - m_logicalDevice->addAction(m_fineMotionAction); - m_logicalDevice->addAction(m_leftMouseButtonAction); - m_logicalDevice->addAxis(m_rxAxis); - m_logicalDevice->addAxis(m_ryAxis); - m_logicalDevice->addAxis(m_txAxis); - m_logicalDevice->addAxis(m_tyAxis); - m_logicalDevice->addAxis(m_tzAxis); - - applyAccelerations(); - - Q_Q(QFirstPersonCameraController); - //// FrameAction - - QObject::connect(m_frameAction, SIGNAL(triggered(float)), - q, SLOT(_q_onTriggered(float))); - - // Disable the logical device when the entity is disabled - QObject::connect(q, &Qt3DCore::QEntity::enabledChanged, - m_logicalDevice, &Qt3DInput::QLogicalDevice::setEnabled); - - q->addComponent(m_frameAction); - q->addComponent(m_logicalDevice); -} - -void QFirstPersonCameraControllerPrivate::applyAccelerations() -{ - const auto inputs = { - m_keyboardTxPosInput, - m_keyboardTyPosInput, - m_keyboardTzPosInput, - m_keyboardTxNegInput, - m_keyboardTyNegInput, - m_keyboardTzNegInput - }; - - for (auto input : inputs) { - input->setAcceleration(m_acceleration); - input->setDeceleration(m_deceleration); - } -} - -void QFirstPersonCameraControllerPrivate::_q_onTriggered(float dt) -{ - if (m_camera != nullptr) { - m_camera->translate(QVector3D(m_txAxis->value() * m_linearSpeed, - m_tyAxis->value() * m_linearSpeed, - m_tzAxis->value() * m_linearSpeed) * dt); - if (m_leftMouseButtonAction->isActive()) { - float lookSpeed = m_lookSpeed; - if (m_fineMotionAction->isActive()) - lookSpeed *= 0.2f; - m_camera->pan(m_rxAxis->value() * lookSpeed * dt, m_firstPersonUp); - m_camera->tilt(m_ryAxis->value() * lookSpeed * dt); - } - } -} - /*! \class Qt3DExtras::QFirstPersonCameraController \brief The QFirstPersonCameraController class allows controlling the scene camera @@ -251,129 +76,35 @@ void QFirstPersonCameraControllerPrivate::_q_onTriggered(float dt) */ QFirstPersonCameraController::QFirstPersonCameraController(Qt3DCore::QNode *parent) - : Qt3DCore::QEntity(*new QFirstPersonCameraControllerPrivate, parent) + : QAbstractCameraController(parent) { - Q_D(QFirstPersonCameraController); - d->init(); } QFirstPersonCameraController::~QFirstPersonCameraController() { } -/*! - \property QFirstPersonCameraController::camera - - Holds the currently controlled camera. -*/ -Qt3DRender::QCamera *QFirstPersonCameraController::camera() const -{ - Q_D(const QFirstPersonCameraController); - return d->m_camera; -} - -/*! - \property QFirstPersonCameraController::linearSpeed - Holds the current linear speed of the camera controller. Linear speed determines the - movement speed of the camera. -*/ -float QFirstPersonCameraController::linearSpeed() const +void QFirstPersonCameraController::moveCamera(const QAbstractCameraController::InputState &state, float dt) { - Q_D(const QFirstPersonCameraController); - return d->m_linearSpeed; -} - -/*! - \property QFirstPersonCameraController::lookSpeed - - Holds the current look speed of the camera controller. The look speed determines the turn rate - of the camera pan and tilt. -*/ -float QFirstPersonCameraController::lookSpeed() const -{ - Q_D(const QFirstPersonCameraController); - return d->m_lookSpeed; -} - -/*! - \property QFirstPersonCameraController::acceleration - - Holds the current acceleration of the camera controller. -*/ -float QFirstPersonCameraController::acceleration() const -{ - Q_D(const QFirstPersonCameraController); - return d->m_acceleration; -} - -/*! - \property QFirstPersonCameraController::deceleration - - Holds the current deceleration of the camera controller. -*/ -float QFirstPersonCameraController::deceleration() const -{ - Q_D(const QFirstPersonCameraController); - return d->m_deceleration; -} - -void QFirstPersonCameraController::setCamera(Qt3DRender::QCamera *camera) -{ - Q_D(QFirstPersonCameraController); - if (d->m_camera != camera) { - - if (d->m_camera) - d->unregisterDestructionHelper(d->m_camera); - - if (camera && !camera->parent()) - camera->setParent(this); - - d->m_camera = camera; - - // Ensures proper bookkeeping - if (d->m_camera) - d->registerDestructionHelper(d->m_camera, &QFirstPersonCameraController::setCamera, d->m_camera); - - emit cameraChanged(); - } -} - -void QFirstPersonCameraController::setLinearSpeed(float linearSpeed) -{ - Q_D(QFirstPersonCameraController); - if (d->m_linearSpeed != linearSpeed) { - d->m_linearSpeed = linearSpeed; - emit linearSpeedChanged(); - } -} - -void QFirstPersonCameraController::setLookSpeed(float lookSpeed) -{ - Q_D(QFirstPersonCameraController); - if (d->m_lookSpeed != lookSpeed) { - d->m_lookSpeed = lookSpeed; - emit lookSpeedChanged(); - } -} + Qt3DRender::QCamera *theCamera = camera(); + + if (theCamera == nullptr) + return; + + theCamera->translate(QVector3D(state.txAxisValue * linearSpeed(), + state.tyAxisValue * linearSpeed(), + state.tzAxisValue * linearSpeed()) * dt); + if (state.leftMouseButtonActive) { + float theLookSpeed = lookSpeed(); + if (state.shiftKeyActive) { + theLookSpeed *= 0.2f; + } -void QFirstPersonCameraController::setAcceleration(float acceleration) -{ - Q_D(QFirstPersonCameraController); - if (d->m_acceleration != acceleration) { - d->m_acceleration = acceleration; - d->applyAccelerations(); - emit accelerationChanged(acceleration); - } -} + const QVector3D upVector(0.0f, 1.0f, 0.0f); -void QFirstPersonCameraController::setDeceleration(float deceleration) -{ - Q_D(QFirstPersonCameraController); - if (d->m_deceleration != deceleration) { - d->m_deceleration = deceleration; - d->applyAccelerations(); - emit decelerationChanged(deceleration); + theCamera->pan(state.rxAxisValue * theLookSpeed * dt, upVector); + theCamera->tilt(state.ryAxisValue * theLookSpeed * dt); } } diff --git a/src/extras/defaults/qfirstpersoncameracontroller.h b/src/extras/defaults/qfirstpersoncameracontroller.h index 3f7a6acc4..60edf7cb8 100644 --- a/src/extras/defaults/qfirstpersoncameracontroller.h +++ b/src/extras/defaults/qfirstpersoncameracontroller.h @@ -37,53 +37,22 @@ #ifndef QT3DEXTRAS_QFIRSTPERSONCAMERACONTROLLER_H #define QT3DEXTRAS_QFIRSTPERSONCAMERACONTROLLER_H -#include <Qt3DExtras/qt3dextras_global.h> -#include <Qt3DCore/QEntity> +#include <Qt3DExtras/qabstractcameracontroller.h> QT_BEGIN_NAMESPACE -namespace Qt3DRender { -class QCamera; -} - namespace Qt3DExtras { -class QFirstPersonCameraControllerPrivate; - -class QT3DEXTRASSHARED_EXPORT QFirstPersonCameraController : public Qt3DCore::QEntity +class QT3DEXTRASSHARED_EXPORT QFirstPersonCameraController : public QAbstractCameraController { Q_OBJECT - Q_PROPERTY(Qt3DRender::QCamera *camera READ camera WRITE setCamera NOTIFY cameraChanged) - Q_PROPERTY(float linearSpeed READ linearSpeed WRITE setLinearSpeed NOTIFY linearSpeedChanged) - Q_PROPERTY(float lookSpeed READ lookSpeed WRITE setLookSpeed NOTIFY lookSpeedChanged) - Q_PROPERTY(float acceleration READ acceleration WRITE setAcceleration NOTIFY accelerationChanged) - Q_PROPERTY(float deceleration READ deceleration WRITE setDeceleration NOTIFY decelerationChanged) + public: explicit QFirstPersonCameraController(Qt3DCore::QNode *parent = nullptr); ~QFirstPersonCameraController(); - Qt3DRender::QCamera *camera() const; - float linearSpeed() const; - float lookSpeed() const; - float acceleration() const; - float deceleration() const; - - void setCamera(Qt3DRender::QCamera *camera); - void setLinearSpeed(float linearSpeed); - void setLookSpeed(float lookSpeed); - void setAcceleration(float acceleration); - void setDeceleration(float deceleration); - -Q_SIGNALS: - void cameraChanged(); - void linearSpeedChanged(); - void lookSpeedChanged(); - void accelerationChanged(float acceleration); - void decelerationChanged(float deceleration); - private: - Q_DECLARE_PRIVATE(QFirstPersonCameraController) - Q_PRIVATE_SLOT(d_func(), void _q_onTriggered(float)) + void moveCamera(const QAbstractCameraController::InputState &state, float dt) override; }; } // Qt3DExtras diff --git a/src/extras/defaults/qfirstpersoncameracontroller_p.h b/src/extras/defaults/qfirstpersoncameracontroller_p.h deleted file mode 100644 index 48a7c7998..000000000 --- a/src/extras/defaults/qfirstpersoncameracontroller_p.h +++ /dev/null @@ -1,152 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** 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 -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QT3DEXTRAS_QFIRSTPERSONCAMERACONTROLLER_P_H -#define QT3DEXTRAS_QFIRSTPERSONCAMERACONTROLLER_P_H - -#include <Qt3DExtras/qfirstpersoncameracontroller.h> -#include <QtGui/QVector3D> - -#include <Qt3DCore/private/qentity_p.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. -// - -QT_BEGIN_NAMESPACE - -namespace Qt3DRender { -class QCamera; -} - -namespace Qt3DLogic { -class QFrameAction; -} - -namespace Qt3DInput { - -class QKeyboardDevice; -class QMouseDevice; -class QLogicalDevice; -class QAction; -class QActionInput; -class QAxis; -class QAnalogAxisInput; -class QButtonAxisInput; -class QAxisActionHandler; - -} - -namespace Qt3DExtras { - -class QFirstPersonCameraControllerPrivate : public Qt3DCore::QEntityPrivate -{ -public: - QFirstPersonCameraControllerPrivate(); - - void init(); - void applyAccelerations(); - - Qt3DRender::QCamera *m_camera; - - Qt3DInput::QAction *m_leftMouseButtonAction; - Qt3DInput::QAction *m_fineMotionAction; - - Qt3DInput::QAxis *m_rxAxis; - Qt3DInput::QAxis *m_ryAxis; - Qt3DInput::QAxis *m_txAxis; - Qt3DInput::QAxis *m_tyAxis; - Qt3DInput::QAxis *m_tzAxis; - - Qt3DInput::QActionInput *m_leftMouseButtonInput; - Qt3DInput::QActionInput *m_fineMotionKeyInput; - - Qt3DInput::QAnalogAxisInput *m_mouseRxInput; - Qt3DInput::QAnalogAxisInput *m_mouseRyInput; - Qt3DInput::QAnalogAxisInput *m_mouseTzXInput; - Qt3DInput::QAnalogAxisInput *m_mouseTzYInput; - Qt3DInput::QButtonAxisInput *m_keyboardTxPosInput; - Qt3DInput::QButtonAxisInput *m_keyboardTyPosInput; - Qt3DInput::QButtonAxisInput *m_keyboardTzPosInput; - Qt3DInput::QButtonAxisInput *m_keyboardTxNegInput; - Qt3DInput::QButtonAxisInput *m_keyboardTyNegInput; - Qt3DInput::QButtonAxisInput *m_keyboardTzNegInput; - - Qt3DInput::QKeyboardDevice *m_keyboardDevice; - Qt3DInput::QMouseDevice *m_mouseDevice; - - Qt3DInput::QLogicalDevice *m_logicalDevice; - - Qt3DLogic::QFrameAction *m_frameAction; - - float m_linearSpeed; - float m_lookSpeed; - float m_acceleration; - float m_deceleration; - QVector3D m_firstPersonUp; - - void _q_onTriggered(float); - - Q_DECLARE_PUBLIC(QFirstPersonCameraController) -}; - -} // Qt3DInput - -QT_END_NAMESPACE - -#endif // QT3DINPUT_QFIRSTPERSONCAMERACONTROLLER_P_H diff --git a/src/extras/defaults/qmetalroughmaterial.cpp b/src/extras/defaults/qmetalroughmaterial.cpp index c3d59d9de..ac6117101 100644 --- a/src/extras/defaults/qmetalroughmaterial.cpp +++ b/src/extras/defaults/qmetalroughmaterial.cpp @@ -71,6 +71,7 @@ QMetalRoughMaterialPrivate::QMetalRoughMaterialPrivate() , m_roughnessMapParameter(new QParameter(QStringLiteral("roughnessMap"), QVariant())) , m_ambientOcclusionMapParameter(new QParameter(QStringLiteral("ambientOcclusionMap"), QVariant())) , m_normalMapParameter(new QParameter(QStringLiteral("normalMap"), QVariant())) + , m_textureScaleParameter(new QParameter(QStringLiteral("texCoordScale"), 1.0f)) , m_environmentIrradianceParameter(new QParameter(QStringLiteral("envLight.irradiance"), m_environmentIrradianceTexture)) , m_environmentSpecularParameter(new QParameter(QStringLiteral("envLight.specular"), m_environmentSpecularTexture)) , m_metalRoughEffect(new QEffect()) @@ -107,8 +108,10 @@ void QMetalRoughMaterialPrivate::init() q, &QMetalRoughMaterial::roughnessChanged); QObject::connect(m_normalMapParameter, &Qt3DRender::QParameter::valueChanged, q, &QMetalRoughMaterial::roughnessChanged); + connect(m_textureScaleParameter, &Qt3DRender::QParameter::valueChanged, + this, &QMetalRoughMaterialPrivate::handleTextureScaleChanged); - m_metalRoughGL3Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/metalrough.vert")))); + m_metalRoughGL3Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/default.vert")))); m_metalRoughGL3ShaderBuilder->setParent(q); m_metalRoughGL3ShaderBuilder->setShaderProgram(m_metalRoughGL3Shader); @@ -136,6 +139,7 @@ void QMetalRoughMaterialPrivate::init() m_metalRoughEffect->addParameter(m_baseColorParameter); m_metalRoughEffect->addParameter(m_metalnessParameter); m_metalRoughEffect->addParameter(m_roughnessParameter); + m_metalRoughEffect->addParameter(m_textureScaleParameter); // Note that even though those parameters are not exposed in the API, // they need to be kept around for now due to a bug in some drivers/GPUs @@ -149,6 +153,12 @@ void QMetalRoughMaterialPrivate::init() q->setEffect(m_metalRoughEffect); } +void QMetalRoughMaterialPrivate::handleTextureScaleChanged(const QVariant &var) +{ + Q_Q(QMetalRoughMaterial); + emit q->textureScaleChanged(var.toFloat()); +} + /*! \class Qt3DExtras::QMetalRoughMaterial \brief The QMetalRoughMaterial provides a default implementation of PBR @@ -249,6 +259,18 @@ QVariant QMetalRoughMaterial::normal() const return d->m_normalMapParameter->value(); } +/*! + \property QMetalRoughMaterial::textureScale + + Holds the current texture scale. It is applied as a multiplier to texture + coordinates at render time. Defaults to 1.0. +*/ +float QMetalRoughMaterial::textureScale() const +{ + Q_D(const QMetalRoughMaterial); + return d->m_textureScaleParameter->value().toFloat(); +} + void QMetalRoughMaterial::setBaseColor(const QVariant &baseColor) { Q_D(QMetalRoughMaterial); @@ -348,6 +370,12 @@ void QMetalRoughMaterial::setNormal(const QVariant &normal) d->m_metalRoughGL3ShaderBuilder->setEnabledLayers(layers); } +void QMetalRoughMaterial::setTextureScale(float textureScale) +{ + Q_D(QMetalRoughMaterial); + d->m_textureScaleParameter->setValue(textureScale); +} + } // namespace Qt3DExtras QT_END_NAMESPACE diff --git a/src/extras/defaults/qmetalroughmaterial.h b/src/extras/defaults/qmetalroughmaterial.h index 6da00ec08..400437338 100644 --- a/src/extras/defaults/qmetalroughmaterial.h +++ b/src/extras/defaults/qmetalroughmaterial.h @@ -62,6 +62,7 @@ class QT3DEXTRASSHARED_EXPORT QMetalRoughMaterial : public Qt3DRender::QMaterial Q_PROPERTY(QVariant roughness READ roughness WRITE setRoughness NOTIFY roughnessChanged) Q_PROPERTY(QVariant ambientOcclusion READ ambientOcclusion WRITE setAmbientOcclusion NOTIFY ambientOcclusionChanged REVISION 10) Q_PROPERTY(QVariant normal READ normal WRITE setNormal NOTIFY normalChanged REVISION 10) + Q_PROPERTY(float textureScale READ textureScale WRITE setTextureScale NOTIFY textureScaleChanged REVISION 10) public: explicit QMetalRoughMaterial(Qt3DCore::QNode *parent = nullptr); @@ -72,6 +73,7 @@ public: QVariant roughness() const; QVariant ambientOcclusion() const; QVariant normal() const; + float textureScale() const; public Q_SLOTS: void setBaseColor(const QVariant &baseColor); @@ -79,6 +81,7 @@ public Q_SLOTS: void setRoughness(const QVariant &roughness); void setAmbientOcclusion(const QVariant &ambientOcclusion); void setNormal(const QVariant &normal); + void setTextureScale(float textureScale); Q_SIGNALS: void baseColorChanged(const QVariant &baseColor); @@ -86,6 +89,7 @@ Q_SIGNALS: void roughnessChanged(const QVariant &roughness); void ambientOcclusionChanged(const QVariant &ambientOcclusion); void normalChanged(const QVariant &normal); + void textureScaleChanged(float textureScale); protected: explicit QMetalRoughMaterial(QMetalRoughMaterialPrivate &dd, Qt3DCore::QNode *parent = nullptr); diff --git a/src/extras/defaults/qmetalroughmaterial_p.h b/src/extras/defaults/qmetalroughmaterial_p.h index 8d6cbfcad..838474490 100644 --- a/src/extras/defaults/qmetalroughmaterial_p.h +++ b/src/extras/defaults/qmetalroughmaterial_p.h @@ -79,6 +79,8 @@ public: void init(); + void handleTextureScaleChanged(const QVariant &var); + Qt3DRender::QAbstractTexture *m_environmentIrradianceTexture; Qt3DRender::QAbstractTexture *m_environmentSpecularTexture; Qt3DRender::QParameter *m_baseColorParameter; @@ -89,6 +91,7 @@ public: Qt3DRender::QParameter *m_roughnessMapParameter; Qt3DRender::QParameter *m_ambientOcclusionMapParameter; Qt3DRender::QParameter *m_normalMapParameter; + Qt3DRender::QParameter *m_textureScaleParameter; Qt3DRender::QParameter *m_environmentIrradianceParameter; Qt3DRender::QParameter *m_environmentSpecularParameter; Qt3DRender::QEffect *m_metalRoughEffect; diff --git a/src/extras/defaults/qnormaldiffusemapalphamaterial.cpp b/src/extras/defaults/qnormaldiffusemapalphamaterial.cpp index eb6398341..dd8288683 100644 --- a/src/extras/defaults/qnormaldiffusemapalphamaterial.cpp +++ b/src/extras/defaults/qnormaldiffusemapalphamaterial.cpp @@ -82,10 +82,10 @@ void QNormalDiffuseMapAlphaMaterialPrivate::init() connect(m_textureScaleParameter, &Qt3DRender::QParameter::valueChanged, this, &QNormalDiffuseMapMaterialPrivate::handleTextureScaleChanged); - m_normalDiffuseGL3Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/normaldiffusemap.vert")))); - m_normalDiffuseGL3Shader->setFragmentShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/normaldiffusemapalpha.frag")))); - m_normalDiffuseGL2ES2Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/normaldiffusemap.vert")))); - m_normalDiffuseGL2ES2Shader->setFragmentShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/normaldiffusemapalpha.frag")))); + 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_normalDiffuseGL2ES2Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/default.vert")))); + m_normalDiffuseGL2ES2Shader->setFragmentShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/normaldiffusemap.frag")))); m_normalDiffuseGL3Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL); m_normalDiffuseGL3Technique->graphicsApiFilter()->setMajorVersion(3); diff --git a/src/extras/defaults/qnormaldiffusemapmaterial.cpp b/src/extras/defaults/qnormaldiffusemapmaterial.cpp index 35cea095a..ec3bd0a22 100644 --- a/src/extras/defaults/qnormaldiffusemapmaterial.cpp +++ b/src/extras/defaults/qnormaldiffusemapmaterial.cpp @@ -107,9 +107,9 @@ void QNormalDiffuseMapMaterialPrivate::init() connect(m_textureScaleParameter, &Qt3DRender::QParameter::valueChanged, this, &QNormalDiffuseMapMaterialPrivate::handleTextureScaleChanged); - m_normalDiffuseGL3Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/normaldiffusemap.vert")))); + 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_normalDiffuseGL2ES2Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/normaldiffusemap.vert")))); + 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_normalDiffuseGL3Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL); diff --git a/src/extras/defaults/qnormaldiffusespecularmapmaterial.cpp b/src/extras/defaults/qnormaldiffusespecularmapmaterial.cpp index c6f8ced9c..eaa1491a0 100644 --- a/src/extras/defaults/qnormaldiffusespecularmapmaterial.cpp +++ b/src/extras/defaults/qnormaldiffusespecularmapmaterial.cpp @@ -115,9 +115,9 @@ void QNormalDiffuseSpecularMapMaterialPrivate::init() connect(m_textureScaleParameter, &Qt3DRender::QParameter::valueChanged, this, &QNormalDiffuseSpecularMapMaterialPrivate::handleTextureScaleChanged); - m_normalDiffuseSpecularGL3Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/normaldiffusemap.vert")))); + 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_normalDiffuseSpecularGL2ES2Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/normaldiffusemap.vert")))); + 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_normalDiffuseSpecularGL3Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL); diff --git a/src/extras/defaults/qorbitcameracontroller.cpp b/src/extras/defaults/qorbitcameracontroller.cpp index 565a75ea1..03e9a290b 100644 --- a/src/extras/defaults/qorbitcameracontroller.cpp +++ b/src/extras/defaults/qorbitcameracontroller.cpp @@ -38,22 +38,15 @@ #include "qorbitcameracontroller_p.h" #include <Qt3DRender/QCamera> -#include <Qt3DInput/QAxis> -#include <Qt3DInput/QAnalogAxisInput> -#include <Qt3DInput/QButtonAxisInput> -#include <Qt3DInput/QAction> -#include <Qt3DInput/QActionInput> -#include <Qt3DInput/QLogicalDevice> -#include <Qt3DInput/QKeyboardDevice> -#include <Qt3DInput/QMouseDevice> -#include <Qt3DInput/QMouseEvent> -#include <Qt3DLogic/QFrameAction> -#include <QtCore/QtGlobal> QT_BEGIN_NAMESPACE namespace Qt3DExtras { +QOrbitCameraControllerPrivate::QOrbitCameraControllerPrivate() + : m_zoomInLimit(2.0f) +{} + /*! \class Qt3DExtras::QOrbitCameraController \brief The QOrbitCameraController class allows controlling the scene camera along orbital path. @@ -99,251 +92,20 @@ namespace Qt3DExtras { \endtable */ -QOrbitCameraControllerPrivate::QOrbitCameraControllerPrivate() - : Qt3DCore::QEntityPrivate() - , m_camera(nullptr) - , m_leftMouseButtonAction(new Qt3DInput::QAction()) - , m_rightMouseButtonAction(new Qt3DInput::QAction()) - , m_altButtonAction(new Qt3DInput::QAction()) - , m_shiftButtonAction(new Qt3DInput::QAction()) - , m_rxAxis(new Qt3DInput::QAxis()) - , m_ryAxis(new Qt3DInput::QAxis()) - , m_txAxis(new Qt3DInput::QAxis()) - , m_tyAxis(new Qt3DInput::QAxis()) - , m_tzAxis(new Qt3DInput::QAxis()) - , m_leftMouseButtonInput(new Qt3DInput::QActionInput()) - , m_rightMouseButtonInput(new Qt3DInput::QActionInput()) - , m_altButtonInput(new Qt3DInput::QActionInput()) - , m_shiftButtonInput(new Qt3DInput::QActionInput()) - , m_mouseRxInput(new Qt3DInput::QAnalogAxisInput()) - , m_mouseRyInput(new Qt3DInput::QAnalogAxisInput()) - , m_mouseTzXInput(new Qt3DInput::QAnalogAxisInput()) - , m_mouseTzYInput(new Qt3DInput::QAnalogAxisInput()) - , m_keyboardTxPosInput(new Qt3DInput::QButtonAxisInput()) - , m_keyboardTyPosInput(new Qt3DInput::QButtonAxisInput()) - , m_keyboardTzPosInput(new Qt3DInput::QButtonAxisInput()) - , m_keyboardTxNegInput(new Qt3DInput::QButtonAxisInput()) - , m_keyboardTyNegInput(new Qt3DInput::QButtonAxisInput()) - , m_keyboardTzNegInput(new Qt3DInput::QButtonAxisInput()) - , m_keyboardDevice(new Qt3DInput::QKeyboardDevice()) - , m_mouseDevice(new Qt3DInput::QMouseDevice()) - , m_logicalDevice(new Qt3DInput::QLogicalDevice()) - , m_frameAction(new Qt3DLogic::QFrameAction()) - , m_linearSpeed(10.0f) - , m_lookSpeed(180.0f) - , m_zoomInLimit(2.0f) - , m_cameraUp(QVector3D(0.0f, 1.0f, 0.0f)) -{} - -void QOrbitCameraControllerPrivate::init() -{ - //// Actions - - // Left Mouse Button Action - m_leftMouseButtonInput->setButtons(QVector<int>() << Qt::LeftButton); - m_leftMouseButtonInput->setSourceDevice(m_mouseDevice); - m_leftMouseButtonAction->addInput(m_leftMouseButtonInput); - - // Right Mouse Button Action - m_rightMouseButtonInput->setButtons(QVector<int>() << Qt::RightButton); - m_rightMouseButtonInput->setSourceDevice(m_mouseDevice); - m_rightMouseButtonAction->addInput(m_rightMouseButtonInput); - - // Alt Button Action - m_altButtonInput->setButtons(QVector<int>() << Qt::Key_Alt); - m_altButtonInput->setSourceDevice(m_keyboardDevice); - m_altButtonAction->addInput(m_altButtonInput); - - // Shift Button Action - m_shiftButtonInput->setButtons(QVector<int>() << Qt::Key_Shift); - m_shiftButtonInput->setSourceDevice(m_keyboardDevice); - m_shiftButtonAction->addInput(m_shiftButtonInput); - - //// Axes - - // Mouse X - m_mouseRxInput->setAxis(Qt3DInput::QMouseDevice::X); - m_mouseRxInput->setSourceDevice(m_mouseDevice); - m_rxAxis->addInput(m_mouseRxInput); - - // Mouse Y - m_mouseRyInput->setAxis(Qt3DInput::QMouseDevice::Y); - m_mouseRyInput->setSourceDevice(m_mouseDevice); - m_ryAxis->addInput(m_mouseRyInput); - - // Mouse Wheel X - m_mouseTzXInput->setAxis(Qt3DInput::QMouseDevice::WheelX); - m_mouseTzXInput->setSourceDevice(m_mouseDevice); - m_tzAxis->addInput(m_mouseTzXInput); - - // Mouse Wheel Y - m_mouseTzYInput->setAxis(Qt3DInput::QMouseDevice::WheelY); - m_mouseTzYInput->setSourceDevice(m_mouseDevice); - m_tzAxis->addInput(m_mouseTzYInput); - - // Keyboard Pos Tx - m_keyboardTxPosInput->setButtons(QVector<int>() << Qt::Key_Right); - m_keyboardTxPosInput->setScale(1.0f); - m_keyboardTxPosInput->setSourceDevice(m_keyboardDevice); - m_txAxis->addInput(m_keyboardTxPosInput); - - // Keyboard Pos Tz - m_keyboardTzPosInput->setButtons(QVector<int>() << Qt::Key_PageUp); - m_keyboardTzPosInput->setScale(1.0f); - m_keyboardTzPosInput->setSourceDevice(m_keyboardDevice); - m_tzAxis->addInput(m_keyboardTzPosInput); - - // Keyboard Pos Ty - m_keyboardTyPosInput->setButtons(QVector<int>() << Qt::Key_Up); - m_keyboardTyPosInput->setScale(1.0f); - m_keyboardTyPosInput->setSourceDevice(m_keyboardDevice); - m_tyAxis->addInput(m_keyboardTyPosInput); - - // Keyboard Neg Tx - m_keyboardTxNegInput->setButtons(QVector<int>() << Qt::Key_Left); - m_keyboardTxNegInput->setScale(-1.0f); - m_keyboardTxNegInput->setSourceDevice(m_keyboardDevice); - m_txAxis->addInput(m_keyboardTxNegInput); - - // Keyboard Neg Tz - m_keyboardTzNegInput->setButtons(QVector<int>() << Qt::Key_PageDown); - m_keyboardTzNegInput->setScale(-1.0f); - m_keyboardTzNegInput->setSourceDevice(m_keyboardDevice); - m_tzAxis->addInput(m_keyboardTzNegInput); - - // Keyboard Neg Ty - m_keyboardTyNegInput->setButtons(QVector<int>() << Qt::Key_Down); - m_keyboardTyNegInput->setScale(-1.0f); - m_keyboardTyNegInput->setSourceDevice(m_keyboardDevice); - m_tyAxis->addInput(m_keyboardTyNegInput); - - //// Logical Device - - m_logicalDevice->addAction(m_leftMouseButtonAction); - m_logicalDevice->addAction(m_rightMouseButtonAction); - m_logicalDevice->addAction(m_altButtonAction); - m_logicalDevice->addAction(m_shiftButtonAction); - m_logicalDevice->addAxis(m_rxAxis); - m_logicalDevice->addAxis(m_ryAxis); - m_logicalDevice->addAxis(m_txAxis); - m_logicalDevice->addAxis(m_tyAxis); - m_logicalDevice->addAxis(m_tzAxis); - - Q_Q(QOrbitCameraController); - //// FrameAction - - QObject::connect(m_frameAction, SIGNAL(triggered(float)), - q, SLOT(_q_onTriggered(float))); - - // Disable the logical device when the entity is disabled - QObject::connect(q, &Qt3DCore::QEntity::enabledChanged, - m_logicalDevice, &Qt3DInput::QLogicalDevice::setEnabled); - - q->addComponent(m_frameAction); - q->addComponent(m_logicalDevice); -} - -float clampInputs(float input1, float input2) -{ - float axisValue = input1 + input2; - return (axisValue < -1) ? -1 : (axisValue > 1) ? 1 : axisValue; -} - -float zoomDistance(QVector3D firstPoint, QVector3D secondPoint) -{ - return (secondPoint - firstPoint).lengthSquared(); -} - -void QOrbitCameraControllerPrivate::_q_onTriggered(float dt) -{ - if (m_camera != nullptr) { - // Mouse input - if (m_leftMouseButtonAction->isActive()) { - if (m_rightMouseButtonAction->isActive()) { - if ( zoomDistance(m_camera->position(), m_camera->viewCenter()) > m_zoomInLimit * m_zoomInLimit) { - // Dolly up to limit - m_camera->translate(QVector3D(0, 0, m_ryAxis->value()), m_camera->DontTranslateViewCenter); - } else { - m_camera->translate(QVector3D(0, 0, -0.5), m_camera->DontTranslateViewCenter); - } - } else { - // Translate - m_camera->translate(QVector3D(clampInputs(m_rxAxis->value(), m_txAxis->value()) * m_linearSpeed, - clampInputs(m_ryAxis->value(), m_tyAxis->value()) * m_linearSpeed, - 0) * dt); - } - return; - } - else if (m_rightMouseButtonAction->isActive()) { - // Orbit - m_camera->panAboutViewCenter((m_rxAxis->value() * m_lookSpeed) * dt, m_cameraUp); - m_camera->tiltAboutViewCenter((m_ryAxis->value() * m_lookSpeed) * dt); - } - // Keyboard Input - if (m_altButtonAction->isActive()) { - // Orbit - m_camera->panAboutViewCenter((m_txAxis->value() * m_lookSpeed) * dt, m_cameraUp); - m_camera->tiltAboutViewCenter((m_tyAxis->value() * m_lookSpeed) * dt); - } else if (m_shiftButtonAction->isActive()) { - if (zoomDistance(m_camera->position(), m_camera->viewCenter()) > m_zoomInLimit * m_zoomInLimit) { - // Dolly - m_camera->translate(QVector3D(0, 0, m_tyAxis->value()), m_camera->DontTranslateViewCenter); - } else { - m_camera->translate(QVector3D(0, 0, -0.5), m_camera->DontTranslateViewCenter); - } - } else { - // Translate - m_camera->translate(QVector3D(clampInputs(m_leftMouseButtonAction->isActive() ? m_rxAxis->value() : 0, m_txAxis->value()) * m_linearSpeed, - clampInputs(m_leftMouseButtonAction->isActive() ? m_ryAxis->value() : 0, m_tyAxis->value()) * m_linearSpeed, - m_tzAxis->value() * m_linearSpeed) * dt); - } - } -} - QOrbitCameraController::QOrbitCameraController(Qt3DCore::QNode *parent) - : Qt3DCore::QEntity(*new QOrbitCameraControllerPrivate, parent) + : QOrbitCameraController(*new QOrbitCameraControllerPrivate, parent) { - Q_D(QOrbitCameraController); - d->init(); } -QOrbitCameraController::~QOrbitCameraController() +/*! \internal + */ +QOrbitCameraController::QOrbitCameraController(QOrbitCameraControllerPrivate &dd, Qt3DCore::QNode *parent) + : QAbstractCameraController(dd, parent) { } -/*! - \property QOrbitCameraController::camera - - Holds the currently controlled camera. -*/ -Qt3DRender::QCamera *QOrbitCameraController::camera() const -{ - Q_D(const QOrbitCameraController); - return d->m_camera; -} - -/*! - \property QOrbitCameraController::linearSpeed - - Holds the current linear speed of the camera controller. Linear speed determines the - movement speed of the camera. -*/ -float QOrbitCameraController::linearSpeed() const -{ - Q_D(const QOrbitCameraController); - return d->m_linearSpeed; -} - -/*! - \property QOrbitCameraController::lookSpeed - - Holds the current look speed of the camera controller. The look speed determines the turn rate - of the camera pan and tilt. -*/ -float QOrbitCameraController::lookSpeed() const +QOrbitCameraController::~QOrbitCameraController() { - Q_D(const QOrbitCameraController); - return d->m_lookSpeed; } /*! @@ -358,51 +120,77 @@ float QOrbitCameraController::zoomInLimit() const return d->m_zoomInLimit; } -void QOrbitCameraController::setCamera(Qt3DRender::QCamera *camera) +void QOrbitCameraController::setZoomInLimit(float zoomInLimit) { Q_D(QOrbitCameraController); - if (d->m_camera != camera) { - - if (d->m_camera) - d->unregisterDestructionHelper(d->m_camera); - - if (camera && !camera->parent()) - camera->setParent(this); - - d->m_camera = camera; - - // Ensures proper bookkeeping - if (d->m_camera) - d->registerDestructionHelper(d->m_camera, &QOrbitCameraController::setCamera, d->m_camera); - - emit cameraChanged(); + if (d->m_zoomInLimit != zoomInLimit) { + d->m_zoomInLimit = zoomInLimit; + emit zoomInLimitChanged(); } } -void QOrbitCameraController::setLinearSpeed(float linearSpeed) +inline float clampInputs(float input1, float input2) { - Q_D(QOrbitCameraController); - if (d->m_linearSpeed != linearSpeed) { - d->m_linearSpeed = linearSpeed; - emit linearSpeedChanged(); - } + float axisValue = input1 + input2; + return (axisValue < -1) ? -1 : (axisValue > 1) ? 1 : axisValue; } -void QOrbitCameraController::setLookSpeed(float lookSpeed) +inline float zoomDistance(QVector3D firstPoint, QVector3D secondPoint) { - Q_D(QOrbitCameraController); - if (d->m_lookSpeed != lookSpeed) { - d->m_lookSpeed = lookSpeed; - emit lookSpeedChanged(); - } + return (secondPoint - firstPoint).lengthSquared(); } -void QOrbitCameraController::setZoomInLimit(float zoomInLimit) +void QOrbitCameraController::moveCamera(const QAbstractCameraController::InputState &state, float dt) { Q_D(QOrbitCameraController); - if (d->m_zoomInLimit != zoomInLimit) { - d->m_zoomInLimit = zoomInLimit; - emit zoomInLimitChanged(); + + Qt3DRender::QCamera *theCamera = camera(); + + if (theCamera == nullptr) + return; + + const QVector3D upVector(0.0f, 1.0f, 0.0f); + + // Mouse input + if (state.leftMouseButtonActive) { + if (state.rightMouseButtonActive) { + if ( zoomDistance(camera()->position(), theCamera->viewCenter()) > d->m_zoomInLimit * d->m_zoomInLimit) { + // Dolly up to limit + theCamera->translate(QVector3D(0, 0, state.ryAxisValue), theCamera->DontTranslateViewCenter); + } else { + theCamera->translate(QVector3D(0, 0, -0.5), theCamera->DontTranslateViewCenter); + } + } else { + // Translate + theCamera->translate(QVector3D(clampInputs(state.rxAxisValue, state.txAxisValue) * linearSpeed(), + clampInputs(state.ryAxisValue, state.tyAxisValue) * linearSpeed(), + 0) * dt); + } + return; + } + else if (state.rightMouseButtonActive) { + // Orbit + theCamera->panAboutViewCenter((state.rxAxisValue * lookSpeed()) * dt, upVector); + theCamera->tiltAboutViewCenter((state.ryAxisValue * lookSpeed()) * dt); + } + + // Keyboard Input + if (state.altKeyActive) { + // Orbit + theCamera->panAboutViewCenter((state.txAxisValue * lookSpeed()) * dt, upVector); + theCamera->tiltAboutViewCenter((state.tyAxisValue * lookSpeed()) * dt); + } 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); + } else { + theCamera->translate(QVector3D(0, 0, -0.5), theCamera->DontTranslateViewCenter); + } + } else { + // Translate + theCamera->translate(QVector3D(clampInputs(state.leftMouseButtonActive ? state.rxAxisValue : 0, state.txAxisValue) * linearSpeed(), + clampInputs(state.leftMouseButtonActive ? state.ryAxisValue : 0, state.tyAxisValue) * linearSpeed(), + state.tzAxisValue * linearSpeed()) * dt); } } diff --git a/src/extras/defaults/qorbitcameracontroller.h b/src/extras/defaults/qorbitcameracontroller.h index 7cb8b3eb7..684bfddf1 100644 --- a/src/extras/defaults/qorbitcameracontroller.h +++ b/src/extras/defaults/qorbitcameracontroller.h @@ -37,50 +37,38 @@ #ifndef QT3DEXTRAS_QORBITCAMERACONTROLLER_H #define QT3DEXTRAS_QORBITCAMERACONTROLLER_H -#include <Qt3DCore/QEntity> -#include <Qt3DExtras/qt3dextras_global.h> +#include <Qt3DExtras/qabstractcameracontroller.h> QT_BEGIN_NAMESPACE -namespace Qt3DRender { -class QCamera; -} - namespace Qt3DExtras { class QOrbitCameraControllerPrivate; -class QT3DEXTRASSHARED_EXPORT QOrbitCameraController : public Qt3DCore::QEntity +class QT3DEXTRASSHARED_EXPORT QOrbitCameraController : public QAbstractCameraController { Q_OBJECT - Q_PROPERTY(Qt3DRender::QCamera *camera READ camera WRITE setCamera NOTIFY cameraChanged) - Q_PROPERTY(float linearSpeed READ linearSpeed WRITE setLinearSpeed NOTIFY linearSpeedChanged) - Q_PROPERTY(float lookSpeed READ lookSpeed WRITE setLookSpeed NOTIFY lookSpeedChanged) Q_PROPERTY(float zoomInLimit READ zoomInLimit WRITE setZoomInLimit NOTIFY zoomInLimitChanged) public: explicit QOrbitCameraController(Qt3DCore::QNode *parent = nullptr); ~QOrbitCameraController(); - Qt3DRender::QCamera *camera() const; - float linearSpeed() const; - float lookSpeed() const; float zoomInLimit() const; - void setCamera(Qt3DRender::QCamera *camera); - void setLinearSpeed(float linearSpeed); - void setLookSpeed(float lookSpeed); void setZoomInLimit(float zoomInLimit); Q_SIGNALS: - void cameraChanged(); - void linearSpeedChanged(); - void lookSpeedChanged(); void zoomInLimitChanged(); +protected: + QOrbitCameraController(QOrbitCameraControllerPrivate &dd, Qt3DCore::QNode *parent = nullptr); + +private: + void moveCamera(const QAbstractCameraController::InputState &state, float dt) override; + private: Q_DECLARE_PRIVATE(QOrbitCameraController) - Q_PRIVATE_SLOT(d_func(), void _q_onTriggered(float)) }; } // Qt3DExtras diff --git a/src/extras/defaults/qorbitcameracontroller_p.h b/src/extras/defaults/qorbitcameracontroller_p.h index 8105d4375..1e4e3d4d2 100644 --- a/src/extras/defaults/qorbitcameracontroller_p.h +++ b/src/extras/defaults/qorbitcameracontroller_p.h @@ -48,88 +48,25 @@ // We mean it. // -#include <Qt3DExtras/qorbitcameracontroller.h> -#include <QtGui/QVector3D> - -#include <Qt3DCore/private/qentity_p.h> +#include <Qt3DExtras/private/qabstractcameracontroller_p.h> QT_BEGIN_NAMESPACE -namespace Qt3DRender { -class QCamera; -} - -namespace Qt3DLogic { -class QFrameAction; -} - -namespace Qt3DInput { - -class QKeyboardDevice; -class QMouseDevice; -class QLogicalDevice; -class QAction; -class QActionInput; -class QAxis; -class QAnalogAxisInput; -class QButtonAxisInput; -class QAxisActionHandler; - -} - namespace Qt3DExtras { -class QOrbitCameraControllerPrivate : public Qt3DCore::QEntityPrivate +class QOrbitCameraControllerPrivate : public QAbstractCameraControllerPrivate { + Q_DECLARE_PUBLIC(QOrbitCameraController) + public: QOrbitCameraControllerPrivate(); void init(); - Qt3DRender::QCamera *m_camera; - - Qt3DInput::QAction *m_leftMouseButtonAction; - Qt3DInput::QAction *m_rightMouseButtonAction; - Qt3DInput::QAction *m_altButtonAction; - Qt3DInput::QAction *m_shiftButtonAction; - - Qt3DInput::QAxis *m_rxAxis; - Qt3DInput::QAxis *m_ryAxis; - Qt3DInput::QAxis *m_txAxis; - Qt3DInput::QAxis *m_tyAxis; - Qt3DInput::QAxis *m_tzAxis; - - Qt3DInput::QActionInput *m_leftMouseButtonInput; - Qt3DInput::QActionInput *m_rightMouseButtonInput; - Qt3DInput::QActionInput *m_altButtonInput; - Qt3DInput::QActionInput *m_shiftButtonInput; - - Qt3DInput::QAnalogAxisInput *m_mouseRxInput; - Qt3DInput::QAnalogAxisInput *m_mouseRyInput; - Qt3DInput::QAnalogAxisInput *m_mouseTzXInput; - Qt3DInput::QAnalogAxisInput *m_mouseTzYInput; - Qt3DInput::QButtonAxisInput *m_keyboardTxPosInput; - Qt3DInput::QButtonAxisInput *m_keyboardTyPosInput; - Qt3DInput::QButtonAxisInput *m_keyboardTzPosInput; - Qt3DInput::QButtonAxisInput *m_keyboardTxNegInput; - Qt3DInput::QButtonAxisInput *m_keyboardTyNegInput; - Qt3DInput::QButtonAxisInput *m_keyboardTzNegInput; - - Qt3DInput::QKeyboardDevice *m_keyboardDevice; - Qt3DInput::QMouseDevice *m_mouseDevice; - - Qt3DInput::QLogicalDevice *m_logicalDevice; - - Qt3DLogic::QFrameAction *m_frameAction; - - float m_linearSpeed; - float m_lookSpeed; float m_zoomInLimit; - QVector3D m_cameraUp; - void _q_onTriggered(float); - - Q_DECLARE_PUBLIC(QOrbitCameraController) +private: + QOrbitCameraController *q_ptr; }; } // namespace Qt3DExtras diff --git a/src/extras/defaults/qphongalphamaterial.cpp b/src/extras/defaults/qphongalphamaterial.cpp index d7f054d71..fd8c52525 100644 --- a/src/extras/defaults/qphongalphamaterial.cpp +++ b/src/extras/defaults/qphongalphamaterial.cpp @@ -65,10 +65,9 @@ QPhongAlphaMaterialPrivate::QPhongAlphaMaterialPrivate() : QMaterialPrivate() , m_phongEffect(new QEffect()) , m_ambientParameter(new QParameter(QStringLiteral("ka"), QColor::fromRgbF(0.05f, 0.05f, 0.05f, 1.0f))) - , m_diffuseParameter(new QParameter(QStringLiteral("kd"), QColor::fromRgbF(0.7f, 0.7f, 0.7f, 1.0f))) + , m_diffuseParameter(new QParameter(QStringLiteral("kd"), QColor::fromRgbF(0.7f, 0.7f, 0.7f, 0.5f))) , m_specularParameter(new QParameter(QStringLiteral("ks"), QColor::fromRgbF(0.01f, 0.01f, 0.01f, 1.0f))) , m_shininessParameter(new QParameter(QStringLiteral("shininess"), 150.0f)) - , m_alphaParameter(new QParameter(QStringLiteral("alpha"), 0.5f)) , m_phongAlphaGL3Technique(new QTechnique()) , m_phongAlphaGL2Technique(new QTechnique()) , m_phongAlphaES2Technique(new QTechnique()) @@ -95,13 +94,11 @@ void QPhongAlphaMaterialPrivate::init() this, &QPhongAlphaMaterialPrivate::handleSpecularChanged); connect(m_shininessParameter, &Qt3DRender::QParameter::valueChanged, this, &QPhongAlphaMaterialPrivate::handleShininessChanged); - connect(m_alphaParameter, &Qt3DRender::QParameter::valueChanged, - this, &QPhongAlphaMaterialPrivate::handleAlphaChanged); - m_phongAlphaGL3Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/phong.vert")))); - m_phongAlphaGL3Shader->setFragmentShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/phongalpha.frag")))); - m_phongAlphaGL2ES2Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/phong.vert")))); - m_phongAlphaGL2ES2Shader->setFragmentShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/phongalpha.frag")))); + 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_phongAlphaGL2ES2Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/default.vert")))); + m_phongAlphaGL2ES2Shader->setFragmentShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/phong.frag")))); m_phongAlphaGL3Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL); m_phongAlphaGL3Technique->graphicsApiFilter()->setMajorVersion(3); @@ -159,7 +156,6 @@ void QPhongAlphaMaterialPrivate::init() m_phongEffect->addParameter(m_diffuseParameter); m_phongEffect->addParameter(m_specularParameter); m_phongEffect->addParameter(m_shininessParameter); - m_phongEffect->addParameter(m_alphaParameter); q->setEffect(m_phongEffect); } @@ -174,6 +170,7 @@ void QPhongAlphaMaterialPrivate::handleDiffuseChanged(const QVariant &var) { Q_Q(QPhongAlphaMaterial); emit q->diffuseChanged(var.value<QColor>()); + emit q->alphaChanged(var.value<QColor>().alphaF()); } void QPhongAlphaMaterialPrivate::handleSpecularChanged(const QVariant &var) @@ -188,12 +185,6 @@ void QPhongAlphaMaterialPrivate::handleShininessChanged(const QVariant &var) emit q->shininessChanged(var.toFloat()); } -void QPhongAlphaMaterialPrivate::handleAlphaChanged(const QVariant &var) -{ - Q_Q(QPhongAlphaMaterial); - emit q->alphaChanged(var.toFloat()); -} - /*! \class Qt3DExtras::QPhongAlphaMaterial @@ -301,7 +292,7 @@ float QPhongAlphaMaterial::shininess() const float QPhongAlphaMaterial::alpha() const { Q_D(const QPhongAlphaMaterial); - return d->m_alphaParameter->value().toFloat(); + return d->m_diffuseParameter->value().value<QColor>().alphaF(); } /*! @@ -378,7 +369,10 @@ void QPhongAlphaMaterial::setAmbient(const QColor &ambient) void QPhongAlphaMaterial::setDiffuse(const QColor &diffuse) { Q_D(QPhongAlphaMaterial); - d->m_diffuseParameter->setValue(diffuse); + QColor currentDiffuse = d->m_diffuseParameter->value().value<QColor>(); + QColor newDiffuse = diffuse; + newDiffuse.setAlphaF(currentDiffuse.alphaF()); + d->m_diffuseParameter->setValue(newDiffuse); } void QPhongAlphaMaterial::setSpecular(const QColor &specular) @@ -396,7 +390,9 @@ void QPhongAlphaMaterial::setShininess(float shininess) void QPhongAlphaMaterial::setAlpha(float alpha) { Q_D(QPhongAlphaMaterial); - d->m_alphaParameter->setValue(alpha); + QColor diffuse = d->m_diffuseParameter->value().value<QColor>(); + diffuse.setAlphaF(alpha); + d->m_diffuseParameter->setValue(diffuse); } void QPhongAlphaMaterial::setSourceRgbArg(QBlendEquationArguments::Blending sourceRgbArg) diff --git a/src/extras/defaults/qphongalphamaterial_p.h b/src/extras/defaults/qphongalphamaterial_p.h index 623eca0ea..84e2eead3 100644 --- a/src/extras/defaults/qphongalphamaterial_p.h +++ b/src/extras/defaults/qphongalphamaterial_p.h @@ -84,14 +84,12 @@ public: void handleDiffuseChanged(const QVariant &var); void handleSpecularChanged(const QVariant &var); void handleShininessChanged(const QVariant &var); - void handleAlphaChanged(const QVariant &var); Qt3DRender::QEffect *m_phongEffect; Qt3DRender::QParameter *m_ambientParameter; Qt3DRender::QParameter *m_diffuseParameter; Qt3DRender::QParameter *m_specularParameter; Qt3DRender::QParameter *m_shininessParameter; - Qt3DRender::QParameter *m_alphaParameter; Qt3DRender::QTechnique *m_phongAlphaGL3Technique; Qt3DRender::QTechnique *m_phongAlphaGL2Technique; Qt3DRender::QTechnique *m_phongAlphaES2Technique; diff --git a/src/extras/defaults/qphongmaterial.cpp b/src/extras/defaults/qphongmaterial.cpp index 449eb7351..25dbf3c85 100644 --- a/src/extras/defaults/qphongmaterial.cpp +++ b/src/extras/defaults/qphongmaterial.cpp @@ -89,10 +89,9 @@ void QPhongMaterialPrivate::init() connect(m_shininessParameter, &Qt3DRender::QParameter::valueChanged, this, &QPhongMaterialPrivate::handleShininessChanged); - - m_phongGL3Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/phong.vert")))); + 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_phongGL2ES2Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/phong.vert")))); + 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_phongGL3Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL); diff --git a/src/extras/extras.qrc b/src/extras/extras.qrc index ce959af93..f3619fdb7 100644 --- a/src/extras/extras.qrc +++ b/src/extras/extras.qrc @@ -4,26 +4,24 @@ <file>shaders/gl3/light.inc.frag</file> <file>shaders/es2/light.inc.frag</file> <file>shaders/es2/light.inc.frag100</file> + <file>shaders/gl3/phong.inc.frag</file> + <file>shaders/es2/phong.inc.frag</file> + <file>shaders/es2/phong.inc.frag100</file> <file>shaders/gl3/metalrough.inc.frag</file> <file>shaders/gl3/coordinatesystems.inc</file> - <file>shaders/gl3/phong.vert</file> + <file>shaders/es2/coordinatesystems.inc</file> <file>shaders/gl3/phong.frag</file> - <file>shaders/es2/phong.vert</file> <file>shaders/es2/phong.frag</file> <file>shaders/gl3/normaldiffusespecularmap.frag</file> - <file>shaders/gl3/diffusemap.vert</file> <file>shaders/gl3/diffusemap.frag</file> <file>shaders/es2/normaldiffusespecularmap.frag</file> - <file>shaders/es2/diffusemap.vert</file> <file>shaders/es2/diffusemap.frag</file> - <file>shaders/es2/normaldiffusemap.vert</file> <file>shaders/es2/normaldiffusemap.frag</file> - <file>shaders/es2/normaldiffusemapalpha.frag</file> <file>shaders/gl3/normaldiffusemap.frag</file> - <file>shaders/gl3/normaldiffusemap.vert</file> - <file>shaders/gl3/normaldiffusemapalpha.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> <file>shaders/gl3/pervertexcolor.vert</file> <file>shaders/es2/pervertexcolor.frag</file> @@ -36,13 +34,10 @@ <file>shaders/gl3/gooch.frag</file> <file>shaders/es2/gooch.frag</file> <file>shaders/es2/gooch.vert</file> - <file>shaders/gl3/phongalpha.frag</file> - <file>shaders/es2/phongalpha.frag</file> <file>shaders/gl3/unlittexture.vert</file> <file>shaders/gl3/unlittexture.frag</file> <file>shaders/es2/unlittexture.frag</file> <file>shaders/es2/unlittexture.vert</file> - <file>shaders/gl3/metalrough.vert</file> <file>shaders/gl3/distancefieldtext.vert</file> <file>shaders/gl3/distancefieldtext.frag</file> <file>shaders/es2/distancefieldtext.frag</file> diff --git a/src/extras/geometries/qconegeometry.cpp b/src/extras/geometries/qconegeometry.cpp index d1a6917f5..a80e2a78a 100644 --- a/src/extras/geometries/qconegeometry.cpp +++ b/src/extras/geometries/qconegeometry.cpp @@ -368,8 +368,8 @@ void QConeGeometryPrivate::init() m_normalAttribute = new QAttribute(q); m_texCoordAttribute = new QAttribute(q); m_indexAttribute = new QAttribute(q); - m_vertexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, q); - m_indexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::IndexBuffer, q); + m_vertexBuffer = new Qt3DRender::QBuffer(q); + m_indexBuffer = new Qt3DRender::QBuffer(q); // vec3 pos, vec2 tex, vec3 normal const quint32 elementSize = 3 + 2 + 3; diff --git a/src/extras/geometries/qcuboidgeometry.cpp b/src/extras/geometries/qcuboidgeometry.cpp index a8899989c..9e6747c1e 100644 --- a/src/extras/geometries/qcuboidgeometry.cpp +++ b/src/extras/geometries/qcuboidgeometry.cpp @@ -497,8 +497,8 @@ void QCuboidGeometryPrivate::init() m_texCoordAttribute = new Qt3DRender::QAttribute(q); m_tangentAttribute = new Qt3DRender::QAttribute(q); m_indexAttribute = new Qt3DRender::QAttribute(q); - m_vertexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, q); - m_indexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::IndexBuffer, q); + m_vertexBuffer = new Qt3DRender::QBuffer(q); + m_indexBuffer = new Qt3DRender::QBuffer(q); // vec3 pos vec2 tex vec3 normal vec4 tangent const quint32 stride = (3 + 2 + 3 + 4) * sizeof(float); diff --git a/src/extras/geometries/qcylindergeometry.cpp b/src/extras/geometries/qcylindergeometry.cpp index a6eb01d41..c86b76d24 100644 --- a/src/extras/geometries/qcylindergeometry.cpp +++ b/src/extras/geometries/qcylindergeometry.cpp @@ -299,8 +299,8 @@ void QCylinderGeometryPrivate::init() m_normalAttribute = new QAttribute(q); m_texCoordAttribute = new QAttribute(q); m_indexAttribute = new QAttribute(q); - m_vertexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, q); - m_indexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::IndexBuffer, q); + m_vertexBuffer = new Qt3DRender::QBuffer(q); + m_indexBuffer = new Qt3DRender::QBuffer(q); // vec3 pos, vec2 tex, vec3 normal const quint32 elementSize = 3 + 2 + 3; diff --git a/src/extras/geometries/qplanegeometry.cpp b/src/extras/geometries/qplanegeometry.cpp index c6318e199..225726342 100644 --- a/src/extras/geometries/qplanegeometry.cpp +++ b/src/extras/geometries/qplanegeometry.cpp @@ -509,8 +509,8 @@ void QPlaneGeometryPrivate::init() m_texCoordAttribute = new QAttribute(q); m_tangentAttribute = new QAttribute(q); m_indexAttribute = new QAttribute(q); - m_vertexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, q); - m_indexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::IndexBuffer, q); + m_vertexBuffer = new Qt3DRender::QBuffer(q); + m_indexBuffer = new Qt3DRender::QBuffer(q); const int nVerts = m_meshResolution.width() * m_meshResolution.height(); const int stride = (3 + 2 + 3 + 4) * sizeof(float); diff --git a/src/extras/geometries/qspheregeometry.cpp b/src/extras/geometries/qspheregeometry.cpp index 92844335c..1a3b50553 100644 --- a/src/extras/geometries/qspheregeometry.cpp +++ b/src/extras/geometries/qspheregeometry.cpp @@ -254,8 +254,8 @@ void QSphereGeometryPrivate::init() m_texCoordAttribute = new QAttribute(q); m_tangentAttribute = new QAttribute(q); m_indexAttribute = new QAttribute(q); - m_vertexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, q); - m_indexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::IndexBuffer, q); + m_vertexBuffer = new Qt3DRender::QBuffer(q); + m_indexBuffer = new Qt3DRender::QBuffer(q); // vec3 pos, vec2 tex, vec3 normal, vec4 tangent const quint32 elementSize = 3 + 2 + 3 + 4; diff --git a/src/extras/geometries/qtorusgeometry.cpp b/src/extras/geometries/qtorusgeometry.cpp index ef14ee50d..726b81c62 100644 --- a/src/extras/geometries/qtorusgeometry.cpp +++ b/src/extras/geometries/qtorusgeometry.cpp @@ -243,8 +243,8 @@ void QTorusGeometryPrivate::init() m_texCoordAttribute = new QAttribute(q); m_tangentAttribute = new QAttribute(q); m_indexAttribute = new QAttribute(q); - m_vertexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, q); - m_indexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::IndexBuffer, q); + m_vertexBuffer = new Qt3DRender::QBuffer(q); + m_indexBuffer = new Qt3DRender::QBuffer(q); // vec3 pos, vec2 tex, vec3 normal, vec4 tangent const quint32 elementSize = 3 + 2 + 3 + 4; const quint32 stride = elementSize * sizeof(float); diff --git a/src/extras/shaders/es2/coordinatesystems.inc b/src/extras/shaders/es2/coordinatesystems.inc new file mode 100644 index 000000000..5f6ee40f5 --- /dev/null +++ b/src/extras/shaders/es2/coordinatesystems.inc @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#define FP highp + +FP mat3 transpose(const in FP mat3 inputMatrix) +{ + FP vec3 i0 = inputMatrix[0]; + FP vec3 i1 = inputMatrix[1]; + FP vec3 i2 = inputMatrix[2]; + + FP mat3 outputMatrix = mat3( + vec3(i0.x, i1.x, i2.x), + vec3(i0.y, i1.y, i2.y), + vec3(i0.z, i1.z, i2.z) + ); + + return outputMatrix; +} + +FP mat3 calcWorldSpaceToTangentSpaceMatrix(const in FP vec3 wNormal, const in FP vec4 wTangent) +{ + // Make the tangent truly orthogonal to the normal by using Gram-Schmidt. + // This allows to build the tangentMatrix below by simply transposing the + // tangent -> eyespace matrix (which would now be orthogonal) + FP vec3 wFixedTangent = normalize(wTangent.xyz - dot(wTangent.xyz, wNormal) * wNormal); + + // Calculate binormal vector. No "real" need to renormalize it, + // as built by crossing two normal vectors. + // To orient the binormal correctly, use the fourth coordinate of the tangent, + // which is +1 for a right hand system, and -1 for a left hand system. + FP vec3 wBinormal = cross(wNormal, wFixedTangent.xyz) * wTangent.w; + + // Construct matrix to transform from world space to tangent space + // This is the transpose of the tangentToWorld transformation matrix + FP mat3 tangentToWorldMatrix = mat3(wFixedTangent, wBinormal, wNormal); + FP mat3 worldToTangentMatrix = transpose(tangentToWorldMatrix); + return worldToTangentMatrix; +} + diff --git a/src/extras/shaders/es2/default.vert b/src/extras/shaders/es2/default.vert new file mode 100644 index 000000000..810f658bc --- /dev/null +++ b/src/extras/shaders/es2/default.vert @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +attribute vec3 vertexPosition; +attribute vec3 vertexNormal; +attribute vec4 vertexTangent; +attribute vec2 vertexTexCoord; + +varying vec3 worldPosition; +varying vec3 worldNormal; +varying vec4 worldTangent; +varying vec2 texCoord; + +uniform mat4 modelMatrix; +uniform mat3 modelNormalMatrix; +uniform mat4 modelViewProjection; + +uniform float texCoordScale; + +void main() +{ + // Pass through texture coordinates + texCoord = vertexTexCoord * texCoordScale; + + // Transform position, normal, and tangent to world coords + worldPosition = vec3(modelMatrix * vec4(vertexPosition, 1.0)); + worldNormal = normalize(modelNormalMatrix * vertexNormal); + worldTangent.xyz = normalize(vec3(modelMatrix * vec4(vertexTangent.xyz, 0.0))); + worldTangent.w = vertexTangent.w; + + // Calculate vertex position in clip coordinates + gl_Position = modelViewProjection * vec4(vertexPosition, 1.0); +} diff --git a/src/extras/shaders/es2/diffusemap.frag b/src/extras/shaders/es2/diffusemap.frag index 7d06d8e2c..6ac9bd5a3 100644 --- a/src/extras/shaders/es2/diffusemap.frag +++ b/src/extras/shaders/es2/diffusemap.frag @@ -1,7 +1,7 @@ #define FP highp -uniform FP vec3 ka; // Ambient reflectivity -uniform FP vec3 ks; // Specular reflectivity +uniform FP vec4 ka; // Ambient reflectivity +uniform FP vec4 ks; // Specular reflectivity uniform FP float shininess; // Specular shininess factor uniform FP vec3 eyePosition; @@ -12,14 +12,11 @@ varying FP vec3 worldPosition; varying FP vec3 worldNormal; varying FP vec2 texCoord; -#pragma include light.inc.frag +#pragma include phong.inc.frag void main() { - FP vec3 diffuseTextureColor = texture2D( diffuseTexture, texCoord ).rgb; - - FP vec3 diffuseColor, specularColor; - adsModel(worldPosition, worldNormal, eyePosition, shininess, diffuseColor, specularColor); - - gl_FragColor = vec4( diffuseTextureColor * ( ka + diffuseColor ) + ks * specularColor, 1.0 ); + 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/diffusemap.vert b/src/extras/shaders/es2/diffusemap.vert deleted file mode 100644 index 13798279e..000000000 --- a/src/extras/shaders/es2/diffusemap.vert +++ /dev/null @@ -1,22 +0,0 @@ -attribute vec3 vertexPosition; -attribute vec3 vertexNormal; -attribute vec2 vertexTexCoord; - -varying vec3 worldPosition; -varying vec3 worldNormal; -varying vec2 texCoord; - -uniform mat4 modelMatrix; -uniform mat3 modelNormalMatrix; -uniform mat4 mvp; - -uniform float texCoordScale; - -void main() -{ - texCoord = vertexTexCoord * texCoordScale; - worldNormal = normalize( modelNormalMatrix * vertexNormal ); - worldPosition = vec3( modelMatrix * vec4( vertexPosition, 1.0 ) ); - - gl_Position = mvp * vec4( vertexPosition, 1.0 ); -} diff --git a/src/extras/shaders/es2/diffusespecularmap.frag b/src/extras/shaders/es2/diffusespecularmap.frag index 4d776772c..99183aaf4 100644 --- a/src/extras/shaders/es2/diffusespecularmap.frag +++ b/src/extras/shaders/es2/diffusespecularmap.frag @@ -1,7 +1,7 @@ #define FP highp // TODO: Replace with a struct -uniform FP vec3 ka; // Ambient reflectivity +uniform FP vec4 ka; // Ambient reflectivity uniform FP float shininess; // Specular shininess factor uniform FP vec3 eyePosition; @@ -13,15 +13,12 @@ varying FP vec3 worldPosition; varying FP vec3 worldNormal; varying FP vec2 texCoord; -#pragma include light.inc.frag +#pragma include phong.inc.frag void main() { - FP vec3 diffuseTextureColor = texture2D( diffuseTexture, texCoord ).rgb; - FP vec3 specularTextureColor = texture2D( specularTexture, texCoord ).rgb; - - FP vec3 diffuseColor, specularColor; - adsModel(worldPosition, worldNormal, eyePosition, shininess, diffuseColor, specularColor); - - gl_FragColor = vec4( diffuseTextureColor * ( ka + diffuseColor ) + specularTextureColor * specularColor, 1.0 ); + 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/light.inc.frag b/src/extras/shaders/es2/light.inc.frag index 57a30036f..167ff306e 100644 --- a/src/extras/shaders/es2/light.inc.frag +++ b/src/extras/shaders/es2/light.inc.frag @@ -1,3 +1,5 @@ +#define FP highp + const int MAX_LIGHTS = 8; const int TYPE_POINT = 0; const int TYPE_DIRECTIONAL = 1; @@ -13,186 +15,3 @@ struct Light { }; uniform Light lights[MAX_LIGHTS]; uniform int lightCount; - -void adsModelNormalMapped(const in FP vec3 vpos, const in FP vec3 vnormal, const in FP vec3 eye, const in FP float shininess, - const in FP mat3 tangentMatrix, - out FP vec3 diffuseColor, out FP vec3 specularColor) -{ - diffuseColor = vec3(0.0); - specularColor = vec3(0.0); - - FP vec3 snormal = normalize( vec3( tangentMatrix[0][2], tangentMatrix[1][2], tangentMatrix[2][2] ) ); - - FP vec3 n = normalize( vnormal ); - - FP vec3 s, ts; - Light light; - for (int i = 0; i < MAX_LIGHTS; ++i) { - if (i >= lightCount) // Make brcm happy with the for loop - break; - if (i == 0) - light = lights[0]; - else if (i == 1) - light = lights[1]; - else if (i == 2) - light = lights[2]; - else if (i == 3) - light = lights[3]; - else if (i == 4) - light = lights[4]; - else if (i == 5) - light = lights[5]; - else if (i == 6) - light = lights[6]; - else if (i == 7) - light = lights[7]; - - FP float att = 1.0; - if ( light.type != TYPE_DIRECTIONAL ) { - s = light.position - vpos; - if ( dot(snormal, s) < 0.0 ) - att = 0.0; - else { - ts = normalize( tangentMatrix * s ); - if (length( light.attenuation ) != 0.0) { - FP float dist = length(s); - att = 1.0 / (light.attenuation.x + light.attenuation.y * dist + light.attenuation.z * dist * dist); - } - s = normalize( s ); - if ( light.type == TYPE_SPOT ) { - if ( degrees(acos(dot(-s, normalize(light.direction))) ) > light.cutOffAngle) - att = 0.0; - } - } - } else { - if ( dot(snormal, -light.direction) > 0.0 ) - s = normalize( tangentMatrix * -light.direction ); - else - att = 0.0; - } - - FP float diffuse = max( dot( ts, n ), 0.0 ); - - FP float specular = 0.0; - if (diffuse > 0.0 && shininess > 0.0 && att > 0.0) { - FP vec3 r = reflect( -ts, n ); - FP vec3 v = normalize( tangentMatrix * ( eye - vpos ) ); - FP float normFactor = ( shininess + 2.0 ) / 2.0; - specular = normFactor * pow( max( dot( r, v ), 0.0 ), shininess ); - } - - diffuseColor += att * light.intensity * diffuse * light.color; - specularColor += att * light.intensity * specular * light.color; - } -} - -void adsModel(const in FP vec3 vpos, const in FP vec3 vnormal, const in FP vec3 eye, const in FP float shininess, - out FP vec3 diffuseColor, out FP vec3 specularColor) -{ - diffuseColor = vec3(0.0); - specularColor = vec3(0.0); - - FP vec3 n = normalize( vnormal ); - - FP vec3 s; - Light light; - for (int i = 0; i < MAX_LIGHTS; ++i) { - if (i >= lightCount) // Make brcm happy with the for loop - break; - if (i == 0) - light = lights[0]; - else if (i == 1) - light = lights[1]; - else if (i == 2) - light = lights[2]; - else if (i == 3) - light = lights[3]; - else if (i == 4) - light = lights[4]; - else if (i == 5) - light = lights[5]; - else if (i == 6) - light = lights[6]; - else if (i == 7) - light = lights[7]; - - FP float att = 1.0; - if ( light.type != TYPE_DIRECTIONAL ) { - s = light.position - vpos; - if (length( light.attenuation ) != 0.0) { - FP float dist = length(s); - att = 1.0 / (light.attenuation.x + light.attenuation.y * dist + light.attenuation.z * dist * dist); - } - s = normalize( s ); - if ( light.type == TYPE_SPOT ) { - if ( degrees(acos(dot(-s, normalize(light.direction))) ) > light.cutOffAngle) - att = 0.0; - } - } else { - s = normalize( -light.direction ); - } - - FP float diffuse = max( dot( s, n ), 0.0 ); - - FP float specular = 0.0; - if (diffuse > 0.0 && shininess > 0.0 && att > 0.0) { - FP vec3 r = reflect( -s, n ); - FP vec3 v = normalize( eye - vpos ); - FP float normFactor = ( shininess + 2.0 ) / 2.0; - specular = normFactor * pow( max( dot( r, v ), 0.0 ), shininess ); - } - - diffuseColor += att * light.intensity * diffuse * light.color; - specularColor += att * light.intensity * specular * light.color; - } -} - -void adModel(const in FP vec3 vpos, const in FP vec3 vnormal, out FP vec3 diffuseColor) -{ - diffuseColor = vec3(0.0); - - FP vec3 n = normalize( vnormal ); - - FP vec3 s; - Light light; - for (int i = 0; i < MAX_LIGHTS; ++i) { - if (i >= lightCount) // Make brcm happy with the for loop - break; - if (i == 0) - light = lights[0]; - else if (i == 1) - light = lights[1]; - else if (i == 2) - light = lights[2]; - else if (i == 3) - light = lights[3]; - else if (i == 4) - light = lights[4]; - else if (i == 5) - light = lights[5]; - else if (i == 6) - light = lights[6]; - else if (i == 7) - light = lights[7]; - - FP float att = 1.0; - if ( light.type != TYPE_DIRECTIONAL ) { - s = light.position - vpos; - if (length( light.attenuation ) != 0.0) { - FP float dist = length(s); - att = 1.0 / (light.attenuation.x + light.attenuation.y * dist + light.attenuation.z * dist * dist); - } - s = normalize( s ); - if ( light.type == TYPE_SPOT ) { - if ( degrees(acos(dot(-s, normalize(light.direction))) ) > light.cutOffAngle) - att = 0.0; - } - } else { - s = normalize( -light.direction ); - } - - FP float diffuse = max( dot( s, n ), 0.0 ); - - diffuseColor += att * light.intensity * diffuse * light.color; - } -} diff --git a/src/extras/shaders/es2/light.inc.frag100 b/src/extras/shaders/es2/light.inc.frag100 index b4988ad82..8680ee423 100644 --- a/src/extras/shaders/es2/light.inc.frag100 +++ b/src/extras/shaders/es2/light.inc.frag100 @@ -1,3 +1,5 @@ +#define FP highp + const int MAX_LIGHTS = 2; // RPi: cannot use more than two as we run out of uniforms const int TYPE_POINT = 0; const int TYPE_DIRECTIONAL = 1; @@ -13,206 +15,3 @@ struct Light { }; uniform Light lights[MAX_LIGHTS]; uniform int lightCount; - -void adsModelNormalMapped(const in FP vec3 vpos, const in FP vec3 vnormal, const in FP vec3 eye, const in FP float shininess, - const in FP mat3 tangentMatrix, - out FP vec3 diffuseColor, out FP vec3 specularColor) -{ - diffuseColor = vec3(0.0); - specularColor = vec3(0.0); - - FP vec3 n = normalize( vnormal ); - - // 0 - if (lightCount < 1) - return; - FP vec3 s; - FP float att = 1.0; - if ( lights[0].type != TYPE_DIRECTIONAL ) { - s = tangentMatrix * ( lights[0].position - vpos ); - if (length( lights[0].attenuation ) != 0.0) { - FP float dist = length(s); - att = 1.0 / (lights[0].attenuation.x + lights[0].attenuation.y * dist + lights[0].attenuation.z * dist * dist); - } - s = normalize( s ); - if ( lights[0].type == TYPE_SPOT ) { - if ( degrees(acos(dot(-s, normalize(lights[0].direction))) ) > lights[0].cutOffAngle) - att = 0.0; - } - } else { - s = normalize( tangentMatrix * -lights[0].direction ); - } - - FP float diffuse = max( dot( s, n ), 0.0 ); - - FP float specular = 0.0; - if (diffuse > 0.0 && shininess > 0.0 && att > 0.0) { - FP vec3 r = reflect( -s, n ); - FP vec3 v = normalize( tangentMatrix * ( eye - vpos ) ); - FP float normFactor = ( shininess + 2.0 ) / 2.0; - specular = normFactor * pow( max( dot( r, v ), 0.0 ), shininess ); - } - - diffuseColor += att * lights[0].intensity * diffuse * lights[0].color; - specularColor += att * specular; - - // 1 - if (lightCount < 2) - return; - att = 1.0; - if ( lights[1].type != TYPE_DIRECTIONAL ) { - s = tangentMatrix * ( lights[1].position - vpos ); - if (length( lights[1].attenuation ) != 0.0) { - FP float dist = length(s); - att = 1.0 / (lights[1].attenuation.x + lights[1].attenuation.y * dist + lights[1].attenuation.z * dist * dist); - } - s = normalize( s ); - if ( lights[1].type == TYPE_SPOT ) { - if ( degrees(acos(dot(-s, normalize(lights[1].direction))) ) > lights[1].cutOffAngle) - att = 0.0; - } - } else { - s = normalize( tangentMatrix * -lights[1].direction ); - } - - diffuse = max( dot( s, n ), 0.0 ); - - specular = 0.0; - if (diffuse > 0.0 && shininess > 0.0 && att > 0.0) { - FP vec3 r = reflect( -s, n ); - FP vec3 v = normalize( tangentMatrix * ( eye - vpos ) ); - FP float normFactor = ( shininess + 2.0 ) / 2.0; - specular = normFactor * pow( max( dot( r, v ), 0.0 ), shininess ); - } - - diffuseColor += att * lights[1].intensity * diffuse * lights[1].color; - specularColor += att * specular; -} - -void adsModel(const in FP vec3 vpos, const in FP vec3 vnormal, const in FP vec3 eye, const in FP float shininess, - out FP vec3 diffuseColor, out FP vec3 specularColor) -{ - diffuseColor = vec3(0.0); - specularColor = vec3(0.0); - - FP vec3 n = normalize( vnormal ); - - // 0 - if (lightCount < 1) - return; - FP vec3 s; - FP float att = 1.0; - if ( lights[0].type != TYPE_DIRECTIONAL ) { - s = lights[0].position - vpos; - if (length( lights[0].attenuation ) != 0.0) { - FP float dist = length(s); - att = 1.0 / (lights[0].attenuation.x + lights[0].attenuation.y * dist + lights[0].attenuation.z * dist * dist); - } - s = normalize( s ); - if ( lights[0].type == TYPE_SPOT ) { - if ( degrees(acos(dot(-s, normalize(lights[0].direction))) ) > lights[0].cutOffAngle) - att = 0.0; - } - } else { - s = normalize( -lights[0].direction ); - } - - FP float diffuse = max( dot( s, n ), 0.0 ); - - FP float specular = 0.0; - if (diffuse > 0.0 && shininess > 0.0 && att > 0.0) { - FP vec3 r = reflect( -s, n ); - FP vec3 v = normalize( eye - vpos ); - FP float normFactor = ( shininess + 2.0 ) / 2.0; - specular = normFactor * pow( max( dot( r, v ), 0.0 ), shininess ); - } - - diffuseColor += att * lights[0].intensity * diffuse * lights[0].color; - specularColor += att * specular; - - // 1 - if (lightCount < 2) - return; - att = 1.0; - if ( lights[1].type != TYPE_DIRECTIONAL ) { - s = lights[1].position - vpos; - if (length( lights[1].attenuation ) != 0.0) { - FP float dist = length(s); - att = 1.0 / (lights[1].attenuation.x + lights[1].attenuation.y * dist + lights[1].attenuation.z * dist * dist); - } - s = normalize( s ); - if ( lights[1].type == TYPE_SPOT ) { - if ( degrees(acos(dot(-s, normalize(lights[1].direction))) ) > lights[1].cutOffAngle) - att = 0.0; - } - } else { - s = normalize( -lights[1].direction ); - } - - diffuse = max( dot( s, n ), 0.0 ); - - specular = 0.0; - if (diffuse > 0.0 && shininess > 0.0 && att > 0.0) { - FP vec3 r = reflect( -s, n ); - FP vec3 v = normalize( eye - vpos ); - FP float normFactor = ( shininess + 2.0 ) / 2.0; - specular = normFactor * pow( max( dot( r, v ), 0.0 ), shininess ); - } - - diffuseColor += att * lights[1].intensity * diffuse * lights[1].color; - specularColor += att * specular; -} - -void adModel(const in FP vec3 vpos, const in FP vec3 vnormal, out FP vec3 diffuseColor) -{ - diffuseColor = vec3(0.0); - - FP vec3 n = normalize( vnormal ); - - // 0 - if (lightCount < 1) - return; - FP vec3 s; - FP float att = 1.0; - if ( lights[0].type != TYPE_DIRECTIONAL ) { - s = lights[0].position - vpos; - if (length( lights[0].attenuation ) != 0.0) { - FP float dist = length(s); - att = 1.0 / (lights[0].attenuation.x + lights[0].attenuation.y * dist + lights[0].attenuation.z * dist * dist); - } - s = normalize( s ); - if ( lights[0].type == TYPE_SPOT ) { - if ( degrees(acos(dot(-s, normalize(lights[0].direction))) ) > lights[0].cutOffAngle) - att = 0.0; - } - } else { - s = normalize( -lights[0].direction ); - } - - FP float diffuse = max( dot( s, n ), 0.0 ); - - diffuseColor += att * lights[0].intensity * diffuse * lights[0].color; - - // 1 - if (lightCount < 2) - return; - att = 1.0; - if ( lights[1].type != TYPE_DIRECTIONAL ) { - s = lights[1].position - vpos; - if (length( lights[1].attenuation ) != 0.0) { - FP float dist = length(s); - att = 1.0 / (lights[1].attenuation.x + lights[1].attenuation.y * dist + lights[1].attenuation.z * dist * dist); - } - s = normalize( s ); - if ( lights[1].type == TYPE_SPOT ) { - if ( degrees(acos(dot(-s, normalize(lights[1].direction))) ) > lights[1].cutOffAngle) - att = 0.0; - } - } else { - s = normalize( -lights[1].direction ); - } - - diffuse = max( dot( s, n ), 0.0 ); - - diffuseColor += att * lights[1].intensity * diffuse * lights[1].color; -} diff --git a/src/extras/shaders/es2/normaldiffusemap.frag b/src/extras/shaders/es2/normaldiffusemap.frag index c69aa8b81..0bf4c5630 100644 --- a/src/extras/shaders/es2/normaldiffusemap.frag +++ b/src/extras/shaders/es2/normaldiffusemap.frag @@ -1,31 +1,34 @@ #define FP highp varying FP vec3 worldPosition; +varying FP vec3 worldNormal; +varying FP vec4 worldTangent; varying FP vec2 texCoord; -varying FP mat3 tangentMatrix; uniform sampler2D diffuseTexture; uniform sampler2D normalTexture; // TODO: Replace with a struct -uniform FP vec3 ka; // Ambient reflectivity -uniform FP vec3 ks; // Specular reflectivity +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 light.inc.frag +#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 normal = 2.0 * texture2D( normalTexture, texCoord ).rgb - vec3( 1.0 ); + FP vec3 tNormal = 2.0 * texture2D( normalTexture, texCoord ).rgb - vec3( 1.0 ); - // Calculate the lighting model, keeping the specular component separate - FP vec3 diffuseColor, specularColor; - adsModelNormalMapped(worldPosition, normal, eyePosition, shininess, tangentMatrix, diffuseColor, specularColor); + FP mat3 tangentMatrix = calcWorldSpaceToTangentSpaceMatrix(worldNormal, worldTangent); + FP mat3 invertTangentMatrix = transpose(tangentMatrix); - // Combine spec with ambient+diffuse for final fragment color - gl_FragColor = vec4( ka + diffuseTextureColor.rgb * diffuseColor + ks * specularColor, 1.0 ); + 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/normaldiffusemap.vert b/src/extras/shaders/es2/normaldiffusemap.vert deleted file mode 100644 index ecc689f69..000000000 --- a/src/extras/shaders/es2/normaldiffusemap.vert +++ /dev/null @@ -1,38 +0,0 @@ -attribute vec3 vertexPosition; -attribute vec3 vertexNormal; -attribute vec2 vertexTexCoord; -attribute vec4 vertexTangent; - -varying vec3 worldPosition; -varying vec2 texCoord; -varying mat3 tangentMatrix; - -uniform mat4 modelMatrix; -uniform mat3 modelNormalMatrix; -uniform mat4 projectionMatrix; -uniform mat4 mvp; - -uniform float texCoordScale; - -void main() -{ - // Pass through texture coordinates - texCoord = vertexTexCoord * texCoordScale; - - // Transform position, normal, and tangent to world coords - vec3 normal = normalize( modelNormalMatrix * vertexNormal ); - vec3 tangent = normalize( modelNormalMatrix * vertexTangent.xyz ); - worldPosition = vec3( modelMatrix * vec4( vertexPosition, 1.0 ) ); - - // Calculate binormal vector - vec3 binormal = normalize( cross( normal, tangent ) ); - - // Construct matrix to transform from eye coords to tangent space - tangentMatrix = mat3 ( - tangent.x, binormal.x, normal.x, - tangent.y, binormal.y, normal.y, - tangent.z, binormal.z, normal.z ); - - // Calculate vertex position in clip coordinates - gl_Position = mvp * vec4( vertexPosition, 1.0 ); -} diff --git a/src/extras/shaders/es2/normaldiffusemapalpha.frag b/src/extras/shaders/es2/normaldiffusemapalpha.frag deleted file mode 100644 index 98acbf01d..000000000 --- a/src/extras/shaders/es2/normaldiffusemapalpha.frag +++ /dev/null @@ -1,32 +0,0 @@ -#define FP highp - -varying FP vec3 worldPosition; -varying FP vec2 texCoord; -varying FP mat3 tangentMatrix; - -uniform sampler2D diffuseTexture; -uniform sampler2D normalTexture; - -// TODO: Replace with a struct -uniform FP vec3 ka; // Ambient reflectivity -uniform FP vec3 ks; // Specular reflectivity -uniform FP float shininess; // Specular shininess factor - -uniform FP vec3 eyePosition; - -#pragma include light.inc.frag - -void main() -{ - // Sample the textures at the interpolated texCoords - FP vec4 diffuseTextureColor = texture2D( diffuseTexture, texCoord ); - FP vec3 normal = 2.0 * texture2D( normalTexture, texCoord ).rgb - vec3( 1.0 ); - - // Calculate the lighting model, keeping the specular component separate - FP vec3 diffuseColor, specularColor; - adsModelNormalMapped(worldPosition, normal, eyePosition, shininess, tangentMatrix, diffuseColor, specularColor); - - // Combine spec with ambient+diffuse for final fragment color - // Use the alpha from the diffuse texture (for alpha to coverage) - gl_FragColor = vec4( ka + diffuseTextureColor.rgb * diffuseColor + ks * specularColor, diffuseTextureColor.a ); -} diff --git a/src/extras/shaders/es2/normaldiffusespecularmap.frag b/src/extras/shaders/es2/normaldiffusespecularmap.frag index b30c1bd5f..0541c8902 100644 --- a/src/extras/shaders/es2/normaldiffusespecularmap.frag +++ b/src/extras/shaders/es2/normaldiffusespecularmap.frag @@ -1,32 +1,35 @@ #define FP highp varying FP vec3 worldPosition; +varying FP vec3 worldNormal; +varying FP vec4 worldTangent; varying FP vec2 texCoord; -varying FP mat3 tangentMatrix; uniform sampler2D diffuseTexture; uniform sampler2D specularTexture; uniform sampler2D normalTexture; // TODO: Replace with a struct -uniform FP vec3 ka; // Ambient reflectivity +uniform FP vec4 ka; // Ambient reflectivity uniform FP float shininess; // Specular shininess factor uniform FP vec3 eyePosition; -#pragma include light.inc.frag +#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 normal = 2.0 * texture2D( normalTexture, texCoord ).rgb - vec3( 1.0 ); + FP vec3 tNormal = 2.0 * texture2D( normalTexture, texCoord ).rgb - vec3( 1.0 ); - // Calculate the lighting model, keeping the specular component separate - FP vec3 diffuseColor, specularColor; - adsModelNormalMapped(worldPosition, normal, eyePosition, shininess, tangentMatrix, diffuseColor, specularColor); + FP mat3 tangentMatrix = calcWorldSpaceToTangentSpaceMatrix(worldNormal, worldTangent); + FP mat3 invertTangentMatrix = transpose(tangentMatrix); - // Combine spec with ambient+diffuse for final fragment color - gl_FragColor = vec4( ka + diffuseTextureColor.rgb * diffuseColor + specularTextureColor.rgb * specularColor, 1.0 ); + 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/pervertexcolor.frag b/src/extras/shaders/es2/pervertexcolor.frag index ab429d942..a2f0e8bf2 100644 --- a/src/extras/shaders/es2/pervertexcolor.frag +++ b/src/extras/shaders/es2/pervertexcolor.frag @@ -2,13 +2,14 @@ varying FP vec3 worldPosition; varying FP vec3 worldNormal; -varying FP vec3 color; +varying FP vec4 color; -#pragma include light.inc.frag +uniform FP vec3 eyePosition; + +#pragma include phong.inc.frag void main() { - FP vec3 diffuseColor; - adModel(worldPosition, worldNormal, diffuseColor); - gl_FragColor = vec4( color + color * diffuseColor, 1.0 ); + FP vec3 worldView = normalize(eyePosition - worldPosition); + gl_FragColor = phongFunction(color, color, vec4(0.0), 0.0, worldPosition, worldView, worldNormal); } diff --git a/src/extras/shaders/es2/pervertexcolor.vert b/src/extras/shaders/es2/pervertexcolor.vert index 7fc3e649f..bfa2e615a 100644 --- a/src/extras/shaders/es2/pervertexcolor.vert +++ b/src/extras/shaders/es2/pervertexcolor.vert @@ -1,10 +1,10 @@ attribute vec3 vertexPosition; attribute vec3 vertexNormal; -attribute vec3 vertexColor; +attribute vec4 vertexColor; varying vec3 worldPosition; varying vec3 worldNormal; -varying vec3 color; +varying vec4 color; uniform mat4 modelMatrix; uniform mat3 modelNormalMatrix; diff --git a/src/extras/shaders/es2/phong.frag b/src/extras/shaders/es2/phong.frag index c00f89db0..6b8ab7111 100644 --- a/src/extras/shaders/es2/phong.frag +++ b/src/extras/shaders/es2/phong.frag @@ -1,8 +1,8 @@ #define FP highp -uniform FP vec3 ka; // Ambient reflectivity -uniform FP vec3 kd; // Diffuse reflectivity -uniform FP vec3 ks; // Specular reflectivity +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; @@ -10,11 +10,10 @@ uniform FP vec3 eyePosition; varying FP vec3 worldPosition; varying FP vec3 worldNormal; -#pragma include light.inc.frag +#pragma include phong.inc.frag void main() { - FP vec3 diffuseColor, specularColor; - adsModel(worldPosition, worldNormal, eyePosition, shininess, diffuseColor, specularColor); - gl_FragColor = vec4( ka + kd * diffuseColor + ks * specularColor, 1.0 ); + FP vec3 worldView = normalize(eyePosition - worldPosition); + gl_FragColor = phongFunction(ka, kd, ks, shininess, worldPosition, worldView, worldNormal); } diff --git a/src/extras/shaders/es2/phong.inc.frag b/src/extras/shaders/es2/phong.inc.frag new file mode 100644 index 000000000..9d17b68b5 --- /dev/null +++ b/src/extras/shaders/es2/phong.inc.frag @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#pragma include light.inc.frag + +void adsModel(const in FP vec3 vpos, const in FP vec3 vnormal, const in FP vec3 vview, const in FP float shininess, + out FP vec3 diffuseColor, out FP vec3 specularColor) +{ + diffuseColor = vec3(0.0); + specularColor = vec3(0.0); + + FP vec3 n = normalize( vnormal ); + + FP vec3 s; + Light light; + for (int i = 0; i < lightCount; ++i) { + if (i == 0) + light = lights[0]; + else if (i == 1) + light = lights[1]; + else if (i == 2) + light = lights[2]; + else if (i == 3) + light = lights[3]; + else if (i == 4) + light = lights[4]; + else if (i == 5) + light = lights[5]; + else if (i == 6) + light = lights[6]; + else if (i == 7) + light = lights[7]; + + FP float att = 1.0; + if ( light.type != TYPE_DIRECTIONAL ) { + s = light.position - vpos; + if (length( light.attenuation ) != 0.0) { + FP float dist = length(s); + att = 1.0 / (light.attenuation.x + light.attenuation.y * dist + light.attenuation.z * dist * dist); + } + s = normalize( s ); + if ( light.type == TYPE_SPOT ) { + if ( degrees(acos(dot(-s, normalize(light.direction))) ) > light.cutOffAngle) + att = 0.0; + } + } else { + s = normalize( -light.direction ); + } + + FP float diffuse = max( dot( s, n ), 0.0 ); + + FP float specular = 0.0; + if (diffuse > 0.0 && shininess > 0.0 && att > 0.0) { + FP vec3 r = reflect( -s, n ); + FP float normFactor = ( shininess + 2.0 ) / 2.0; + specular = normFactor * pow( max( dot( r, vview ), 0.0 ), shininess ); + } + + diffuseColor += att * light.intensity * diffuse * light.color; + specularColor += att * light.intensity * specular * light.color; + } +} + +FP vec4 phongFunction(const in FP vec4 ambient, + const in FP vec4 diffuse, + const in FP vec4 specular, + const in FP float shininess, + const in FP vec3 worldPosition, + const in FP vec3 worldView, + const in FP vec3 worldNormal) +{ + // Calculate the lighting model, keeping the specular component separate + FP vec3 diffuseColor, specularColor; + adsModel(worldPosition, worldNormal, worldView, shininess, diffuseColor, specularColor); + + // Combine spec with ambient+diffuse for final fragment color + FP vec3 color = (ambient.rgb + diffuseColor) * diffuse.rgb + + specularColor * specular.rgb; + + return vec4(color, diffuse.a); +} diff --git a/src/extras/shaders/es2/phong.inc.frag100 b/src/extras/shaders/es2/phong.inc.frag100 new file mode 100644 index 000000000..507d8eaf5 --- /dev/null +++ b/src/extras/shaders/es2/phong.inc.frag100 @@ -0,0 +1,142 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#pragma include light.inc.frag + +void adsModel(const in FP vec3 vpos, const in FP vec3 vnormal, const in FP vec3 vview, const in FP float shininess, + out FP vec3 diffuseColor, out FP vec3 specularColor) +{ + diffuseColor = vec3(0.0); + specularColor = vec3(0.0); + + FP vec3 n = normalize( vnormal ); + + // 0 + if (lightCount < 1) + return; + FP vec3 s; + FP float att = 1.0; + if ( lights[0].type != TYPE_DIRECTIONAL ) { + s = lights[0].position - vpos; + if (length( lights[0].attenuation ) != 0.0) { + FP float dist = length(s); + att = 1.0 / (lights[0].attenuation.x + lights[0].attenuation.y * dist + lights[0].attenuation.z * dist * dist); + } + s = normalize( s ); + if ( lights[0].type == TYPE_SPOT ) { + if ( degrees(acos(dot(-s, normalize(lights[0].direction))) ) > lights[0].cutOffAngle) + att = 0.0; + } + } else { + s = normalize( -lights[0].direction ); + } + + FP float diffuse = max( dot( s, n ), 0.0 ); + + FP float specular = 0.0; + if (diffuse > 0.0 && shininess > 0.0 && att > 0.0) { + FP vec3 r = reflect( -s, n ); + FP float normFactor = ( shininess + 2.0 ) / 2.0; + specular = normFactor * pow( max( dot( r, vview ), 0.0 ), shininess ); + } + + diffuseColor += att * lights[0].intensity * diffuse * lights[0].color; + specularColor += att * specular; + + // 1 + if (lightCount < 2) + return; + att = 1.0; + if ( lights[1].type != TYPE_DIRECTIONAL ) { + s = lights[1].position - vpos; + if (length( lights[1].attenuation ) != 0.0) { + FP float dist = length(s); + att = 1.0 / (lights[1].attenuation.x + lights[1].attenuation.y * dist + lights[1].attenuation.z * dist * dist); + } + s = normalize( s ); + if ( lights[1].type == TYPE_SPOT ) { + if ( degrees(acos(dot(-s, normalize(lights[1].direction))) ) > lights[1].cutOffAngle) + att = 0.0; + } + } else { + s = normalize( -lights[1].direction ); + } + + diffuse = max( dot( s, n ), 0.0 ); + + specular = 0.0; + if (diffuse > 0.0 && shininess > 0.0 && att > 0.0) { + FP vec3 r = reflect( -s, n ); + FP float normFactor = ( shininess + 2.0 ) / 2.0; + specular = normFactor * pow( max( dot( r, vview ), 0.0 ), shininess ); + } + + diffuseColor += att * lights[1].intensity * diffuse * lights[1].color; + specularColor += att * specular; +} + +FP vec4 phongFunction(const in FP vec4 ambient, + const in FP vec4 diffuse, + const in FP vec4 specular, + const in FP float shininess, + const in FP vec3 worldPosition, + const in FP vec3 worldView, + const in FP vec3 worldNormal) +{ + // Calculate the lighting model, keeping the specular component separate + FP vec3 diffuseColor, specularColor; + adsModel(worldPosition, worldNormal, worldView, shininess, diffuseColor, specularColor); + + // Combine spec with ambient+diffuse for final fragment color + FP vec3 color = (ambient.rgb + diffuseColor) * diffuse.rgb + + specularColor * specular.rgb; + + return vec4(color, diffuse.a); +} diff --git a/src/extras/shaders/es2/phong.vert b/src/extras/shaders/es2/phong.vert deleted file mode 100644 index 2b4c51b14..000000000 --- a/src/extras/shaders/es2/phong.vert +++ /dev/null @@ -1,17 +0,0 @@ -attribute vec3 vertexPosition; -attribute vec3 vertexNormal; - -varying vec3 worldPosition; -varying vec3 worldNormal; - -uniform mat4 modelMatrix; -uniform mat3 modelNormalMatrix; -uniform mat4 modelViewProjection; - -void main() -{ - worldNormal = normalize( modelNormalMatrix * vertexNormal ); - worldPosition = vec3( modelMatrix * vec4( vertexPosition, 1.0 ) ); - - gl_Position = modelViewProjection * vec4( vertexPosition, 1.0 ); -} diff --git a/src/extras/shaders/es2/phongalpha.frag b/src/extras/shaders/es2/phongalpha.frag deleted file mode 100644 index c5ec43049..000000000 --- a/src/extras/shaders/es2/phongalpha.frag +++ /dev/null @@ -1,22 +0,0 @@ -#define FP highp - -// TODO: Replace with a struct -uniform FP vec3 ka; // Ambient reflectivity -uniform FP vec3 kd; // Diffuse reflectivity -uniform FP vec3 ks; // Specular reflectivity -uniform FP float shininess; // Specular shininess factor -uniform FP float alpha; - -uniform FP vec3 eyePosition; - -varying FP vec3 worldPosition; -varying FP vec3 worldNormal; - -#pragma include light.inc.frag - -void main() -{ - FP vec3 diffuseColor, specularColor; - adsModel(worldPosition, worldNormal, eyePosition, shininess, diffuseColor, specularColor); - gl_FragColor = vec4( ka + kd * diffuseColor + ks * specularColor, alpha ); -} diff --git a/src/extras/shaders/gl3/metalrough.vert b/src/extras/shaders/gl3/default.vert index 6d3a60ef6..f97cd099d 100644 --- a/src/extras/shaders/gl3/metalrough.vert +++ b/src/extras/shaders/gl3/default.vert @@ -48,7 +48,7 @@ ** ****************************************************************************/ -#version 150 +#version 150 core in vec3 vertexPosition; in vec3 vertexNormal; @@ -62,12 +62,14 @@ out vec2 texCoord; uniform mat4 modelMatrix; uniform mat3 modelNormalMatrix; -uniform mat4 mvp; +uniform mat4 modelViewProjection; + +uniform float texCoordScale; void main() { - // Pass the texture coordinates through - texCoord = vertexTexCoord; + // Pass through scaled texture coordinates + texCoord = vertexTexCoord * texCoordScale; // Transform position, normal, and tangent to world space worldPosition = vec3(modelMatrix * vec4(vertexPosition, 1.0)); @@ -75,5 +77,6 @@ void main() worldTangent.xyz = normalize(vec3(modelMatrix * vec4(vertexTangent.xyz, 0.0))); worldTangent.w = vertexTangent.w; - gl_Position = mvp * vec4(vertexPosition, 1.0); + // Calculate vertex position in clip coordinates + gl_Position = modelViewProjection * vec4(vertexPosition, 1.0); } diff --git a/src/extras/shaders/gl3/diffusemap.frag b/src/extras/shaders/gl3/diffusemap.frag index 7810fdb68..34fef5a43 100644 --- a/src/extras/shaders/gl3/diffusemap.frag +++ b/src/extras/shaders/gl3/diffusemap.frag @@ -1,7 +1,7 @@ #version 150 core -uniform vec3 ka; // Ambient reflectivity -uniform vec3 ks; // Specular reflectivity +uniform vec4 ka; // Ambient reflectivity +uniform vec4 ks; // Specular reflectivity uniform float shininess; // Specular shininess factor uniform vec3 eyePosition; @@ -14,14 +14,11 @@ in vec2 texCoord; out vec4 fragColor; -#pragma include light.inc.frag +#pragma include phong.inc.frag void main() { - vec3 diffuseTextureColor = texture( diffuseTexture, texCoord ).rgb; - - vec3 diffuseColor, specularColor; - adsModel(worldPosition, worldNormal, eyePosition, shininess, diffuseColor, specularColor); - - fragColor = vec4( diffuseTextureColor * ( ka + diffuseColor ) + ks * specularColor, 1.0 ); + 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/diffusemap.vert b/src/extras/shaders/gl3/diffusemap.vert deleted file mode 100644 index 439be6e99..000000000 --- a/src/extras/shaders/gl3/diffusemap.vert +++ /dev/null @@ -1,24 +0,0 @@ -#version 150 core - -in vec3 vertexPosition; -in vec3 vertexNormal; -in vec2 vertexTexCoord; - -out vec3 worldPosition; -out vec3 worldNormal; -out vec2 texCoord; - -uniform mat4 modelMatrix; -uniform mat3 modelNormalMatrix; -uniform mat4 mvp; - -uniform float texCoordScale; - -void main() -{ - texCoord = vertexTexCoord * texCoordScale; - worldNormal = normalize( modelNormalMatrix * vertexNormal ); - worldPosition = vec3( modelMatrix * vec4( vertexPosition, 1.0 ) ); - - gl_Position = mvp * vec4( vertexPosition, 1.0 ); -} diff --git a/src/extras/shaders/gl3/diffusespecularmap.frag b/src/extras/shaders/gl3/diffusespecularmap.frag index fb809393a..8673a5121 100644 --- a/src/extras/shaders/gl3/diffusespecularmap.frag +++ b/src/extras/shaders/gl3/diffusespecularmap.frag @@ -1,7 +1,7 @@ #version 150 core // TODO: Replace with a struct -uniform vec3 ka; // Ambient reflectivity +uniform vec4 ka; // Ambient reflectivity uniform float shininess; // Specular shininess factor uniform vec3 eyePosition; @@ -15,15 +15,12 @@ in vec2 texCoord; out vec4 fragColor; -#pragma include light.inc.frag +#pragma include phong.inc.frag void main() { - vec3 diffuseTextureColor = texture( diffuseTexture, texCoord ).rgb; - vec3 specularTextureColor = texture( specularTexture, texCoord ).rgb; - - vec3 diffuseColor, specularColor; - adsModel(worldPosition, worldNormal, eyePosition, shininess, diffuseColor, specularColor); - - fragColor = vec4( diffuseTextureColor * ( ka + diffuseColor ) + specularTextureColor * specularColor, 1.0 ); + 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/light.inc.frag b/src/extras/shaders/gl3/light.inc.frag index ce5c581cf..0b642638f 100644 --- a/src/extras/shaders/gl3/light.inc.frag +++ b/src/extras/shaders/gl3/light.inc.frag @@ -23,200 +23,3 @@ struct EnvironmentLight { }; uniform EnvironmentLight envLight; uniform int envLightCount = 0; - -void adsModelNormalMapped(const in vec3 worldPos, - const in vec3 tsNormal, - const in vec3 worldEye, - const in float shininess, - const in mat3 tangentMatrix, - out vec3 diffuseColor, - out vec3 specularColor) -{ - diffuseColor = vec3(0.0); - specularColor = vec3(0.0); - - // We perform all work in tangent space, so we convert quantities from world space - vec3 tsPos = tangentMatrix * worldPos; - vec3 n = normalize(tsNormal); - vec3 v = normalize(tangentMatrix * (worldEye - worldPos)); - vec3 s = vec3(0.0); - - for (int i = 0; i < lightCount; ++i) { - float att = 1.0; - float sDotN = 0.0; - - if (lights[i].type != TYPE_DIRECTIONAL) { - // Point and Spot lights - - // Transform the light position from world to tangent space - vec3 tsLightPos = tangentMatrix * lights[i].position; - vec3 sUnnormalized = tsLightPos - tsPos; - s = normalize(sUnnormalized); // Light direction in tangent space - - // Calculate the attenuation factor - sDotN = dot(s, n); - if (sDotN > 0.0) { - if (lights[i].constantAttenuation != 0.0 - || lights[i].linearAttenuation != 0.0 - || lights[i].quadraticAttenuation != 0.0) { - float dist = length(sUnnormalized); - att = 1.0 / (lights[i].constantAttenuation + - lights[i].linearAttenuation * dist + - lights[i].quadraticAttenuation * dist * dist); - } - - // The light direction is in world space, convert to tangent space - if (lights[i].type == TYPE_SPOT) { - // Check if fragment is inside or outside of the spot light cone - vec3 tsLightDirection = tangentMatrix * lights[i].direction; - if (degrees(acos(dot(-s, tsLightDirection))) > lights[i].cutOffAngle) - sDotN = 0.0; - } - } - } else { - // Directional lights - // The light direction is in world space, convert to tangent space - s = normalize(tangentMatrix * -lights[i].direction); - sDotN = dot(s, n); - } - - // Calculate the diffuse factor - float diffuse = max(sDotN, 0.0); - - // Calculate the specular factor - float specular = 0.0; - if (diffuse > 0.0 && shininess > 0.0) { - float normFactor = (shininess + 2.0) / 2.0; - vec3 r = reflect(-s, n); // Reflection direction in tangent space - specular = normFactor * pow(max(dot(r, v), 0.0), shininess); - } - - // Accumulate the diffuse and specular contributions - diffuseColor += att * lights[i].intensity * diffuse * lights[i].color; - specularColor += att * lights[i].intensity * specular * lights[i].color; - } -} - -void adsModel(const in vec3 worldPos, - const in vec3 worldNormal, - const in vec3 worldEye, - const in float shininess, - out vec3 diffuseColor, - out vec3 specularColor) -{ - diffuseColor = vec3(0.0); - specularColor = vec3(0.0); - - // We perform all work in world space - vec3 n = normalize(worldNormal); - vec3 v = normalize(worldEye - worldPos); - vec3 s = vec3(0.0); - - for (int i = 0; i < lightCount; ++i) { - float att = 1.0; - float sDotN = 0.0; - - if (lights[i].type != TYPE_DIRECTIONAL) { - // Point and Spot lights - - // Light position is already in world space - vec3 sUnnormalized = lights[i].position - worldPos; - s = normalize(sUnnormalized); // Light direction - - // Calculate the attenuation factor - sDotN = dot(s, n); - if (sDotN > 0.0) { - if (lights[i].constantAttenuation != 0.0 - || lights[i].linearAttenuation != 0.0 - || lights[i].quadraticAttenuation != 0.0) { - float dist = length(sUnnormalized); - att = 1.0 / (lights[i].constantAttenuation + - lights[i].linearAttenuation * dist + - lights[i].quadraticAttenuation * dist * dist); - } - - // The light direction is in world space already - if (lights[i].type == TYPE_SPOT) { - // Check if fragment is inside or outside of the spot light cone - if (degrees(acos(dot(-s, lights[i].direction))) > lights[i].cutOffAngle) - sDotN = 0.0; - } - } - } else { - // Directional lights - // The light direction is in world space already - s = normalize(-lights[i].direction); - sDotN = dot(s, n); - } - - // Calculate the diffuse factor - float diffuse = max(sDotN, 0.0); - - // Calculate the specular factor - float specular = 0.0; - if (diffuse > 0.0 && shininess > 0.0) { - float normFactor = (shininess + 2.0) / 2.0; - vec3 r = reflect(-s, n); // Reflection direction in world space - specular = normFactor * pow(max(dot(r, v), 0.0), shininess); - } - - // Accumulate the diffuse and specular contributions - diffuseColor += att * lights[i].intensity * diffuse * lights[i].color; - specularColor += att * lights[i].intensity * specular * lights[i].color; - } -} - -void adModel(const in vec3 worldPos, - const in vec3 worldNormal, - out vec3 diffuseColor) -{ - diffuseColor = vec3(0.0); - - // We perform all work in world space - vec3 n = normalize(worldNormal); - vec3 s = vec3(0.0); - - for (int i = 0; i < lightCount; ++i) { - float att = 1.0; - float sDotN = 0.0; - - if (lights[i].type != TYPE_DIRECTIONAL) { - // Point and Spot lights - - // Light position is already in world space - vec3 sUnnormalized = lights[i].position - worldPos; - s = normalize(sUnnormalized); // Light direction - - // Calculate the attenuation factor - sDotN = dot(s, n); - if (sDotN > 0.0) { - if (lights[i].constantAttenuation != 0.0 - || lights[i].linearAttenuation != 0.0 - || lights[i].quadraticAttenuation != 0.0) { - float dist = length(sUnnormalized); - att = 1.0 / (lights[i].constantAttenuation + - lights[i].linearAttenuation * dist + - lights[i].quadraticAttenuation * dist * dist); - } - - // The light direction is in world space already - if (lights[i].type == TYPE_SPOT) { - // Check if fragment is inside or outside of the spot light cone - if (degrees(acos(dot(-s, lights[i].direction))) > lights[i].cutOffAngle) - sDotN = 0.0; - } - } - } else { - // Directional lights - // The light direction is in world space already - s = normalize(-lights[i].direction); - sDotN = dot(s, n); - } - - // Calculate the diffuse factor - float diffuse = max(sDotN, 0.0); - - // Accumulate the diffuse contributions - diffuseColor += att * lights[i].intensity * diffuse * lights[i].color; - } -} diff --git a/src/extras/shaders/gl3/normaldiffusemap.frag b/src/extras/shaders/gl3/normaldiffusemap.frag index a99a7ed73..bac776738 100644 --- a/src/extras/shaders/gl3/normaldiffusemap.frag +++ b/src/extras/shaders/gl3/normaldiffusemap.frag @@ -1,33 +1,36 @@ #version 150 core in vec3 worldPosition; +in vec3 worldNormal; +in vec4 worldTangent; in vec2 texCoord; -in mat3 tangentMatrix; uniform sampler2D diffuseTexture; uniform sampler2D normalTexture; // TODO: Replace with a struct -uniform vec3 ka; // Ambient reflectivity -uniform vec3 ks; // Specular reflectivity +uniform vec4 ka; // Ambient reflectivity +uniform vec4 ks; // Specular reflectivity uniform float shininess; // Specular shininess factor uniform vec3 eyePosition; out vec4 fragColor; -#pragma include light.inc.frag +#pragma include phong.inc.frag +#pragma include coordinatesystems.inc void main() { // Sample the textures at the interpolated texCoords vec4 diffuseTextureColor = texture( diffuseTexture, texCoord ); - vec3 normal = 2.0 * texture( normalTexture, texCoord ).rgb - vec3( 1.0 ); + vec3 tNormal = 2.0 * texture( normalTexture, texCoord ).rgb - vec3( 1.0 ); - // Calculate the lighting model, keeping the specular component separate - vec3 diffuseColor, specularColor; - adsModelNormalMapped(worldPosition, normal, eyePosition, shininess, tangentMatrix, diffuseColor, specularColor); + mat3 tangentMatrix = calcWorldSpaceToTangentSpaceMatrix(worldNormal, worldTangent); + mat3 invertTangentMatrix = transpose(tangentMatrix); - // Combine spec with ambient+diffuse for final fragment color - fragColor = vec4( ka + diffuseTextureColor.rgb * diffuseColor + ks * specularColor, 1.0 ); + 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/normaldiffusemap.vert b/src/extras/shaders/gl3/normaldiffusemap.vert deleted file mode 100644 index 8da443e8d..000000000 --- a/src/extras/shaders/gl3/normaldiffusemap.vert +++ /dev/null @@ -1,47 +0,0 @@ -#version 150 core - -in vec3 vertexPosition; -in vec3 vertexNormal; -in vec2 vertexTexCoord; -in vec4 vertexTangent; - -out vec3 worldPosition; -out vec2 texCoord; -out mat3 tangentMatrix; - -uniform mat4 modelMatrix; -uniform mat3 modelNormalMatrix; -uniform mat4 mvp; - -uniform float texCoordScale; - -void main() -{ - // Pass through scaled texture coordinates - texCoord = vertexTexCoord * texCoordScale; - - // Transform position, normal, and tangent to world coords - worldPosition = vec3(modelMatrix * vec4(vertexPosition, 1.0)); - vec3 normal = normalize(modelNormalMatrix * vertexNormal); - vec3 tangent = normalize(vec3(modelMatrix * vec4(vertexTangent.xyz, 0.0))); - - // Make the tangent truly orthogonal to the normal by using Gram-Schmidt. - // This allows to build the tangentMatrix below by simply transposing the - // tangent -> world space matrix (which would now be orthogonal) - tangent = normalize(tangent - dot(tangent, normal) * normal); - - // Calculate binormal vector. No "real" need to renormalize it, - // as built by crossing two normal vectors. - // To orient the binormal correctly, use the fourth coordinate of the tangent, - // which is +1 for a right hand system, and -1 for a left hand system. - vec3 binormal = cross(normal, tangent) * vertexTangent.w; - - // Construct matrix to transform from eye coords to tangent space - tangentMatrix = mat3( - tangent.x, binormal.x, normal.x, - tangent.y, binormal.y, normal.y, - tangent.z, binormal.z, normal.z); - - // Calculate vertex position in clip coordinates - gl_Position = mvp * vec4(vertexPosition, 1.0); -} diff --git a/src/extras/shaders/gl3/normaldiffusemapalpha.frag b/src/extras/shaders/gl3/normaldiffusemapalpha.frag deleted file mode 100644 index ce5cf0e90..000000000 --- a/src/extras/shaders/gl3/normaldiffusemapalpha.frag +++ /dev/null @@ -1,34 +0,0 @@ -#version 150 core - -in vec3 worldPosition; -in vec2 texCoord; -in mat3 tangentMatrix; - -uniform sampler2D diffuseTexture; -uniform sampler2D normalTexture; - -// TODO: Replace with a struct -uniform vec3 ka; // Ambient reflectivity -uniform vec3 ks; // Specular reflectivity -uniform float shininess; // Specular shininess factor - -uniform vec3 eyePosition; - -out vec4 fragColor; - -#pragma include light.inc.frag - -void main() -{ - // Sample the textures at the interpolated texCoords - vec4 diffuseTextureColor = texture( diffuseTexture, texCoord ); - vec3 normal = 2.0 * texture( normalTexture, texCoord ).rgb - vec3( 1.0 ); - - // Calculate the lighting model, keeping the specular component separate - vec3 diffuseColor, specularColor; - adsModelNormalMapped(worldPosition, normal, eyePosition, shininess, tangentMatrix, diffuseColor, specularColor); - - // Combine spec with ambient+diffuse for final fragment color - // Use the alpha from the diffuse texture (for alpha to coverage) - fragColor = vec4( ka + diffuseTextureColor.rgb * diffuseColor + ks * specularColor, diffuseTextureColor.a ); -} diff --git a/src/extras/shaders/gl3/normaldiffusespecularmap.frag b/src/extras/shaders/gl3/normaldiffusespecularmap.frag index b60cfe84c..d96b9e747 100644 --- a/src/extras/shaders/gl3/normaldiffusespecularmap.frag +++ b/src/extras/shaders/gl3/normaldiffusespecularmap.frag @@ -1,8 +1,9 @@ #version 150 core in vec3 worldPosition; +in vec3 worldNormal; +in vec4 worldTangent; in vec2 texCoord; -in mat3 tangentMatrix; out vec4 fragColor; @@ -10,26 +11,25 @@ uniform sampler2D diffuseTexture; uniform sampler2D specularTexture; uniform sampler2D normalTexture; -uniform vec3 ka; // Ambient reflectivity +uniform vec4 ka; // Ambient reflectivity uniform float shininess; // Specular shininess factor uniform vec3 eyePosition; -#pragma include light.inc.frag +#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 normal = 2.0 * texture( normalTexture, texCoord ).rgb - vec3( 1.0 ); + vec3 tNormal = 2.0 * texture( normalTexture, texCoord ).rgb - vec3( 1.0 ); - // Calculate the lighting model, keeping the specular component separate - vec3 diffuseColor, specularColor; - adsModelNormalMapped(worldPosition, normal, eyePosition, - shininess, tangentMatrix, - diffuseColor, specularColor); + mat3 tangentMatrix = calcWorldSpaceToTangentSpaceMatrix(worldNormal, worldTangent); + mat3 invertTangentMatrix = transpose(tangentMatrix); - // Combine spec with ambient+diffuse for final fragment color - fragColor = vec4((ka + diffuseColor) * diffuseTextureColor.rgb - + specularColor * specularTextureColor.rgb, 1.0); + 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/pervertexcolor.frag b/src/extras/shaders/gl3/pervertexcolor.frag index b5ed5a33d..40fc066d6 100644 --- a/src/extras/shaders/gl3/pervertexcolor.frag +++ b/src/extras/shaders/gl3/pervertexcolor.frag @@ -2,15 +2,16 @@ in vec3 worldPosition; in vec3 worldNormal; -in vec3 color; +in vec4 color; out vec4 fragColor; -#pragma include light.inc.frag +uniform vec3 eyePosition; + +#pragma include phong.inc.frag void main() { - vec3 diffuseColor; - adModel(worldPosition, worldNormal, diffuseColor); - fragColor = vec4( color + color * diffuseColor, 1.0 ); + vec3 worldView = normalize(eyePosition - worldPosition); + fragColor = phongFunction(color, color, vec4(0.0), 0.0, worldPosition, worldView, worldNormal); } diff --git a/src/extras/shaders/gl3/pervertexcolor.vert b/src/extras/shaders/gl3/pervertexcolor.vert index 87713a520..1d721e945 100644 --- a/src/extras/shaders/gl3/pervertexcolor.vert +++ b/src/extras/shaders/gl3/pervertexcolor.vert @@ -2,11 +2,11 @@ in vec3 vertexPosition; in vec3 vertexNormal; -in vec3 vertexColor; +in vec4 vertexColor; out vec3 worldPosition; out vec3 worldNormal; -out vec3 color; +out vec4 color; uniform mat4 modelMatrix; uniform mat3 modelNormalMatrix; diff --git a/src/extras/shaders/gl3/phong.frag b/src/extras/shaders/gl3/phong.frag index a4d7e0969..3652672b5 100644 --- a/src/extras/shaders/gl3/phong.frag +++ b/src/extras/shaders/gl3/phong.frag @@ -1,8 +1,8 @@ #version 150 core -uniform vec3 ka; // Ambient reflectivity -uniform vec3 kd; // Diffuse reflectivity -uniform vec3 ks; // Specular reflectivity +uniform vec4 ka; // Ambient reflectivity +uniform vec4 kd; // Diffuse reflectivity +uniform vec4 ks; // Specular reflectivity uniform float shininess; // Specular shininess factor uniform vec3 eyePosition; @@ -12,11 +12,10 @@ in vec3 worldNormal; out vec4 fragColor; -#pragma include light.inc.frag +#pragma include phong.inc.frag void main() { - vec3 diffuseColor, specularColor; - adsModel(worldPosition, worldNormal, eyePosition, shininess, diffuseColor, specularColor); - fragColor = vec4( ka + kd * diffuseColor + ks * specularColor, 1.0 ); + vec3 worldView = normalize(eyePosition - worldPosition); + fragColor = phongFunction(ka, kd, ks, shininess, worldPosition, worldView, worldNormal); } diff --git a/src/extras/shaders/gl3/phong.inc.frag b/src/extras/shaders/gl3/phong.inc.frag new file mode 100644 index 000000000..47a6ecd4a --- /dev/null +++ b/src/extras/shaders/gl3/phong.inc.frag @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#pragma include light.inc.frag + +void adsModel(const in vec3 worldPos, + const in vec3 worldNormal, + const in vec3 worldView, + const in float shininess, + out vec3 diffuseColor, + out vec3 specularColor) +{ + diffuseColor = vec3(0.0); + specularColor = vec3(0.0); + + // We perform all work in world space + vec3 n = normalize(worldNormal); + vec3 s = vec3(0.0); + + for (int i = 0; i < lightCount; ++i) { + float att = 1.0; + float sDotN = 0.0; + + if (lights[i].type != TYPE_DIRECTIONAL) { + // Point and Spot lights + + // Light position is already in world space + vec3 sUnnormalized = lights[i].position - worldPos; + s = normalize(sUnnormalized); // Light direction + + // Calculate the attenuation factor + sDotN = dot(s, n); + if (sDotN > 0.0) { + if (lights[i].constantAttenuation != 0.0 + || lights[i].linearAttenuation != 0.0 + || lights[i].quadraticAttenuation != 0.0) { + float dist = length(sUnnormalized); + att = 1.0 / (lights[i].constantAttenuation + + lights[i].linearAttenuation * dist + + lights[i].quadraticAttenuation * dist * dist); + } + + // The light direction is in world space already + if (lights[i].type == TYPE_SPOT) { + // Check if fragment is inside or outside of the spot light cone + if (degrees(acos(dot(-s, lights[i].direction))) > lights[i].cutOffAngle) + sDotN = 0.0; + } + } + } else { + // Directional lights + // The light direction is in world space already + s = normalize(-lights[i].direction); + sDotN = dot(s, n); + } + + // Calculate the diffuse factor + float diffuse = max(sDotN, 0.0); + + // Calculate the specular factor + float specular = 0.0; + if (diffuse > 0.0 && shininess > 0.0) { + float normFactor = (shininess + 2.0) / 2.0; + vec3 r = reflect(-s, n); // Reflection direction in world space + specular = normFactor * pow(max(dot(r, worldView), 0.0), shininess); + } + + // Accumulate the diffuse and specular contributions + diffuseColor += att * lights[i].intensity * diffuse * lights[i].color; + specularColor += att * lights[i].intensity * specular * lights[i].color; + } +} + +vec4 phongFunction(const in vec4 ambient, + const in vec4 diffuse, + const in vec4 specular, + const in float shininess, + const in vec3 worldPosition, + const in vec3 worldView, + const in vec3 worldNormal) +{ + // Calculate the lighting model, keeping the specular component separate + vec3 diffuseColor, specularColor; + adsModel(worldPosition, worldNormal, worldView, shininess, diffuseColor, specularColor); + + // Combine spec with ambient+diffuse for final fragment color + vec3 color = (ambient.rgb + diffuseColor) * diffuse.rgb + + specularColor * specular.rgb; + + return vec4(color, diffuse.a); +} diff --git a/src/extras/shaders/gl3/phong.vert b/src/extras/shaders/gl3/phong.vert deleted file mode 100644 index cdb3c70e9..000000000 --- a/src/extras/shaders/gl3/phong.vert +++ /dev/null @@ -1,19 +0,0 @@ -#version 150 core - -in vec3 vertexPosition; -in vec3 vertexNormal; - -out vec3 worldPosition; -out vec3 worldNormal; - -uniform mat4 modelMatrix; -uniform mat3 modelNormalMatrix; -uniform mat4 modelViewProjection; - -void main() -{ - worldNormal = normalize( modelNormalMatrix * vertexNormal ); - worldPosition = vec3( modelMatrix * vec4( vertexPosition, 1.0 ) ); - - gl_Position = modelViewProjection * vec4( vertexPosition, 1.0 ); -} diff --git a/src/extras/shaders/gl3/phongalpha.frag b/src/extras/shaders/gl3/phongalpha.frag deleted file mode 100644 index cb019e9aa..000000000 --- a/src/extras/shaders/gl3/phongalpha.frag +++ /dev/null @@ -1,24 +0,0 @@ -#version 150 core - -// TODO: Replace with a struct -uniform vec3 ka; // Ambient reflectivity -uniform vec3 kd; // Diffuse reflectivity -uniform vec3 ks; // Specular reflectivity -uniform float shininess; // Specular shininess factor -uniform float alpha; - -uniform vec3 eyePosition; - -in vec3 worldPosition; -in vec3 worldNormal; - -out vec4 fragColor; - -#pragma include light.inc.frag - -void main() -{ - vec3 diffuseColor, specularColor; - adsModel(worldPosition, worldNormal, eyePosition, shininess, diffuseColor, specularColor); - fragColor = vec4( ka + kd * diffuseColor + ks * specularColor, alpha ); -} diff --git a/src/extras/text/distancefieldtextrenderer.cpp b/src/extras/text/distancefieldtextrenderer.cpp index 9f390e8da..4cf9c0b4a 100644 --- a/src/extras/text/distancefieldtextrenderer.cpp +++ b/src/extras/text/distancefieldtextrenderer.cpp @@ -80,8 +80,8 @@ void DistanceFieldTextRendererPrivate::init() m_geometry = new Qt3DRender::QGeometry(m_renderer); m_renderer->setGeometry(m_geometry); - m_vertexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, m_geometry); - m_indexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::IndexBuffer, m_geometry); + m_vertexBuffer = new Qt3DRender::QBuffer(m_geometry); + m_indexBuffer = new Qt3DRender::QBuffer(m_geometry); m_positionAttr = new Qt3DRender::QAttribute(m_geometry); m_positionAttr->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); diff --git a/src/plugins/geometryloaders/default/objgeometryloader.cpp b/src/plugins/geometryloaders/default/objgeometryloader.cpp index b1fb1f931..7184e2f69 100644 --- a/src/plugins/geometryloaders/default/objgeometryloader.cpp +++ b/src/plugins/geometryloaders/default/objgeometryloader.cpp @@ -144,7 +144,7 @@ bool ObjGeometryLoader::doLoad(QIODevice *ioDev, const QString &subMesh) ++normalsOffset; } } - } else if (!skipping && qstrncmp(tokens.charPtrAt(0), "f ", 2) == 0) { + } else if (!skipping && tokens.size() >= 4 && qstrncmp(tokens.charPtrAt(0), "f ", 2) == 0) { // Process face ++faceCount; diff --git a/src/plugins/sceneparsers/assimp/assimpimporter.cpp b/src/plugins/sceneparsers/assimp/assimpimporter.cpp index a1558b7e2..3a06c7807 100644 --- a/src/plugins/sceneparsers/assimp/assimpimporter.cpp +++ b/src/plugins/sceneparsers/assimp/assimpimporter.cpp @@ -403,8 +403,8 @@ void AssimpImporter::setSource(const QUrl &source) } /*! - * Sets the \a source used by the parser to load the asset file. - * If the file is valid, this will trigger parsing of the file. + * Sets the \a basePath used by the parser to load the asset file. + * If the file specified in \a data is valid, this will trigger parsing of the file. */ void AssimpImporter::setData(const QByteArray &data, const QString &basePath) { @@ -412,7 +412,7 @@ void AssimpImporter::setData(const QByteArray &data, const QString &basePath) } /*! - * Returns \c true if the extension of \a source is supported by + * Returns \c true if the extension in QStringList \a extensions is supported by * the assimp parser. */ bool AssimpImporter::areFileTypesSupported(const QStringList &extensions) const diff --git a/src/plugins/sceneparsers/gltf/gltfimporter.cpp b/src/plugins/sceneparsers/gltf/gltfimporter.cpp index a94a4f307..4419bd708 100644 --- a/src/plugins/sceneparsers/gltf/gltfimporter.cpp +++ b/src/plugins/sceneparsers/gltf/gltfimporter.cpp @@ -268,11 +268,23 @@ GLTFImporter::~GLTFImporter() } +/*! + \class Qt3DRender::GLTFImporter + \inmodule Qt3DRender + \brief Handles importing of gltf files +*/ +/*! + Set the base \a path for importing scenes. +*/ void GLTFImporter::setBasePath(const QString& path) { m_basePath = path; } +/*! + Set a \a json document as the file used for importing a scene. + Returns true if the operation is successful. +*/ bool GLTFImporter::setJSON(const QJsonDocument &json ) { if ( !json.isObject() ) { @@ -286,7 +298,8 @@ bool GLTFImporter::setJSON(const QJsonDocument &json ) } /*! - * Sets the \a path used by the parser to load the scene file. + * Sets the path based on parameter \a source. The path is + * used by the parser to load the scene file. * If the file is valid, parsing is automatically triggered. */ void GLTFImporter::setSource(const QUrl &source) @@ -314,8 +327,9 @@ void GLTFImporter::setSource(const QUrl &source) } /*! - * Sets the \a path used by the parser to load the scene file. - * If the file is valid, parsing is automatically triggered. + * Sets the \a basePath used by the parser to load the scene file. + * If the file derived from \a data is valid, parsing is automatically + * triggered. */ void GLTFImporter::setData(const QByteArray& data, const QString &basePath) { @@ -332,7 +346,7 @@ void GLTFImporter::setData(const QByteArray& data, const QString &basePath) } /*! - * Returns true if the extensions are supported by the + * Returns true if the \a extensions are supported by the * GLTF parser. */ bool GLTFImporter::areFileTypesSupported(const QStringList &extensions) const @@ -340,6 +354,9 @@ bool GLTFImporter::areFileTypesSupported(const QStringList &extensions) const return GLTFImporter::isGLTFSupported(extensions); } +/*! + Imports the node specified in \a id from the GLTF file. +*/ Qt3DCore::QEntity* GLTFImporter::node(const QString &id) { QJsonObject nodes = m_json.object().value(KEY_NODES).toObject(); @@ -507,6 +524,9 @@ Qt3DCore::QEntity* GLTFImporter::node(const QString &id) return result; } +/*! + Imports the scene specified in parameter \a id. +*/ Qt3DCore::QEntity* GLTFImporter::scene(const QString &id) { parse(); @@ -1656,6 +1676,9 @@ void GLTFImporter::processJSONRenderPass(const QString &id, const QJsonObject &j m_renderPasses[id] = pass; } +/*! + Loads raw data from the GLTF file into the buffer. +*/ void GLTFImporter::loadBufferData() { for (auto &bufferData : m_bufferDatas) { @@ -1665,6 +1688,9 @@ void GLTFImporter::loadBufferData() } } +/*! + Removes all data from the buffer. +*/ void GLTFImporter::unloadBufferData() { for (const auto &bufferData : qAsConst(m_bufferDatas)) { diff --git a/src/plugins/sceneparsers/gltfexport/gltfexporter.cpp b/src/plugins/sceneparsers/gltfexport/gltfexporter.cpp index 7921fce64..ba100e095 100644 --- a/src/plugins/sceneparsers/gltfexport/gltfexporter.cpp +++ b/src/plugins/sceneparsers/gltfexport/gltfexporter.cpp @@ -266,6 +266,13 @@ GLTFExporter::~GLTFExporter() { } +/*! + \class Qt3DRender::GLTFExporter + \inmodule Qt3DRender + \brief Manages the export of a 3D scene to the GLTF format. + + Handles the export of a 3D scene to the GLTF format. +*/ // sceneRoot : The root entity that contains the exported scene. If the sceneRoot doesn't have // any exportable components, it is not exported itself. This is because importing a // scene creates an empty top level entity to hold the scene. @@ -278,6 +285,23 @@ GLTFExporter::~GLTFExporter() // "binaryJson" (bool): Generates a binary JSON file, which is more efficient to parse. // "compactJson" (bool): Removes unnecessary whitespace from the generated JSON file. // Ignored if "binaryJson" option is true. + +/*! + Exports the scene to the GLTF format + + \a sceneRoot is the root entity that will be exported. + If the sceneRoot does not have any exportable components, it is not exported itself. + + \a outDir is the directory in which the scene export is created. + + \a exportName is the name of the directory created in \c outDir that will hold + the exported scene. + + \a options contain the export options. + + Returns true if the export was carried out successfully. +*/ + bool GLTFExporter::exportScene(QEntity *sceneRoot, const QString &outDir, const QString &exportName, const QVariantHash &options) { @@ -643,18 +667,23 @@ void GLTFExporter::parseMaterials() for (auto param : parameters) { if (param->value().type() == QVariant::Color) { QColor color = param->value().value<QColor>(); - if (param->name() == MATERIAL_AMBIENT_COLOR) + if (param->name() == MATERIAL_AMBIENT_COLOR) { matInfo.colors.insert(QStringLiteral("ambient"), color); - else if (param->name() == MATERIAL_DIFFUSE_COLOR) + } else if (param->name() == MATERIAL_DIFFUSE_COLOR) { + if (matInfo.type == MaterialInfo::TypePhongAlpha) { + matInfo.values.insert(QStringLiteral("transparency"), float(color.alphaF())); + color.setAlphaF(1.0f); + } matInfo.colors.insert(QStringLiteral("diffuse"), color); - else if (param->name() == MATERIAL_SPECULAR_COLOR) + } else if (param->name() == MATERIAL_SPECULAR_COLOR) { matInfo.colors.insert(QStringLiteral("specular"), color); - else if (param->name() == MATERIAL_COOL_COLOR) // Custom Qt3D gooch + } else if (param->name() == MATERIAL_COOL_COLOR) { // Custom Qt3D gooch matInfo.colors.insert(QStringLiteral("cool"), color); - else if (param->name() == MATERIAL_WARM_COLOR) // Custom Qt3D gooch + } else if (param->name() == MATERIAL_WARM_COLOR) { // Custom Qt3D gooch matInfo.colors.insert(QStringLiteral("warm"), color); - else + } else { matInfo.colors.insert(param->name(), color); + } } else if (param->value().canConvert<QAbstractTexture *>()) { const QString urlString = textureVariantToUrl(param->value()); if (param->name() == MATERIAL_DIFFUSE_TEXTURE) diff --git a/src/quick3d/quick3drender/items/quick3dbuffer.cpp b/src/quick3d/quick3drender/items/quick3dbuffer.cpp index 362e60328..9ff349118 100644 --- a/src/quick3d/quick3drender/items/quick3dbuffer.cpp +++ b/src/quick3d/quick3drender/items/quick3dbuffer.cpp @@ -61,7 +61,7 @@ const int jsValueTypeId = qMetaTypeId<QJSValue>(); } Quick3DBuffer::Quick3DBuffer(Qt3DCore::QNode *parent) - : Qt3DRender::QBuffer(QBuffer::VertexBuffer, parent) + : Qt3DRender::QBuffer(parent) , m_engine(nullptr) , m_v4engine(nullptr) { diff --git a/src/render/backend/renderer.cpp b/src/render/backend/renderer.cpp index da4ad0ae0..1ba178a3a 100644 --- a/src/render/backend/renderer.cpp +++ b/src/render/backend/renderer.cpp @@ -64,6 +64,7 @@ #include <Qt3DRender/private/renderqueue_p.h> #include <Qt3DRender/private/shader_p.h> #include <Qt3DRender/private/buffer_p.h> +#include <Qt3DRender/private/glbuffer_p.h> #include <Qt3DRender/private/renderstateset_p.h> #include <Qt3DRender/private/technique_p.h> #include <Qt3DRender/private/renderthread_p.h> @@ -1078,8 +1079,9 @@ void Renderer::updateGLResources() for (HBuffer handle: dirtyBufferHandles) { Buffer *buffer = m_nodesManager->bufferManager()->data(handle); // Forces creation if it doesn't exit + // Also note the binding point doesn't really matter here, we just upload data if (!m_graphicsContext->hasGLBufferForBuffer(buffer)) - m_graphicsContext->glBufferForRenderBuffer(buffer); + m_graphicsContext->glBufferForRenderBuffer(buffer, GLBuffer::ArrayBuffer); // Update the glBuffer data m_graphicsContext->updateBuffer(buffer); buffer->unsetDirty(); @@ -1604,7 +1606,7 @@ void Renderer::performDraw(RenderCommand *command) } // Get GLBuffer from Buffer; - GLBuffer *indirectDrawGLBuffer = m_graphicsContext->glBufferForRenderBuffer(indirectDrawBuffer); + GLBuffer *indirectDrawGLBuffer = m_graphicsContext->glBufferForRenderBuffer(indirectDrawBuffer, GLBuffer::DrawIndirectBuffer); if (Q_UNLIKELY(indirectDrawGLBuffer == nullptr)) { qWarning() << "Invalid Indirect Draw Buffer - failed to retrieve GLBuffer"; return; diff --git a/src/render/backend/renderview.cpp b/src/render/backend/renderview.cpp index 962480f2f..07311824e 100644 --- a/src/render/backend/renderview.cpp +++ b/src/render/backend/renderview.cpp @@ -129,6 +129,7 @@ RenderView::StandardUniformsNameToTypeHash RenderView::initializeStandardUniform setters.insert(StringToInt::lookupId(QLatin1String("modelViewNormal")), ModelViewNormalMatrix); setters.insert(StringToInt::lookupId(QLatin1String("viewportMatrix")), ViewportMatrix); setters.insert(StringToInt::lookupId(QLatin1String("inverseViewportMatrix")), InverseViewportMatrix); + setters.insert(StringToInt::lookupId(QLatin1String("aspectRatio")), AspectRatio); setters.insert(StringToInt::lookupId(QLatin1String("exposure")), Exposure); setters.insert(StringToInt::lookupId(QLatin1String("gamma")), Gamma); setters.insert(StringToInt::lookupId(QLatin1String("time")), Time); @@ -200,6 +201,8 @@ UniformValue RenderView::standardUniformValue(RenderView::StandardUniform standa viewportMatrix.viewport(resolveViewport(m_viewport, m_surfaceSize)); return UniformValue(viewportMatrix.inverted()); } + case AspectRatio: + return float(m_surfaceSize.width()) / float(m_surfaceSize.height()); case Exposure: return UniformValue(m_data.m_renderCameraLens ? m_data.m_renderCameraLens->exposure() : 0.0f); case Gamma: diff --git a/src/render/backend/renderview_p.h b/src/render/backend/renderview_p.h index bc68e2a63..8c733fc3a 100644 --- a/src/render/backend/renderview_p.h +++ b/src/render/backend/renderview_p.h @@ -342,6 +342,7 @@ private: ModelViewNormalMatrix, ViewportMatrix, InverseViewportMatrix, + AspectRatio, Time, Exposure, Gamma, diff --git a/src/render/frontend/qitemmodelbuffer.cpp b/src/render/frontend/qitemmodelbuffer.cpp index 3941ac2fd..82215204a 100644 --- a/src/render/frontend/qitemmodelbuffer.cpp +++ b/src/render/frontend/qitemmodelbuffer.cpp @@ -223,7 +223,7 @@ QBuffer *QItemModelBuffer::buffer() m_attributes.clear(); m_itemStride = 0; - m_buffer = new QBuffer(QBuffer::VertexBuffer); + m_buffer = new QBuffer; // assume model will change m_buffer->setUsage(QBuffer::DynamicDraw); diff --git a/src/render/frontend/qrendersettings.cpp b/src/render/frontend/qrendersettings.cpp index 4212897ab..23f88eb10 100644 --- a/src/render/frontend/qrendersettings.cpp +++ b/src/render/frontend/qrendersettings.cpp @@ -217,8 +217,11 @@ void QRenderSettings::setActiveFrameGraph(QFrameGraphNode *activeFrameGraph) if (d->m_activeFrameGraph && activeFrameGraph) { Qt3DRender::QRenderSurfaceSelector *oldSurfaceSelector = Qt3DRender::QRenderSurfaceSelectorPrivate::find(d->m_activeFrameGraph); Qt3DRender::QRenderSurfaceSelector *newSurfaceSelector = Qt3DRender::QRenderSurfaceSelectorPrivate::find(activeFrameGraph); - if (oldSurfaceSelector && newSurfaceSelector && oldSurfaceSelector->surface()) + if (oldSurfaceSelector && newSurfaceSelector && oldSurfaceSelector->surface()) { + newSurfaceSelector->setExternalRenderTargetSize(oldSurfaceSelector->externalRenderTargetSize()); + newSurfaceSelector->setSurfacePixelRatio(oldSurfaceSelector->surfacePixelRatio()); newSurfaceSelector->setSurface(oldSurfaceSelector->surface()); + } } if (d->m_activeFrameGraph) diff --git a/src/render/geometry/buffer.cpp b/src/render/geometry/buffer.cpp index 666b5006d..3658ef335 100644 --- a/src/render/geometry/buffer.cpp +++ b/src/render/geometry/buffer.cpp @@ -51,7 +51,6 @@ namespace Render { Buffer::Buffer() : BackendNode(QBackendNode::ReadWrite) - , m_type(QBuffer::VertexBuffer) , m_usage(QBuffer::StaticDraw) , m_bufferDirty(false) , m_syncData(false) @@ -68,7 +67,6 @@ Buffer::~Buffer() void Buffer::cleanup() { - m_type = QBuffer::VertexBuffer; m_usage = QBuffer::StaticDraw; m_data.clear(); m_bufferUpdates.clear(); @@ -120,7 +118,6 @@ void Buffer::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &chang const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QBufferData>>(change); const auto &data = typedChange->data; m_data = data.data; - m_type = data.type; m_usage = data.usage; m_syncData = data.syncData; m_access = data.access; @@ -164,9 +161,6 @@ void Buffer::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Qt3DRender::QBufferUpdate updateData = propertyChange->value().value<Qt3DRender::QBufferUpdate>(); m_bufferUpdates.push_back(updateData); m_bufferDirty = true; - } else if (propertyName == QByteArrayLiteral("type")) { - m_type = static_cast<QBuffer::BufferType>(propertyChange->value().value<int>()); - m_bufferDirty = true; } else if (propertyName == QByteArrayLiteral("usage")) { m_usage = static_cast<QBuffer::UsageType>(propertyChange->value().value<int>()); m_bufferDirty = true; diff --git a/src/render/geometry/buffer_p.h b/src/render/geometry/buffer_p.h index 690d1eab6..9a171599d 100644 --- a/src/render/geometry/buffer_p.h +++ b/src/render/geometry/buffer_p.h @@ -78,7 +78,6 @@ public: void setManager(BufferManager *manager); void executeFunctor(); void updateDataFromGPUToCPU(QByteArray data); - inline QBuffer::BufferType type() const { return m_type; } inline QBuffer::UsageType usage() const { return m_usage; } inline QByteArray data() const { return m_data; } inline QVector<Qt3DRender::QBufferUpdate> &pendingBufferUpdates() { return m_bufferUpdates; } @@ -92,7 +91,6 @@ private: void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; void forceDataUpload(); - QBuffer::BufferType m_type; QBuffer::UsageType m_usage; QByteArray m_data; QVector<Qt3DRender::QBufferUpdate> m_bufferUpdates; diff --git a/src/render/geometry/qbuffer.cpp b/src/render/geometry/qbuffer.cpp index 3d524d60f..fe065929d 100644 --- a/src/render/geometry/qbuffer.cpp +++ b/src/render/geometry/qbuffer.cpp @@ -77,6 +77,8 @@ QBufferPrivate::QBufferPrivate() * \qmlproperty QBuffer::BufferType Buffer::type * * Holds the buffer type. + * + * \deprecated */ /*! @@ -220,6 +222,8 @@ QBufferPrivate::QBufferPrivate() * GL_SHADER_STORAGE_BUFFER * \value DrawIndirectBuffer * GL_DRAW_INDIRECT_BUFFER + * + * \deprecated */ /*! @@ -253,7 +257,17 @@ QBufferPrivate::QBufferPrivate() */ /*! + * Constructs a new QBuffer with \a parent. + */ +QBuffer::QBuffer(QNode *parent) + : QNode(*new QBufferPrivate(), parent) +{ +} + +/*! * Constructs a new QBuffer of buffer type \a ty with \a parent. + * + * \deprecated */ QBuffer::QBuffer(QBuffer::BufferType ty, QNode *parent) : QNode(*new QBufferPrivate(), parent) @@ -360,6 +374,8 @@ void QBuffer::setUsage(QBuffer::UsageType usage) * \property QBuffer::type * * Holds the buffer type. + * + * \deprecated */ QBuffer::BufferType QBuffer::type() const { @@ -448,7 +464,6 @@ Qt3DCore::QNodeCreatedChangeBasePtr QBuffer::createNodeCreationChange() const auto &data = creationChange->data; Q_D(const QBuffer); data.data = d->m_data; - data.type = d->m_type; data.usage = d->m_usage; data.functor = d->m_functor; data.syncData = d->m_syncData; diff --git a/src/render/geometry/qbuffer.h b/src/render/geometry/qbuffer.h index 1aa4bcc06..09fe54e10 100644 --- a/src/render/geometry/qbuffer.h +++ b/src/render/geometry/qbuffer.h @@ -95,11 +95,12 @@ public: }; Q_ENUM(AccessType) // LCOV_EXCL_LINE - explicit QBuffer(BufferType ty = QBuffer::VertexBuffer, Qt3DCore::QNode *parent = nullptr); + explicit QBuffer(Qt3DCore::QNode *parent = nullptr); + QT_DEPRECATED explicit QBuffer(BufferType ty, Qt3DCore::QNode *parent = nullptr); ~QBuffer(); UsageType usage() const; - BufferType type() const; + QT_DEPRECATED BufferType type() const; bool isSyncData() const; AccessType accessType() const; @@ -112,7 +113,7 @@ public: Q_INVOKABLE void updateData(int offset, const QByteArray &bytes); public Q_SLOTS: - void setType(BufferType type); + QT_DEPRECATED void setType(BufferType type); void setUsage(UsageType usage); void setSyncData(bool syncData); void setAccessType(AccessType access); diff --git a/src/render/geometry/qbuffer_p.h b/src/render/geometry/qbuffer_p.h index a722675ab..a342518e0 100644 --- a/src/render/geometry/qbuffer_p.h +++ b/src/render/geometry/qbuffer_p.h @@ -80,7 +80,6 @@ public: struct QBufferData { QByteArray data; - QBuffer::BufferType type; QBuffer::UsageType usage; QBufferDataGeneratorPtr functor; bool syncData; diff --git a/src/render/geometry/skeleton.cpp b/src/render/geometry/skeleton.cpp index 485069e2a..075936f37 100644 --- a/src/render/geometry/skeleton.cpp +++ b/src/render/geometry/skeleton.cpp @@ -118,7 +118,12 @@ void Skeleton::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) switch (e->type()) { case Qt3DCore::PropertyUpdated: { const auto change = qSharedPointerCast<QPropertyUpdatedChange>(e); - if (change->propertyName() == QByteArrayLiteral("source")) { + if (change->propertyName() == QByteArrayLiteral("localPoses")) { + // When the animation aspect sends us a new set of local poses, all we + // need to do is copy them into place. The existing jobs will then update + // the skinning matrix palette. + m_skeletonData.localPoses = change->value().value<QVector<Qt3DCore::Sqt>>(); + } else if (change->propertyName() == QByteArrayLiteral("source")) { Q_ASSERT(m_dataType == File); const auto source = change->value().toUrl(); if (source != m_source) { diff --git a/src/render/graphicshelpers/graphicscontext.cpp b/src/render/graphicshelpers/graphicscontext.cpp index 11132c5ed..814429504 100644 --- a/src/render/graphicshelpers/graphicscontext.cpp +++ b/src/render/graphicshelpers/graphicscontext.cpp @@ -120,22 +120,14 @@ static void logOpenGLDebugMessage(const QOpenGLDebugMessage &debugMessage) namespace { -GLBuffer::Type bufferTypeToGLBufferType(QBuffer::BufferType type) +GLBuffer::Type attributeTypeToGLBufferType(QAttribute::AttributeType type) { switch (type) { - case QBuffer::VertexBuffer: + case QAttribute::VertexAttribute: return GLBuffer::ArrayBuffer; - case QBuffer::IndexBuffer: + case QAttribute::IndexAttribute: return GLBuffer::IndexBuffer; - case QBuffer::PixelPackBuffer: - return GLBuffer::PixelPackBuffer; - case QBuffer::PixelUnpackBuffer: - return GLBuffer::PixelUnpackBuffer; - case QBuffer::UniformBuffer: - return GLBuffer::UniformBuffer; - case QBuffer::ShaderStorageBuffer: - return GLBuffer::ShaderStorageBuffer; - case QBuffer::DrawIndirectBuffer: + case QAttribute::DrawIndirectAttribute: return GLBuffer::DrawIndirectBuffer; default: Q_UNREACHABLE(); @@ -1220,7 +1212,7 @@ void GraphicsContext::setParameters(ShaderParameterPack ¶meterPack) int ssboIndex = 0; for (const BlockToSSBO b : blockToSSBOs) { Buffer *cpuBuffer = m_renderer->nodeManagers()->bufferManager()->lookupResource(b.m_bufferID); - GLBuffer *ssbo = glBufferForRenderBuffer(cpuBuffer); + GLBuffer *ssbo = glBufferForRenderBuffer(cpuBuffer, GLBuffer::ShaderStorageBuffer); bindShaderStorageBlock(shader->programId(), b.m_blockIndex, ssboIndex); // Needed to avoid conflict where the buffer would already // be bound as a VertexArray @@ -1240,7 +1232,7 @@ void GraphicsContext::setParameters(ShaderParameterPack ¶meterPack) int uboIndex = 0; for (const BlockToUBO &b : blockToUBOs) { Buffer *cpuBuffer = m_renderer->nodeManagers()->bufferManager()->lookupResource(b.m_bufferID); - GLBuffer *ubo = glBufferForRenderBuffer(cpuBuffer); + GLBuffer *ubo = glBufferForRenderBuffer(cpuBuffer, GLBuffer::UniformBuffer); bindUniformBlock(shader->programId(), b.m_blockIndex, uboIndex); // Needed to avoid conflict where the buffer would already // be bound as a VertexArray @@ -1287,7 +1279,7 @@ void GraphicsContext::enableAttribute(const VAOVertexAttribute &attr) // Bind buffer within the current VAO GLBuffer *buf = m_renderer->nodeManagers()->glBufferManager()->data(attr.bufferHandle); Q_ASSERT(buf); - bindGLBuffer(buf, attr.bufferType); + bindGLBuffer(buf, attr.attributeType); // Don't use QOpenGLShaderProgram::setAttributeBuffer() because of QTBUG-43199. // Use the introspection data and set the attribute explicitly @@ -1437,7 +1429,7 @@ void GraphicsContext::specifyAttribute(const Attribute *attribute, const GLint attributeDataType = glDataTypeFromAttributeDataType(attribute->vertexBaseType()); const HGLBuffer glBufferHandle = m_renderer->nodeManagers()->glBufferManager()->lookupHandle(buffer->peerId()); Q_ASSERT(!glBufferHandle.isNull()); - const GLBuffer::Type bufferType = bufferTypeToGLBufferType(buffer->type()); + const GLBuffer::Type attributeType = attributeTypeToGLBufferType(attribute->attributeType()); int typeSize = 0; int attrCount = 0; @@ -1457,7 +1449,7 @@ void GraphicsContext::specifyAttribute(const Attribute *attribute, for (int i = 0; i < attrCount; i++) { VAOVertexAttribute attr; attr.bufferHandle = glBufferHandle; - attr.bufferType = bufferType; + attr.attributeType = attributeType; attr.location = location + i; attr.dataType = attributeDataType; attr.byteOffset = attribute->byteOffset() + (i * attrCount * typeSize); @@ -1476,9 +1468,7 @@ void GraphicsContext::specifyAttribute(const Attribute *attribute, void GraphicsContext::specifyIndices(Buffer *buffer) { - Q_ASSERT(buffer->type() == QBuffer::IndexBuffer); - - GLBuffer *buf = glBufferForRenderBuffer(buffer); + GLBuffer *buf = glBufferForRenderBuffer(buffer, GLBuffer::IndexBuffer); if (!bindGLBuffer(buf, GLBuffer::IndexBuffer)) qCWarning(Backend) << Q_FUNC_INFO << "binding index buffer failed"; @@ -1585,14 +1575,14 @@ void GraphicsContext::memoryBarrier(QMemoryBarrier::Operations barriers) m_glHelper->memoryBarrier(barriers); } -GLBuffer *GraphicsContext::glBufferForRenderBuffer(Buffer *buf) +GLBuffer *GraphicsContext::glBufferForRenderBuffer(Buffer *buf, GLBuffer::Type type) { if (!m_renderBufferHash.contains(buf->peerId())) - m_renderBufferHash.insert(buf->peerId(), createGLBufferFor(buf)); + m_renderBufferHash.insert(buf->peerId(), createGLBufferFor(buf, type)); return m_renderer->nodeManagers()->glBufferManager()->data(m_renderBufferHash.value(buf->peerId())); } -HGLBuffer GraphicsContext::createGLBufferFor(Buffer *buffer) +HGLBuffer GraphicsContext::createGLBufferFor(Buffer *buffer, GLBuffer::Type type) { GLBuffer *b = m_renderer->nodeManagers()->glBufferManager()->getOrCreateResource(buffer->peerId()); // b.setUsagePattern(static_cast<QOpenGLBuffer::UsagePattern>(buffer->usage())); @@ -1600,7 +1590,7 @@ HGLBuffer GraphicsContext::createGLBufferFor(Buffer *buffer) if (!b->create(this)) qCWarning(Render::Io) << Q_FUNC_INFO << "buffer creation failed"; - if (!bindGLBuffer(b, bufferTypeToGLBufferType(buffer->type()))) + if (!bindGLBuffer(b, type)) qCWarning(Render::Io) << Q_FUNC_INFO << "buffer binding failed"; return m_renderer->nodeManagers()->glBufferManager()->lookupHandle(buffer->peerId()); @@ -1621,7 +1611,7 @@ bool GraphicsContext::bindGLBuffer(GLBuffer *buffer, GLBuffer::Type type) void GraphicsContext::uploadDataToGLBuffer(Buffer *buffer, GLBuffer *b, bool releaseBuffer) { - if (!bindGLBuffer(b, bufferTypeToGLBufferType(buffer->type()))) + if (!bindGLBuffer(b, GLBuffer::ArrayBuffer)) // We're uploading, the type doesn't matter here qCWarning(Render::Io) << Q_FUNC_INFO << "buffer bind failed"; // If the buffer is dirty (hence being called here) // there are two possible cases @@ -1663,15 +1653,14 @@ void GraphicsContext::uploadDataToGLBuffer(Buffer *buffer, GLBuffer *b, bool rel if (releaseBuffer) { b->release(this); - if (bufferTypeToGLBufferType(buffer->type()) == GLBuffer::ArrayBuffer) - m_boundArrayBuffer = nullptr; + m_boundArrayBuffer = nullptr; } qCDebug(Render::Io) << "uploaded buffer size=" << buffer->data().size(); } QByteArray GraphicsContext::downloadDataFromGLBuffer(Buffer *buffer, GLBuffer *b) { - if (!bindGLBuffer(b, bufferTypeToGLBufferType(buffer->type()))) + if (!bindGLBuffer(b, GLBuffer::ArrayBuffer)) // We're downloading, the type doesn't matter here qCWarning(Render::Io) << Q_FUNC_INFO << "buffer bind failed"; QByteArray data = b->download(this, buffer->data().size()); diff --git a/src/render/graphicshelpers/graphicscontext_p.h b/src/render/graphicshelpers/graphicscontext_p.h index 21ec90c58..1b9438a6f 100644 --- a/src/render/graphicshelpers/graphicscontext_p.h +++ b/src/render/graphicshelpers/graphicscontext_p.h @@ -188,7 +188,7 @@ public: * @param buf * @return */ - GLBuffer *glBufferForRenderBuffer(Buffer *buf); + GLBuffer *glBufferForRenderBuffer(Buffer *buf, GLBuffer::Type type); /** * @brief activateTexture - make a texture active on a hardware unit @@ -270,7 +270,7 @@ private: void bindFrameBufferAttachmentHelper(GLuint fboId, const AttachmentPack &attachments); void activateDrawBuffers(const AttachmentPack &attachments); - HGLBuffer createGLBufferFor(Buffer *buffer); + HGLBuffer createGLBufferFor(Buffer *buffer, GLBuffer::Type type); void uploadDataToGLBuffer(Buffer *buffer, GLBuffer *b, bool releaseBuffer = false); QByteArray downloadDataFromGLBuffer(Buffer *buffer, GLBuffer *b); bool bindGLBuffer(GLBuffer *buffer, GLBuffer::Type type); @@ -331,7 +331,7 @@ private: struct VAOVertexAttribute { HGLBuffer bufferHandle; - GLBuffer::Type bufferType; + GLBuffer::Type attributeType; int location; GLint dataType; uint byteOffset; diff --git a/src/render/materialsystem/prototypes/default.json b/src/render/materialsystem/prototypes/default.json index 429c435f4..9f16b0f53 100644 --- a/src/render/materialsystem/prototypes/default.json +++ b/src/render/materialsystem/prototypes/default.json @@ -107,7 +107,7 @@ "major": 2, "minor": 0 }, - "substitution": "gl_fragColor = $fragColor;" + "substitution": "gl_FragColor = $fragColor;" }, { "format": { @@ -377,6 +377,15 @@ "rules": [ { "format": { + "api": "OpenGLES", + "major": 2, + "minor": 0 + }, + "substitution": "highp mat3 $matrix = calcWorldSpaceToTangentSpaceMatrix($worldNormal, $worldTangent);", + "headerSnippets": [ "#pragma include :/shaders/es2/coordinatesystems.inc" ] + }, + { + "format": { "api": "OpenGLCoreProfile", "major": 3, "minor": 0 @@ -386,6 +395,40 @@ } ] }, + "phongFunction": { + "inputs": [ + "ambient", + "diffuse", + "specular", + "shininess", + "worldPosition", + "worldView", + "worldNormal" + ], + "outputs": [ + "outputColor" + ], + "rules": [ + { + "format": { + "api": "OpenGLES", + "major": 2, + "minor": 0 + }, + "substitution": "highp vec4 $outputColor = phongFunction($ambient, $diffuse, $specular, $shininess, $worldPosition, $worldView, $worldNormal);", + "headerSnippets": [ "#pragma include :/shaders/es2/phong.inc.frag" ] + }, + { + "format": { + "api": "OpenGLCoreProfile", + "major": 3, + "minor": 0 + }, + "substitution": "vec4 $outputColor = phongFunction($ambient, $diffuse, $specular, $shininess, $worldPosition, $worldView, $worldNormal);", + "headerSnippets": [ "#pragma include :/shaders/gl3/phong.inc.frag" ] + } + ] + }, "metalRoughFunction": { "inputs": [ "baseColor", diff --git a/src/render/texture/gltexture.cpp b/src/render/texture/gltexture.cpp index 2a35a6f7e..11cc1544f 100644 --- a/src/render/texture/gltexture.cpp +++ b/src/render/texture/gltexture.cpp @@ -208,6 +208,7 @@ QOpenGLTexture* GLTexture::getOrCreateGLTexture() // need to (re-)upload texture data? if (needUpload && !texturedDataInvalid) { uploadGLTextureData(); + setDirtyFlag(TextureData, false); } // need to set texture parameters? diff --git a/tests/auto/animation/animation.pro b/tests/auto/animation/animation.pro index eff1a4779..c97b07923 100644 --- a/tests/auto/animation/animation.pro +++ b/tests/auto/animation/animation.pro @@ -38,5 +38,6 @@ qtConfig(private_tests) { animationutils \ qabstractanimation \ clock \ - skeleton + skeleton \ + findrunningclipanimatorsjob } diff --git a/tests/auto/animation/animationutils/tst_animationutils.cpp b/tests/auto/animation/animationutils/tst_animationutils.cpp index c75ae8e6a..1e55a29b5 100644 --- a/tests/auto/animation/animationutils/tst_animationutils.cpp +++ b/tests/auto/animation/animationutils/tst_animationutils.cpp @@ -149,6 +149,7 @@ public: auto channelMappingId = Qt3DCore::QNodeId::createId(); ChannelMapping *channelMapping = handler->channelMappingManager()->getOrCreateResource(channelMappingId); setPeerId(channelMapping, channelMappingId); + channelMapping->setHandler(handler); channelMapping->setTargetId(targetId); channelMapping->setProperty(property); channelMapping->setPropertyName(propertyName); @@ -164,6 +165,7 @@ public: auto channelMappingId = Qt3DCore::QNodeId::createId(); ChannelMapping *channelMapping = handler->channelMappingManager()->getOrCreateResource(channelMappingId); setPeerId(channelMapping, channelMappingId); + channelMapping->setHandler(handler); channelMapping->setSkeletonId(skeletonId); channelMapping->setMappingType(ChannelMapping::SkeletonMappingType); return channelMapping; @@ -273,88 +275,20 @@ private Q_SLOTS: { QTest::addColumn<Handler *>("handler"); QTest::addColumn<QVector<ChannelMapping *>>("channelMappings"); - QTest::addColumn<ChannelMapper *>("channelMapper"); - QTest::addColumn<AnimationClip *>("clip"); - QTest::addColumn<QVector<MappingData>>("expectedMappingData"); - - auto handler = new Handler; - auto channelMapping = createChannelMapping(handler, - QLatin1String("Location"), - Qt3DCore::QNodeId::createId(), - QLatin1String("translation"), - "translation", - static_cast<int>(QVariant::Vector3D)); - QVector<ChannelMapping *> channelMappings; - channelMappings.push_back(channelMapping); - - // ... a channel mapper... - auto channelMapper = createChannelMapper(handler, QVector<Qt3DCore::QNodeId>() << channelMapping->peerId()); - - // ...and an animation clip - auto clip = createAnimationClipLoader(handler, QUrl("qrc:/clip1.json")); - - QVector<MappingData> mappingData; - MappingData mapping; - mapping.targetId = channelMapping->targetId(); - mapping.propertyName = channelMapping->propertyName(); // Location - mapping.type = channelMapping->type(); - mapping.channelIndices = QVector<int>() << 0 << 1 << 2; // Location X, Y, Z - mappingData.push_back(mapping); - - QTest::newRow("clip1.json") << handler - << channelMappings - << channelMapper - << clip - << mappingData; - } - - void checkBuildPropertyMappings() - { - // GIVEN - QFETCH(Handler *, handler); - QFETCH(QVector<ChannelMapping *>, channelMappings); - QFETCH(ChannelMapper *, channelMapper); - QFETCH(AnimationClip *, clip); - QFETCH(QVector<MappingData>, expectedMappingData); - - // WHEN - // Build the mapping data for the above configuration - QVector<MappingData> mappingData = buildPropertyMappings(handler, clip, channelMapper); - - // THEN - QCOMPARE(mappingData.size(), expectedMappingData.size()); - for (int i = 0; i < mappingData.size(); ++i) { - const auto mapping = mappingData[i]; - const auto expectedMapping = expectedMappingData[i]; - - QCOMPARE(mapping.targetId, expectedMapping.targetId); - QCOMPARE(mapping.propertyName, expectedMapping.propertyName); - QCOMPARE(mapping.type, expectedMapping.type); - QCOMPARE(mapping.channelIndices.size(), expectedMapping.channelIndices.size()); - for (int j = 0; j < mapping.channelIndices.size(); ++j) { - QCOMPARE(mapping.channelIndices[j], expectedMapping.channelIndices[j]); - } - } - - // Cleanup - delete handler; - } - - void checkBuildPropertyMappings2_data() - { - QTest::addColumn<QVector<ChannelMapping *>>("channelMappings"); QTest::addColumn<QVector<ChannelNameAndType>>("channelNamesAndTypes"); QTest::addColumn<QVector<ComponentIndices>>("channelComponentIndices"); QTest::addColumn<QVector<MappingData>>("expectedResults"); // Single ChannelMapping { - auto channelMapping = new ChannelMapping(); - channelMapping->setChannelName("Location"); - channelMapping->setTargetId(Qt3DCore::QNodeId::createId()); - channelMapping->setProperty(QLatin1String("translation")); - channelMapping->setPropertyName("translation"); - channelMapping->setType(static_cast<int>(QVariant::Vector3D)); + Handler *handler = new Handler(); + + auto channelMapping = createChannelMapping(handler, + QLatin1String("Location"), + Qt3DCore::QNodeId::createId(), + QLatin1String("translation"), + "translation", + static_cast<int>(QVariant::Vector3D)); QVector<ChannelMapping *> channelMappings = { channelMapping }; @@ -390,6 +324,7 @@ private Q_SLOTS: QVector<MappingData> expectedResults = { expectedMapping }; QTest::newRow("single mapping") + << handler << channelMappings << channelNamesAndTypes << channelComponentIndices @@ -398,40 +333,42 @@ private Q_SLOTS: // Multiple ChannelMappings { - auto locationMapping = new ChannelMapping(); - locationMapping->setChannelName("Location"); - locationMapping->setTargetId(Qt3DCore::QNodeId::createId()); - locationMapping->setProperty(QLatin1String("translation")); - locationMapping->setPropertyName("translation"); - locationMapping->setType(static_cast<int>(QVariant::Vector3D)); - - auto metalnessMapping = new ChannelMapping(); - metalnessMapping->setChannelName("Metalness"); - metalnessMapping->setTargetId(Qt3DCore::QNodeId::createId()); - metalnessMapping->setProperty(QLatin1String("metalness")); - metalnessMapping->setPropertyName("metalness"); - metalnessMapping->setType(static_cast<int>(QVariant::Double)); - - auto baseColorMapping = new ChannelMapping(); - baseColorMapping->setChannelName("BaseColor"); - baseColorMapping->setTargetId(Qt3DCore::QNodeId::createId()); - baseColorMapping->setProperty(QLatin1String("baseColor")); - baseColorMapping->setPropertyName("baseColor"); - baseColorMapping->setType(static_cast<int>(QVariant::Vector3D)); - - auto roughnessMapping = new ChannelMapping(); - roughnessMapping->setChannelName("Roughness"); - roughnessMapping->setTargetId(Qt3DCore::QNodeId::createId()); - roughnessMapping->setProperty(QLatin1String("roughness")); - roughnessMapping->setPropertyName("roughness"); - roughnessMapping->setType(static_cast<int>(QVariant::Double)); - - auto rotationMapping = new ChannelMapping(); - rotationMapping->setChannelName("Rotation"); - rotationMapping->setTargetId(Qt3DCore::QNodeId::createId()); - rotationMapping->setProperty(QLatin1String("rotation")); - rotationMapping->setPropertyName("rotation"); - rotationMapping->setType(static_cast<int>(QVariant::Quaternion)); + Handler *handler = new Handler(); + + auto locationMapping = createChannelMapping(handler, + QLatin1String("Location"), + Qt3DCore::QNodeId::createId(), + QLatin1String("translation"), + "translation", + static_cast<int>(QVariant::Vector3D)); + + auto metalnessMapping = createChannelMapping(handler, + QLatin1String("Metalness"), + Qt3DCore::QNodeId::createId(), + QLatin1String("metalness"), + "metalness", + static_cast<int>(QVariant::Double)); + + auto baseColorMapping = createChannelMapping(handler, + QLatin1String("BaseColor"), + Qt3DCore::QNodeId::createId(), + QLatin1String("baseColor"), + "baseColor", + static_cast<int>(QVariant::Vector3D)); + + auto roughnessMapping = createChannelMapping(handler, + QLatin1String("Roughness"), + Qt3DCore::QNodeId::createId(), + QLatin1String("roughness"), + "roughness", + static_cast<int>(QVariant::Double)); + + auto rotationMapping = createChannelMapping(handler, + QLatin1String("Rotation"), + Qt3DCore::QNodeId::createId(), + QLatin1String("rotation"), + "rotation", + static_cast<int>(QVariant::Quaternion)); QVector<ChannelMapping *> channelMappings = { locationMapping, metalnessMapping, @@ -500,6 +437,77 @@ private Q_SLOTS: expectedRotationMapping }; QTest::newRow("multiple mappings") + << handler + << channelMappings + << channelNamesAndTypes + << channelComponentIndices + << expectedResults; + } + + // Single skeleton mapping + { + Handler *handler = new Handler(); + const int jointCount = 4; + auto skeleton = createSkeleton(handler, jointCount); + auto channelMapping = createChannelMapping(handler, skeleton->peerId()); + + QVector<ChannelMapping *> channelMappings = { channelMapping }; + + // Create a few channels in the format description + QVector<ChannelNameAndType> channelNamesAndTypes; + for (int i = 0; i < jointCount; ++i) { + channelNamesAndTypes.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D), i }); + channelNamesAndTypes.push_back({ QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion), i }); + channelNamesAndTypes.push_back({ QLatin1String("Scale"), static_cast<int>(QVariant::Vector3D), i }); + } + + // And the matching indices + QVector<ComponentIndices> channelComponentIndices; + channelComponentIndices.push_back({ 0, 1, 2 }); + channelComponentIndices.push_back({ 3, 4, 5, 6 }); + channelComponentIndices.push_back({ 7, 8, 9 }); + + channelComponentIndices.push_back({ 10, 11, 12 }); + channelComponentIndices.push_back({ 13, 14, 15, 16 }); + channelComponentIndices.push_back({ 17, 18, 19 }); + + channelComponentIndices.push_back({ 20, 21, 22 }); + channelComponentIndices.push_back({ 23, 24, 25, 26 }); + channelComponentIndices.push_back({ 27, 28, 29 }); + + channelComponentIndices.push_back({ 30, 31, 32 }); + channelComponentIndices.push_back({ 33, 34, 35, 36 }); + channelComponentIndices.push_back({ 37, 38, 39 }); + + QVector<MappingData> expectedResults; + int componentIndicesIndex = 0; + for (int i = 0; i < jointCount; ++i) { + MappingData locationMapping; + locationMapping.targetId = channelMapping->skeletonId(); + locationMapping.propertyName = "translation"; + locationMapping.type = static_cast<int>(QVariant::Vector3D); + locationMapping.channelIndices = channelComponentIndices[componentIndicesIndex++]; + locationMapping.jointIndex = i; + + MappingData rotationMapping; + rotationMapping.targetId = channelMapping->skeletonId(); + rotationMapping.propertyName = "rotation"; + rotationMapping.type = static_cast<int>(QVariant::Quaternion); + rotationMapping.channelIndices = channelComponentIndices[componentIndicesIndex++]; + rotationMapping.jointIndex = i; + + MappingData scaleMapping; + scaleMapping.targetId = channelMapping->skeletonId(); + scaleMapping.propertyName = "scale"; + scaleMapping.type = static_cast<int>(QVariant::Vector3D); + scaleMapping.channelIndices = channelComponentIndices[componentIndicesIndex++]; + scaleMapping.jointIndex = i; + + expectedResults << locationMapping << rotationMapping << scaleMapping; + } + + QTest::newRow("single skeleton mapping") + << handler << channelMappings << channelNamesAndTypes << channelComponentIndices @@ -507,9 +515,10 @@ private Q_SLOTS: } } - void checkBuildPropertyMappings2() + void checkBuildPropertyMappings() { // GIVEN + QFETCH(Handler *, handler); QFETCH(QVector<ChannelMapping *>, channelMappings); QFETCH(QVector<ChannelNameAndType>, channelNamesAndTypes); QFETCH(QVector<ComponentIndices>, channelComponentIndices); @@ -527,6 +536,7 @@ private Q_SLOTS: const auto expectedMapping = expectedResults[i]; QCOMPARE(actualMapping.targetId, expectedMapping.targetId); + QCOMPARE(actualMapping.jointIndex, expectedMapping.jointIndex); QCOMPARE(actualMapping.propertyName, expectedMapping.propertyName); QCOMPARE(actualMapping.type, expectedMapping.type); QCOMPARE(actualMapping.channelIndices.size(), expectedMapping.channelIndices.size()); @@ -534,6 +544,9 @@ private Q_SLOTS: QCOMPARE(actualMapping.channelIndices[j], expectedMapping.channelIndices[j]); } } + + // Cleanup + delete handler; } void checkLocalTimeFromGlobalTime_data() @@ -2088,6 +2101,18 @@ private Q_SLOTS: QTest::newRow("simple lerp") << handler << lerp->peerId() << expectedIds; } + + { + Handler *handler = new Handler; + + const auto value1 = createClipBlendValue(handler); + const auto clip1Id = Qt3DCore::QNodeId::createId(); + value1->setClipId(clip1Id); + + QVector<Qt3DCore::QNodeId> expectedIds = { value1->peerId() }; + + QTest::newRow("value only") << handler << value1->peerId() << expectedIds; + } } void checkGatherValueNodesToEvaluate() @@ -2694,8 +2719,8 @@ private Q_SLOTS: clip->setSource(QUrl("qrc:/clip3.json")); clip->loadAnimation(); - ComponentIndices expectedResults = { 0, 1, 2, 3, // Rotation - 4, 5, 6, // Location + ComponentIndices expectedResults = { 0, 1, 3, 2, // Rotation (y/z swapped in clip3.json) + 4, 6, 5, // Location (y/z swapped in clip3.json) 7, 8, 9, // Base Color 10, // Metalness 11 }; // Roughness @@ -2724,8 +2749,8 @@ private Q_SLOTS: clip->setSource(QUrl("qrc:/clip3.json")); clip->loadAnimation(); - ComponentIndices expectedResults = { 4, 5, 6, // Location - 0, 1, 2, 3, // Rotation + ComponentIndices expectedResults = { 4, 6, 5, // Location (y/z swapped in clip3.json) + 0, 1, 3, 2, // Rotation (y/z swapped in clip3.json) 7, 8, 9, // Base Color 10, // Metalness 11 }; // Roughness @@ -2754,8 +2779,8 @@ private Q_SLOTS: clip->setSource(QUrl("qrc:/clip3.json")); clip->loadAnimation(); - ComponentIndices expectedResults = { 0, 1, 2, 3, // Rotation - 4, 5, 6, // Location + ComponentIndices expectedResults = { 0, 1, 3, 2, // Rotation (y/z swapped in clip3.json) + 4, 6, 5, // Location (y/z swapped in clip3.json) -1, -1, -1, // Albedo (missing from clip) 10, // Metalness 11 }; // Roughness @@ -2784,8 +2809,8 @@ private Q_SLOTS: clip->setSource(QUrl("qrc:/clip3.json")); clip->loadAnimation(); - ComponentIndices expectedResults = { 4, 5, 6, // Location - 0, 1, 2, 3, // Rotation + ComponentIndices expectedResults = { 4, 6, 5, // Location (y/z swapped in clip3.json) + 0, 1, 3, 2, // Rotation (y/z swapped in clip3.json) -1, -1, -1, // Albedo (missing from clip) 10, // Metalness 11 }; // Roughness @@ -2825,17 +2850,17 @@ private Q_SLOTS: clip->setSource(QUrl("qrc:/clip5.json")); clip->loadAnimation(); - ComponentIndices expectedResults = { 4, 5, 6, // Location, joint 0 - 0, 1, 2, 3, // Rotation, joint 0 + ComponentIndices expectedResults = { 4, 6, 5, // Location, joint 0 (y/z swapped in clip5.json) + 0, 1, 3, 2, // Rotation, joint 0 (y/z swapped in clip5.json) 7, 8, 9, // Scale, joint 0 - 14, 15, 16, // Location, joint 1 - 10, 11, 12, 13, // Rotation, joint 1 + 14, 16, 15, // Location, joint 1 (y/z swapped in clip5.json) + 10, 11, 13, 12, // Rotation, joint 1 (y/z swapped in clip5.json) 17, 18, 19, // Scale, joint 1 - 24, 25, 26, // Location, joint 2 - 20, 21, 22, 23, // Rotation, joint 2 + 24, 26, 25, // Location, joint 2 (y/z swapped in clip5.json) + 20, 21, 23, 22, // Rotation, joint 2 (y/z swapped in clip5.json) 27, 28, 29, // Scale, joint 2 - 34, 35, 36, // Location, joint 3 - 30, 31, 32, 33, // Rotation, joint 3 + 34, 36, 35, // Location, joint 3 (y/z swapped in clip5.json) + 30, 31, 33, 32, // Rotation, joint 3 (y/z swapped in clip5.json) 37, 38, 39 }; // Scale, joint 3 QTest::newRow("skeleton (SQT), 4 joints") diff --git a/tests/auto/animation/channelmapper/tst_channelmapper.cpp b/tests/auto/animation/channelmapper/tst_channelmapper.cpp index 4dcb52aef..446e1a0c5 100644 --- a/tests/auto/animation/channelmapper/tst_channelmapper.cpp +++ b/tests/auto/animation/channelmapper/tst_channelmapper.cpp @@ -30,6 +30,8 @@ #include <qbackendnodetester.h> #include <Qt3DAnimation/private/handler_p.h> #include <Qt3DAnimation/private/channelmapper_p.h> +#include <Qt3DAnimation/private/channelmapping_p.h> +#include <Qt3DAnimation/private/managers_p.h> #include <Qt3DAnimation/qchannelmapper.h> #include <Qt3DAnimation/qchannelmapping.h> #include <Qt3DAnimation/private/qchannelmapper_p.h> @@ -116,13 +118,40 @@ private Q_SLOTS: // WHEN Qt3DAnimation::QChannelMapping mapping; const Qt3DCore::QNodeId mappingId = mapping.id(); - const auto nodeAddedChange = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), &mapping); + Qt3DAnimation::Animation::ChannelMapping *backendMapping + = handler.channelMappingManager()->getOrCreateResource(mappingId); + backendMapping->setHandler(&handler); + simulateInitialization(&mapping, backendMapping); + + auto nodeAddedChange = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), &mapping); nodeAddedChange->setPropertyName("mappings"); backendMapper.sceneChangeEvent(nodeAddedChange); // THEN QCOMPARE(backendMapper.mappingIds().size(), 1); QCOMPARE(backendMapper.mappingIds().first(), mappingId); + QCOMPARE(backendMapper.mappings().size(), 1); + QCOMPARE(backendMapper.mappings().first(), backendMapping); + + // WHEN + Qt3DAnimation::QChannelMapping mapping2; + const Qt3DCore::QNodeId mappingId2 = mapping2.id(); + Qt3DAnimation::Animation::ChannelMapping *backendMapping2 + = handler.channelMappingManager()->getOrCreateResource(mappingId2); + backendMapping2->setHandler(&handler); + simulateInitialization(&mapping2, backendMapping2); + + nodeAddedChange = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), &mapping2); + nodeAddedChange->setPropertyName("mappings"); + backendMapper.sceneChangeEvent(nodeAddedChange); + + // THEN + QCOMPARE(backendMapper.mappingIds().size(), 2); + QCOMPARE(backendMapper.mappingIds().first(), mappingId); + QCOMPARE(backendMapper.mappingIds().last(), mappingId2); + QCOMPARE(backendMapper.mappings().size(), 2); + QCOMPARE(backendMapper.mappings().first(), backendMapping); + QCOMPARE(backendMapper.mappings().last(), backendMapping2); // WHEN const auto nodeRemovedChange = Qt3DCore::QPropertyNodeRemovedChangePtr::create(Qt3DCore::QNodeId(), &mapping); @@ -130,7 +159,10 @@ private Q_SLOTS: backendMapper.sceneChangeEvent(nodeRemovedChange); // THEN - QCOMPARE(backendMapper.mappingIds().size(), 0); + QCOMPARE(backendMapper.mappingIds().size(), 1); + QCOMPARE(backendMapper.mappingIds().first(), mappingId2); + QCOMPARE(backendMapper.mappings().size(), 1); + QCOMPARE(backendMapper.mappings().first(), backendMapping2); } }; diff --git a/tests/auto/animation/clipblendvalue/tst_clipblendvalue.cpp b/tests/auto/animation/clipblendvalue/tst_clipblendvalue.cpp index 6fe2846b8..fcbc167ca 100644 --- a/tests/auto/animation/clipblendvalue/tst_clipblendvalue.cpp +++ b/tests/auto/animation/clipblendvalue/tst_clipblendvalue.cpp @@ -137,8 +137,7 @@ private Q_SLOTS: QVector<Qt3DCore::QNodeId> actualIds = clipNode.currentDependencyIds(); // THEN - QCOMPARE(actualIds.size(), 1); - QCOMPARE(actualIds[0], clipId); + QCOMPARE(actualIds.size(), 0); // WHEN auto anotherClipId = Qt3DCore::QNodeId::createId(); @@ -146,8 +145,7 @@ private Q_SLOTS: actualIds = clipNode.currentDependencyIds(); // THEN - QCOMPARE(actualIds.size(), 1); - QCOMPARE(actualIds[0], anotherClipId); + QCOMPARE(actualIds.size(), 0); } void checkDuration() diff --git a/tests/auto/animation/findrunningclipanimatorsjob/clip1.json b/tests/auto/animation/findrunningclipanimatorsjob/clip1.json new file mode 100644 index 000000000..a2ad365a8 --- /dev/null +++ b/tests/auto/animation/findrunningclipanimatorsjob/clip1.json @@ -0,0 +1,114 @@ +{ + "animations": [ + { + "animationName": "CubeAction", + "channels": [ + { + "channelComponents": [ + { + "channelComponentName": "Location X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 5.0 + ], + "leftHandle": [ + 1.4985717137654622, + 5.0 + ], + "rightHandle": [ + 3.4180949529012046, + 5.0 + ] + } + ] + }, + { + "channelComponentName": "Location Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Location Z", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + } + ], + "channelName": "Location" + } + ] + } + ] +} + diff --git a/tests/auto/animation/findrunningclipanimatorsjob/findrunningclipanimatorsjob.pro b/tests/auto/animation/findrunningclipanimatorsjob/findrunningclipanimatorsjob.pro new file mode 100644 index 000000000..f81b95dcd --- /dev/null +++ b/tests/auto/animation/findrunningclipanimatorsjob/findrunningclipanimatorsjob.pro @@ -0,0 +1,15 @@ +TEMPLATE = app + +TARGET = tst_findrunningclipanimatorsjob + +QT += core-private 3dcore 3dcore-private 3danimation 3danimation-private testlib + +CONFIG += testcase + +SOURCES += \ + tst_findrunningclipanimatorsjob.cpp + +include(../../core/common/common.pri) + +RESOURCES += \ + findrunningclipanimatorsjob.qrc diff --git a/tests/auto/animation/findrunningclipanimatorsjob/findrunningclipanimatorsjob.qrc b/tests/auto/animation/findrunningclipanimatorsjob/findrunningclipanimatorsjob.qrc new file mode 100644 index 000000000..72234ec64 --- /dev/null +++ b/tests/auto/animation/findrunningclipanimatorsjob/findrunningclipanimatorsjob.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/"> + <file>clip1.json</file> + </qresource> +</RCC> diff --git a/tests/auto/animation/findrunningclipanimatorsjob/tst_findrunningclipanimatorsjob.cpp b/tests/auto/animation/findrunningclipanimatorsjob/tst_findrunningclipanimatorsjob.cpp new file mode 100644 index 000000000..79d18b7cf --- /dev/null +++ b/tests/auto/animation/findrunningclipanimatorsjob/tst_findrunningclipanimatorsjob.cpp @@ -0,0 +1,204 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <Qt3DAnimation/qanimationcliploader.h> +#include <Qt3DAnimation/qclipanimator.h> +#include <Qt3DAnimation/qchannelmapper.h> +#include <Qt3DAnimation/qchannelmapping.h> +#include <Qt3DAnimation/private/clipanimator_p.h> +#include <Qt3DAnimation/private/channelmapper_p.h> +#include <Qt3DAnimation/private/channelmapping_p.h> +#include <Qt3DAnimation/private/findrunningclipanimatorsjob_p.h> +#include <Qt3DAnimation/private/handler_p.h> +#include <Qt3DAnimation/private/managers_p.h> +#include <Qt3DCore/private/qnode_p.h> +#include <Qt3DCore/private/qscene_p.h> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/private/qbackendnode_p.h> +#include <qbackendnodetester.h> +#include <testpostmanarbiter.h> + +using namespace Qt3DAnimation::Animation; + +Q_DECLARE_METATYPE(Qt3DAnimation::Animation::Handler*) +Q_DECLARE_METATYPE(QVector<Qt3DAnimation::Animation::HClipAnimator>) + +typedef QHash<ClipAnimator*, QVector<Qt3DAnimation::Animation::MappingData>> MappingDataResults; +Q_DECLARE_METATYPE(MappingDataResults) + +class tst_FindRunningClipAnimatorsJob: public Qt3DCore::QBackendNodeTester +{ + Q_OBJECT +public: + ChannelMapping *createChannelMapping(Handler *handler, + const QString &channelName, + const Qt3DCore::QNodeId targetId, + const QString &property, + const char *propertyName, + int type) + { + auto channelMappingId = Qt3DCore::QNodeId::createId(); + ChannelMapping *channelMapping = handler->channelMappingManager()->getOrCreateResource(channelMappingId); + setPeerId(channelMapping, channelMappingId); + channelMapping->setHandler(handler); + channelMapping->setTargetId(targetId); + channelMapping->setProperty(property); + channelMapping->setPropertyName(propertyName); + channelMapping->setChannelName(channelName); + channelMapping->setType(type); + return channelMapping; + } + + ChannelMapper *createChannelMapper(Handler *handler, + const QVector<Qt3DCore::QNodeId> &mappingIds) + { + auto channelMapperId = Qt3DCore::QNodeId::createId(); + ChannelMapper *channelMapper = handler->channelMapperManager()->getOrCreateResource(channelMapperId); + setPeerId(channelMapper, channelMapperId); + channelMapper->setHandler(handler); + channelMapper->setMappingIds(mappingIds); + return channelMapper; + } + + AnimationClip *createAnimationClipLoader(Handler *handler, + const QUrl &source) + { + auto clipId = Qt3DCore::QNodeId::createId(); + AnimationClip *clip = handler->animationClipLoaderManager()->getOrCreateResource(clipId); + setPeerId(clip, clipId); + clip->setHandler(handler); + clip->setDataType(AnimationClip::File); + clip->setSource(source); + clip->loadAnimation(); + return clip; + } + + ClipAnimator *createClipAnimator(Handler *handler, + qint64 globalStartTimeNS, + int loops) + { + auto animatorId = Qt3DCore::QNodeId::createId(); + ClipAnimator *animator = handler->clipAnimatorManager()->getOrCreateResource(animatorId); + setPeerId(animator, animatorId); + animator->setHandler(handler); + animator->setStartTime(globalStartTimeNS); + animator->setLoops(loops); + return animator; + } + +private Q_SLOTS: + void checkJob_data() + { + QTest::addColumn<Handler *>("handler"); + QTest::addColumn<QVector<HClipAnimator>>("dirtyClipAnimators"); + QTest::addColumn<MappingDataResults>("expectedResults"); + + Handler *handler; + AnimationClip *clip; + ClipAnimator *animator; + QVector<HClipAnimator> dirtyClipAnimators; + ChannelMapper *channelMapper; + MappingDataResults expectedResults; + + { + handler = new Handler(); + clip = createAnimationClipLoader(handler, QUrl("qrc:/clip1.json")); + + const qint64 globalStartTimeNS = 0; + const int loops = 1; + animator = createClipAnimator(handler, globalStartTimeNS, loops); + animator->setClipId(clip->peerId()); + dirtyClipAnimators = (QVector<HClipAnimator>() + << handler->clipAnimatorManager()->getOrAcquireHandle(animator->peerId())); + + auto channelMapping = createChannelMapping(handler, + QLatin1String("Location"), + Qt3DCore::QNodeId::createId(), + QLatin1String("translation"), + "translation", + static_cast<int>(QVariant::Vector3D)); + QVector<ChannelMapping *> channelMappings; + channelMappings.push_back(channelMapping); + + channelMapper = createChannelMapper(handler, QVector<Qt3DCore::QNodeId>() << channelMapping->peerId()); + animator->setMapperId(channelMapper->peerId()); + animator->setRunning(true); // Has to be marked as running for the job to process it + + const ComponentIndices locationIndices = { 0, 1, 2 }; + MappingData expectedMapping; + expectedMapping.targetId = channelMapping->targetId(); + expectedMapping.propertyName = channelMapping->propertyName(); + expectedMapping.type = channelMapping->type(); + expectedMapping.channelIndices = locationIndices; + expectedResults.insert(animator, QVector<MappingData>() << expectedMapping); + + QTest::newRow("single mapping") + << handler + << dirtyClipAnimators + << expectedResults; + } + } + + void checkJob() + { + // GIVEN + QFETCH(Handler *, handler); + QFETCH(QVector<HClipAnimator>, dirtyClipAnimators); + QFETCH(MappingDataResults, expectedResults); + FindRunningClipAnimatorsJob job; + + // WHEN + job.setHandler(handler); + job.setDirtyClipAnimators(dirtyClipAnimators); + job.run(); + + // THEN - check the resulting MappingData on the animator matches the expected results + for (const auto &dirtyClipAnimator : dirtyClipAnimators) { + const auto animator = handler->clipAnimatorManager()->data(dirtyClipAnimator); + const QVector<MappingData> actualMappingData = animator->mappingData(); + const QVector<MappingData> expectedMappingData = expectedResults[animator]; + + QCOMPARE(expectedMappingData.size(), actualMappingData.size()); + for (int i = 0; i < actualMappingData.size(); ++i) { + QCOMPARE(expectedMappingData[i].targetId, actualMappingData[i].targetId); + QCOMPARE(expectedMappingData[i].type, actualMappingData[i].type); + QVERIFY(qstrcmp(expectedMappingData[i].propertyName, actualMappingData[i].propertyName) == 0); + QCOMPARE(expectedMappingData[i].channelIndices.size(), actualMappingData[i].channelIndices.size()); + + for (int j = 0; j < actualMappingData[i].channelIndices.size(); ++j) { + QCOMPARE(expectedMappingData[i].channelIndices[j], actualMappingData[i].channelIndices[j]); + } + } + } + } +}; + +QTEST_APPLESS_MAIN(tst_FindRunningClipAnimatorsJob) + +#include "tst_findrunningclipanimatorsjob.moc" diff --git a/tests/auto/render/buffer/tst_buffer.cpp b/tests/auto/render/buffer/tst_buffer.cpp index 84990f4ab..a23e46c65 100644 --- a/tests/auto/render/buffer/tst_buffer.cpp +++ b/tests/auto/render/buffer/tst_buffer.cpp @@ -87,7 +87,6 @@ private Q_SLOTS: // THEN QCOMPARE(renderBuffer.peerId(), buffer.id()); QCOMPARE(renderBuffer.isDirty(), true); - QCOMPARE(renderBuffer.type(), buffer.type()); QCOMPARE(renderBuffer.usage(), buffer.usage()); QCOMPARE(renderBuffer.data(), buffer.data()); QCOMPARE(renderBuffer.dataGenerator(), buffer.dataGenerator()); @@ -105,7 +104,6 @@ private Q_SLOTS: // THEN QCOMPARE(renderBuffer.isDirty(), false); - QCOMPARE(renderBuffer.type(), Qt3DRender::QBuffer::VertexBuffer); QCOMPARE(renderBuffer.usage(), Qt3DRender::QBuffer::StaticDraw); QVERIFY(renderBuffer.data().isEmpty()); QVERIFY(renderBuffer.peerId().isNull()); @@ -113,7 +111,7 @@ private Q_SLOTS: QVERIFY(renderBuffer.pendingBufferUpdates().empty()); // GIVEN - Qt3DRender::QBuffer buffer(Qt3DRender::QBuffer::IndexBuffer); + Qt3DRender::QBuffer buffer; buffer.setUsage(Qt3DRender::QBuffer::DynamicCopy); buffer.setData(QByteArrayLiteral("C7")); buffer.setDataGenerator(Qt3DRender::QBufferDataGeneratorPtr(new TestFunctor(73))); @@ -132,7 +130,6 @@ private Q_SLOTS: renderBuffer.sceneChangeEvent(updateChange); // THEN - QCOMPARE(renderBuffer.type(), Qt3DRender::QBuffer::IndexBuffer); QCOMPARE(renderBuffer.usage(), Qt3DRender::QBuffer::DynamicCopy); QCOMPARE(renderBuffer.isDirty(), true); QCOMPARE(renderBuffer.data(), QByteArrayLiteral("C7")); @@ -144,7 +141,6 @@ private Q_SLOTS: // THEN QCOMPARE(renderBuffer.isDirty(), false); - QCOMPARE(renderBuffer.type(), Qt3DRender::QBuffer::VertexBuffer); QCOMPARE(renderBuffer.usage(), Qt3DRender::QBuffer::StaticDraw); QVERIFY(renderBuffer.data().isEmpty()); QVERIFY(renderBuffer.dataGenerator().isNull()); @@ -159,7 +155,6 @@ private Q_SLOTS: renderBuffer.setRenderer(&renderer); // THEN - QVERIFY(renderBuffer.type() != Qt3DRender::QBuffer::IndexBuffer); QVERIFY(renderBuffer.data().isEmpty()); QVERIFY(renderBuffer.usage() != Qt3DRender::QBuffer::DynamicRead); QVERIFY(!renderBuffer.isDirty()); @@ -168,24 +163,6 @@ private Q_SLOTS: // WHEN Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); - updateChange->setValue(static_cast<int>(Qt3DRender::QBuffer::IndexBuffer)); - updateChange->setPropertyName("type"); - renderBuffer.sceneChangeEvent(updateChange); - - - // THEN - QCOMPARE(renderBuffer.type(), Qt3DRender::QBuffer::IndexBuffer); - QVERIFY(renderer.dirtyBits() != 0); - QVERIFY(renderBuffer.isDirty()); - - QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::BuffersDirty); - renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); - - renderBuffer.unsetDirty(); - QVERIFY(!renderBuffer.isDirty()); - - // WHEN - updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId()); updateChange->setValue(static_cast<int>(Qt3DRender::QBuffer::DynamicRead)); updateChange->setPropertyName("usage"); renderBuffer.sceneChangeEvent(updateChange); diff --git a/tests/auto/render/meshfunctors/tst_meshfunctors.cpp b/tests/auto/render/meshfunctors/tst_meshfunctors.cpp index c0e871d62..1904169fb 100644 --- a/tests/auto/render/meshfunctors/tst_meshfunctors.cpp +++ b/tests/auto/render/meshfunctors/tst_meshfunctors.cpp @@ -27,8 +27,12 @@ ****************************************************************************/ #include <QtTest/QtTest> +#include <Qt3DCore/qcomponent.h> #include <Qt3DRender/qgeometryfactory.h> #include <Qt3DRender/qgeometry.h> +#include <Qt3DRender/qmesh.h> +#include <Qt3DRender/private/qmesh_p.h> +#include <Qt3DCore/qaspectengine.h> class MeshFunctorA : public Qt3DRender::QGeometryFactory { @@ -117,8 +121,46 @@ private Q_SLOTS: QVERIFY(*functorB == *functorB); QVERIFY(*functorASub == *functorASub); } + + void checkMeshFunctorEquality() + { + // GIVEN + Qt3DCore::QAspectEngine engine; + auto meshA = new Qt3DRender::QMesh(); + meshA->setSource(QUrl::fromLocalFile(QLatin1String("/foo"))); + meshA->setMeshName(QLatin1String("bar")); + + auto meshB = new Qt3DRender::QMesh(); + meshB->setSource(QUrl::fromLocalFile(QLatin1String("/foo"))); + meshB->setMeshName(QLatin1String("baz")); + + auto meshC = new Qt3DRender::QMesh(); + meshC->setSource(QUrl::fromLocalFile(QLatin1String("/baz"))); + meshC->setMeshName(QLatin1String("bar")); + + auto meshD = new Qt3DRender::QMesh(); + meshD->setSource(QUrl::fromLocalFile(QLatin1String("/foo"))); + meshD->setMeshName(QLatin1String("bar")); + + const Qt3DRender::MeshLoaderFunctor functorA(meshA, &engine); + const Qt3DRender::MeshLoaderFunctor functorB(meshB, &engine); + const Qt3DRender::MeshLoaderFunctor functorC(meshC, &engine); + const Qt3DRender::MeshLoaderFunctor functorD(meshD, &engine); + + // WHEN + const bool selfEquality = (functorA == functorA); + const bool sameSource = (functorA == functorB); + const bool sameMeshName = (functorA == functorC); + const bool perfectMatch = (functorA == functorD); + + // THEN + QCOMPARE(selfEquality, true); + QCOMPARE(sameSource, false); + QCOMPARE(sameMeshName, false); + QCOMPARE(perfectMatch, true); + } }; -QTEST_APPLESS_MAIN(tst_MeshFunctors) +QTEST_MAIN(tst_MeshFunctors) #include "tst_meshfunctors.moc" diff --git a/tests/auto/render/qbuffer/tst_qbuffer.cpp b/tests/auto/render/qbuffer/tst_qbuffer.cpp index 5408c0474..c0d96d10b 100644 --- a/tests/auto/render/qbuffer/tst_qbuffer.cpp +++ b/tests/auto/render/qbuffer/tst_qbuffer.cpp @@ -112,7 +112,6 @@ private Q_SLOTS: QCOMPARE(buffer->metaObject(), creationChangeData->metaObject()); QCOMPARE(buffer->data(), cloneData.data); QCOMPARE(buffer->usage(), cloneData.usage); - QCOMPARE(buffer->type(), cloneData.type); QCOMPARE(buffer->dataGenerator(), cloneData.functor); QCOMPARE(buffer->isSyncData(), cloneData.syncData); if (buffer->dataGenerator()) { diff --git a/tests/manual/skinned-mesh/DefaultSceneEntity.qml b/tests/manual/skinned-mesh/DefaultSceneEntity.qml index 26760fa51..e3465a8bb 100644 --- a/tests/manual/skinned-mesh/DefaultSceneEntity.qml +++ b/tests/manual/skinned-mesh/DefaultSceneEntity.qml @@ -68,8 +68,8 @@ Entity { Camera { id: mainCamera - position: Qt.vector3d(0, 0.8, 2) - viewCenter: Qt.vector3d(0, 0.8, 0) + position: Qt.vector3d(2.5, 0.8, 5) + viewCenter: Qt.vector3d(2.5, 0.8, 0) fieldOfView: 60 } diff --git a/tests/manual/skinned-mesh/SkinnedEntity.qml b/tests/manual/skinned-mesh/SkinnedEntity.qml index 47f2bae7b..f1c3ee0c2 100644 --- a/tests/manual/skinned-mesh/SkinnedEntity.qml +++ b/tests/manual/skinned-mesh/SkinnedEntity.qml @@ -12,6 +12,7 @@ Entity { property alias transform: transform property color baseColor: "red" property alias rootJoint: skeleton.rootJoint + property alias skeleton: skeleton components: [ Transform { diff --git a/tests/manual/skinned-mesh/SkinnedPbrEffect.qml b/tests/manual/skinned-mesh/SkinnedPbrEffect.qml index 79e4f7757..c1c383a74 100644 --- a/tests/manual/skinned-mesh/SkinnedPbrEffect.qml +++ b/tests/manual/skinned-mesh/SkinnedPbrEffect.qml @@ -30,7 +30,8 @@ Effect { ShaderProgramBuilder { shaderProgram: prog - fragmentShaderGraph: "qrc:/shaders/graphs/metalroughuniform.frag.json" + fragmentShaderGraph: "qrc:/shaders/graphs/metalrough.frag.json" + enabledLayers: ["baseColor", "metalness", "roughness", "ambientOcclusion", "normal"] } } } diff --git a/tests/manual/skinned-mesh/jump.json b/tests/manual/skinned-mesh/jump.json new file mode 100644 index 000000000..7d7447a40 --- /dev/null +++ b/tests/manual/skinned-mesh/jump.json @@ -0,0 +1,4571 @@ +{ + "animations": [ + { + "animationName": "Jump", + "channels": [ + { + "channelComponents": [ + { + "channelComponentName": "Location X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.3090757727622986, + 0.0 + ], + "rightHandle": [ + 0.3090757528940837, + 0.0 + ] + }, + { + "coords": [ + 0.7916666666666666, + 0.0 + ], + "leftHandle": [ + 0.482590913772583, + 0.0 + ], + "rightHandle": [ + 0.9543381532033285, + 0.0 + ] + }, + { + "coords": [ + 1.2083333333333333, + -0.5 + ], + "leftHandle": [ + 1.0456618467966716, + -0.5 + ], + "rightHandle": [ + 1.2896690368652344, + -0.5 + ] + }, + { + "coords": [ + 1.4166666666666667, + -0.5 + ], + "leftHandle": [ + 1.3353309631347656, + -0.5 + ], + "rightHandle": [ + 1.5305366516113281, + -0.5 + ] + }, + { + "coords": [ + 1.7083333333333333, + 2.5 + ], + "leftHandle": [ + 1.5944633483886719, + 1.4873701333999634 + ], + "rightHandle": [ + 1.838470458984375, + 3.6572914123535156 + ] + }, + { + "coords": [ + 2.0416666666666665, + 5.0 + ], + "leftHandle": [ + 1.911529541015625, + 5.0 + ], + "rightHandle": [ + 2.5296810468037925, + 5.0 + ] + }, + { + "coords": [ + 3.2916666666666665, + 5.0 + ], + "leftHandle": [ + 2.8036524454752603, + 5.0 + ], + "rightHandle": [ + 3.405536651611328, + 5.0 + ] + }, + { + "coords": [ + 3.5833333333333335, + 5.0 + ], + "leftHandle": [ + 3.469463348388672, + 5.0 + ], + "rightHandle": [ + 3.6972033182779946, + 5.0 + ] + }, + { + "coords": [ + 3.875, + 5.0 + ], + "leftHandle": [ + 3.7611300150553384, + 5.0 + ], + "rightHandle": [ + 3.9888699849446616, + 5.0 + ] + }, + { + "coords": [ + 4.166666666666667, + 5.0 + ], + "leftHandle": [ + 4.052796681722005, + 5.0 + ], + "rightHandle": [ + 4.248002370198567, + 5.0 + ] + }, + { + "coords": [ + 4.375, + 5.0 + ], + "leftHandle": [ + 4.293664296468099, + 5.0 + ], + "rightHandle": [ + 4.456335703531901, + 5.0 + ] + }, + { + "coords": [ + 4.583333333333333, + 5.0 + ], + "leftHandle": [ + 4.501997629801433, + 5.0 + ], + "rightHandle": [ + 4.664669036865234, + 5.0 + ] + }, + { + "coords": [ + 4.791666666666667, + 5.0 + ], + "leftHandle": [ + 4.710330963134766, + 5.0 + ], + "rightHandle": [ + 4.873002370198567, + 5.0 + ] + }, + { + "coords": [ + 5.0, + 5.0 + ], + "leftHandle": [ + 4.918664296468099, + 5.0 + ], + "rightHandle": [ + 5.081335703531901, + 5.0 + ] + }, + { + "coords": [ + 5.208333333333333, + 5.0 + ], + "leftHandle": [ + 5.126997629801433, + 5.0 + ], + "rightHandle": [ + 5.598744710286458, + 5.0 + ] + }, + { + "coords": [ + 6.208333333333333, + 5.0 + ], + "leftHandle": [ + 5.817921956380208, + 5.0 + ], + "rightHandle": [ + 6.371004740397136, + 5.0 + ] + }, + { + "coords": [ + 6.625, + 5.5 + ], + "leftHandle": [ + 6.462328592936198, + 5.5 + ], + "rightHandle": [ + 6.706335703531901, + 5.5 + ] + }, + { + "coords": [ + 6.833333333333333, + 5.5 + ], + "leftHandle": [ + 6.751997629801433, + 5.5 + ], + "rightHandle": [ + 6.947203318277995, + 5.5 + ] + }, + { + "coords": [ + 7.125, + 2.5 + ], + "leftHandle": [ + 7.011130015055339, + 3.512629985809326 + ], + "rightHandle": [ + 7.255137125651042, + 1.342708706855774 + ] + }, + { + "coords": [ + 7.458333333333333, + 0.0 + ], + "leftHandle": [ + 7.328196207682292, + 0.0 + ], + "rightHandle": [ + 7.946347554524739, + 0.0 + ] + }, + { + "coords": [ + 8.708333333333334, + 0.0 + ], + "leftHandle": [ + 8.220319112141928, + 0.0 + ], + "rightHandle": [ + 8.822203318277994, + 0.0 + ] + }, + { + "coords": [ + 9.0, + 0.0 + ], + "leftHandle": [ + 8.886130015055338, + 0.0 + ], + "rightHandle": [ + 9.113869984944662, + 0.0 + ] + }, + { + "coords": [ + 9.291666666666666, + 0.0 + ], + "leftHandle": [ + 9.177796681722006, + 0.0 + ], + "rightHandle": [ + 9.405536651611328, + 0.0 + ] + }, + { + "coords": [ + 9.583333333333334, + 0.0 + ], + "leftHandle": [ + 9.469463348388672, + 0.0 + ], + "rightHandle": [ + 9.664669036865234, + 0.0 + ] + }, + { + "coords": [ + 9.791666666666666, + 0.0 + ], + "leftHandle": [ + 9.710330963134766, + 0.0 + ], + "rightHandle": [ + 9.873002370198568, + 0.0 + ] + }, + { + "coords": [ + 10.0, + 0.0 + ], + "leftHandle": [ + 9.9186642964681, + 0.0 + ], + "rightHandle": [ + 10.0813357035319, + 0.0 + ] + }, + { + "coords": [ + 10.208333333333334, + 0.0 + ], + "leftHandle": [ + 10.126997629801432, + 0.0 + ], + "rightHandle": [ + 10.289669036865234, + 0.0 + ] + }, + { + "coords": [ + 10.416666666666666, + 0.0 + ], + "leftHandle": [ + 10.335330963134766, + 0.0 + ], + "rightHandle": [ + 10.498002370198568, + 0.0 + ] + }, + { + "coords": [ + 10.625, + 0.0 + ], + "leftHandle": [ + 10.5436642964681, + 0.0 + ], + "rightHandle": [ + 10.7063357035319, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Location Z", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.3090757727622986, + 0.0 + ], + "rightHandle": [ + 0.3090757528940837, + 0.0 + ] + }, + { + "coords": [ + 0.7916666666666666, + 0.0 + ], + "leftHandle": [ + 0.482590913772583, + 0.0 + ], + "rightHandle": [ + 0.9543381532033285, + 0.0 + ] + }, + { + "coords": [ + 1.2083333333333333, + 0.0 + ], + "leftHandle": [ + 1.0456618467966716, + 0.0 + ], + "rightHandle": [ + 1.2896690368652344, + 0.0 + ] + }, + { + "coords": [ + 1.4166666666666667, + 0.0 + ], + "leftHandle": [ + 1.3353309631347656, + 0.0 + ], + "rightHandle": [ + 1.5305366516113281, + 0.0 + ] + }, + { + "coords": [ + 1.7083333333333333, + 0.0 + ], + "leftHandle": [ + 1.5944633483886719, + 0.0 + ], + "rightHandle": [ + 1.838470458984375, + 0.0 + ] + }, + { + "coords": [ + 2.0416666666666665, + 0.0 + ], + "leftHandle": [ + 1.911529541015625, + 0.0 + ], + "rightHandle": [ + 2.5296810468037925, + 0.0 + ] + }, + { + "coords": [ + 3.2916666666666665, + 0.0 + ], + "leftHandle": [ + 2.8036524454752603, + 0.0 + ], + "rightHandle": [ + 3.405536651611328, + 0.0 + ] + }, + { + "coords": [ + 3.5833333333333335, + 0.0 + ], + "leftHandle": [ + 3.469463348388672, + 0.0 + ], + "rightHandle": [ + 3.6972033182779946, + 0.0 + ] + }, + { + "coords": [ + 3.875, + 0.0 + ], + "leftHandle": [ + 3.7611300150553384, + 0.0 + ], + "rightHandle": [ + 3.9888699849446616, + 0.0 + ] + }, + { + "coords": [ + 4.166666666666667, + 0.0 + ], + "leftHandle": [ + 4.052796681722005, + 0.0 + ], + "rightHandle": [ + 4.248002370198567, + 0.0 + ] + }, + { + "coords": [ + 4.375, + 0.0 + ], + "leftHandle": [ + 4.293664296468099, + 0.0 + ], + "rightHandle": [ + 4.456335703531901, + 0.0 + ] + }, + { + "coords": [ + 4.583333333333333, + 0.0 + ], + "leftHandle": [ + 4.501997629801433, + 0.0 + ], + "rightHandle": [ + 4.664669036865234, + 0.0 + ] + }, + { + "coords": [ + 4.791666666666667, + 0.0 + ], + "leftHandle": [ + 4.710330963134766, + 0.0 + ], + "rightHandle": [ + 4.873002370198567, + 0.0 + ] + }, + { + "coords": [ + 5.0, + 0.0 + ], + "leftHandle": [ + 4.918664296468099, + 0.0 + ], + "rightHandle": [ + 5.081335703531901, + 0.0 + ] + }, + { + "coords": [ + 5.208333333333333, + 0.0 + ], + "leftHandle": [ + 5.126997629801433, + 0.0 + ], + "rightHandle": [ + 5.598744710286458, + 0.0 + ] + }, + { + "coords": [ + 6.208333333333333, + 0.0 + ], + "leftHandle": [ + 5.817921956380208, + 0.0 + ], + "rightHandle": [ + 6.371004740397136, + 0.0 + ] + }, + { + "coords": [ + 6.625, + 0.0 + ], + "leftHandle": [ + 6.462328592936198, + 0.0 + ], + "rightHandle": [ + 6.706335703531901, + 0.0 + ] + }, + { + "coords": [ + 6.833333333333333, + 0.0 + ], + "leftHandle": [ + 6.751997629801433, + 0.0 + ], + "rightHandle": [ + 6.947203318277995, + 0.0 + ] + }, + { + "coords": [ + 7.125, + 0.0 + ], + "leftHandle": [ + 7.011130015055339, + 0.0 + ], + "rightHandle": [ + 7.255137125651042, + 0.0 + ] + }, + { + "coords": [ + 7.458333333333333, + 0.0 + ], + "leftHandle": [ + 7.328196207682292, + 0.0 + ], + "rightHandle": [ + 7.946347554524739, + 0.0 + ] + }, + { + "coords": [ + 8.708333333333334, + 0.0 + ], + "leftHandle": [ + 8.220319112141928, + 0.0 + ], + "rightHandle": [ + 8.822203318277994, + 0.0 + ] + }, + { + "coords": [ + 9.0, + 0.0 + ], + "leftHandle": [ + 8.886130015055338, + 0.0 + ], + "rightHandle": [ + 9.113869984944662, + 0.0 + ] + }, + { + "coords": [ + 9.291666666666666, + 0.0 + ], + "leftHandle": [ + 9.177796681722006, + 0.0 + ], + "rightHandle": [ + 9.405536651611328, + 0.0 + ] + }, + { + "coords": [ + 9.583333333333334, + 0.0 + ], + "leftHandle": [ + 9.469463348388672, + 0.0 + ], + "rightHandle": [ + 9.664669036865234, + 0.0 + ] + }, + { + "coords": [ + 9.791666666666666, + 0.0 + ], + "leftHandle": [ + 9.710330963134766, + 0.0 + ], + "rightHandle": [ + 9.873002370198568, + 0.0 + ] + }, + { + "coords": [ + 10.0, + 0.0 + ], + "leftHandle": [ + 9.9186642964681, + 0.0 + ], + "rightHandle": [ + 10.0813357035319, + 0.0 + ] + }, + { + "coords": [ + 10.208333333333334, + 0.0 + ], + "leftHandle": [ + 10.126997629801432, + 0.0 + ], + "rightHandle": [ + 10.289669036865234, + 0.0 + ] + }, + { + "coords": [ + 10.416666666666666, + 0.0 + ], + "leftHandle": [ + 10.335330963134766, + 0.0 + ], + "rightHandle": [ + 10.498002370198568, + 0.0 + ] + }, + { + "coords": [ + 10.625, + 0.0 + ], + "leftHandle": [ + 10.5436642964681, + 0.0 + ], + "rightHandle": [ + 10.7063357035319, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Location Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.3090757727622986, + 0.0 + ], + "rightHandle": [ + 0.3090757528940837, + 0.0 + ] + }, + { + "coords": [ + 0.7916666666666666, + 0.0 + ], + "leftHandle": [ + 0.482590913772583, + 0.0 + ], + "rightHandle": [ + 0.9543381532033285, + 0.0 + ] + }, + { + "coords": [ + 1.2083333333333333, + 0.0 + ], + "leftHandle": [ + 1.0456618467966716, + 0.0 + ], + "rightHandle": [ + 1.2896690368652344, + 0.0 + ] + }, + { + "coords": [ + 1.4166666666666667, + 0.0 + ], + "leftHandle": [ + 1.3353309631347656, + 0.0 + ], + "rightHandle": [ + 1.5305366516113281, + 0.0 + ] + }, + { + "coords": [ + 1.7083333333333333, + 2.0 + ], + "leftHandle": [ + 1.5944633483886719, + 2.0 + ], + "rightHandle": [ + 1.838470458984375, + 2.0 + ] + }, + { + "coords": [ + 2.0416666666666665, + 0.0 + ], + "leftHandle": [ + 1.911529541015625, + 0.0 + ], + "rightHandle": [ + 2.5296810468037925, + 0.0 + ] + }, + { + "coords": [ + 3.2916666666666665, + 0.0 + ], + "leftHandle": [ + 2.8036524454752603, + 0.0 + ], + "rightHandle": [ + 3.405536651611328, + 0.0 + ] + }, + { + "coords": [ + 3.5833333333333335, + 0.0 + ], + "leftHandle": [ + 3.469463348388672, + 0.0 + ], + "rightHandle": [ + 3.6972033182779946, + 0.0 + ] + }, + { + "coords": [ + 3.875, + 0.5 + ], + "leftHandle": [ + 3.7611300150553384, + 0.5 + ], + "rightHandle": [ + 3.9888699849446616, + 0.5 + ] + }, + { + "coords": [ + 4.166666666666667, + 0.0 + ], + "leftHandle": [ + 4.052796681722005, + 0.0 + ], + "rightHandle": [ + 4.248002370198567, + 0.0 + ] + }, + { + "coords": [ + 4.375, + 0.0 + ], + "leftHandle": [ + 4.293664296468099, + 0.0 + ], + "rightHandle": [ + 4.456335703531901, + 0.0 + ] + }, + { + "coords": [ + 4.583333333333333, + 0.0 + ], + "leftHandle": [ + 4.501997629801433, + 0.0 + ], + "rightHandle": [ + 4.664669036865234, + 0.0 + ] + }, + { + "coords": [ + 4.791666666666667, + 0.0 + ], + "leftHandle": [ + 4.710330963134766, + 0.0 + ], + "rightHandle": [ + 4.873002370198567, + 0.0 + ] + }, + { + "coords": [ + 5.0, + 0.30000001192092896 + ], + "leftHandle": [ + 4.918664296468099, + 0.30000001192092896 + ], + "rightHandle": [ + 5.081335703531901, + 0.30000001192092896 + ] + }, + { + "coords": [ + 5.208333333333333, + 0.0 + ], + "leftHandle": [ + 5.126997629801433, + 0.0 + ], + "rightHandle": [ + 5.598744710286458, + 0.0 + ] + }, + { + "coords": [ + 6.208333333333333, + 0.0 + ], + "leftHandle": [ + 5.817921956380208, + 0.0 + ], + "rightHandle": [ + 6.371004740397136, + 0.0 + ] + }, + { + "coords": [ + 6.625, + 0.0 + ], + "leftHandle": [ + 6.462328592936198, + 0.0 + ], + "rightHandle": [ + 6.706335703531901, + 0.0 + ] + }, + { + "coords": [ + 6.833333333333333, + 0.0 + ], + "leftHandle": [ + 6.751997629801433, + 0.0 + ], + "rightHandle": [ + 6.947203318277995, + 0.0 + ] + }, + { + "coords": [ + 7.125, + 2.0 + ], + "leftHandle": [ + 7.011130015055339, + 2.0 + ], + "rightHandle": [ + 7.255137125651042, + 2.0 + ] + }, + { + "coords": [ + 7.458333333333333, + 0.0 + ], + "leftHandle": [ + 7.328196207682292, + 0.0 + ], + "rightHandle": [ + 7.946347554524739, + 0.0 + ] + }, + { + "coords": [ + 8.708333333333334, + 0.0 + ], + "leftHandle": [ + 8.220319112141928, + 0.0 + ], + "rightHandle": [ + 8.822203318277994, + 0.0 + ] + }, + { + "coords": [ + 9.0, + 0.0 + ], + "leftHandle": [ + 8.886130015055338, + 0.0 + ], + "rightHandle": [ + 9.113869984944662, + 0.0 + ] + }, + { + "coords": [ + 9.291666666666666, + 0.5 + ], + "leftHandle": [ + 9.177796681722006, + 0.5 + ], + "rightHandle": [ + 9.405536651611328, + 0.5 + ] + }, + { + "coords": [ + 9.583333333333334, + 0.0 + ], + "leftHandle": [ + 9.469463348388672, + 0.0 + ], + "rightHandle": [ + 9.664669036865234, + 0.0 + ] + }, + { + "coords": [ + 9.791666666666666, + 0.0 + ], + "leftHandle": [ + 9.710330963134766, + 0.0 + ], + "rightHandle": [ + 9.873002370198568, + 0.0 + ] + }, + { + "coords": [ + 10.0, + 0.0 + ], + "leftHandle": [ + 9.9186642964681, + 0.0 + ], + "rightHandle": [ + 10.0813357035319, + 0.0 + ] + }, + { + "coords": [ + 10.208333333333334, + 0.0 + ], + "leftHandle": [ + 10.126997629801432, + 0.0 + ], + "rightHandle": [ + 10.289669036865234, + 0.0 + ] + }, + { + "coords": [ + 10.416666666666666, + 0.30000001192092896 + ], + "leftHandle": [ + 10.335330963134766, + 0.30000001192092896 + ], + "rightHandle": [ + 10.498002370198568, + 0.30000001192092896 + ] + }, + { + "coords": [ + 10.625, + 0.0 + ], + "leftHandle": [ + 10.5436642964681, + 0.0 + ], + "rightHandle": [ + 10.7063357035319, + 0.0 + ] + } + ] + } + ], + "channelName": "Location", + "jointIndex": 0 + }, + { + "channelComponents": [ + { + "channelComponentName": "Scale X", + "keyFrames": [ + { + "coords": [ + 0.0, + 1.000070333480835 + ], + "leftHandle": [ + -0.3090757926305135, + 1.000070333480835 + ], + "rightHandle": [ + 0.3090757528940837, + 1.000070333480835 + ] + }, + { + "coords": [ + 0.7916666666666666, + 1.000070333480835 + ], + "leftHandle": [ + 0.482590913772583, + 1.000070333480835 + ], + "rightHandle": [ + 0.9543381532033285, + 1.000070333480835 + ] + }, + { + "coords": [ + 1.2083333333333333, + 1.2000703811645508 + ], + "leftHandle": [ + 1.0456618467966716, + 1.2000703811645508 + ], + "rightHandle": [ + 1.6150120099385579, + 1.2000703811645508 + ] + }, + { + "coords": [ + 1.4166666666666667, + 1.2000703811645508 + ], + "leftHandle": [ + 1.0099881490071614, + 1.2000703811645508 + ], + "rightHandle": [ + 1.5305366516113281, + 1.2000703811645508 + ] + }, + { + "coords": [ + 1.7083333333333333, + 0.8000703454017639 + ], + "leftHandle": [ + 1.5944633483886719, + 0.8000703454017639 + ], + "rightHandle": [ + 1.838470458984375, + 0.8000703454017639 + ] + }, + { + "coords": [ + 2.0416666666666665, + 1.2000703811645508 + ], + "leftHandle": [ + 1.9603309631347656, + 1.0536658763885498 + ], + "rightHandle": [ + 2.057933807373047, + 1.229351282119751 + ] + }, + { + "coords": [ + 2.0833333333333335, + 1.3000702857971191 + ], + "leftHandle": [ + 2.0386231740315757, + 1.3000702857971191 + ], + "rightHandle": [ + 2.1339289347330728, + 1.3000702857971191 + ] + }, + { + "coords": [ + 2.2083333333333335, + 0.9400703310966492 + ], + "leftHandle": [ + 2.1606807708740234, + 0.9400703310966492 + ], + "rightHandle": [ + 2.255985895792643, + 0.9400703310966492 + ] + }, + { + "coords": [ + 2.3333333333333335, + 1.000070333480835 + ], + "leftHandle": [ + 2.2827377319335938, + 1.000070333480835 + ], + "rightHandle": [ + 2.3780434926350913, + 1.000070333480835 + ] + }, + { + "coords": [ + 3.2916666666666665, + 1.000070333480835 + ], + "leftHandle": [ + 2.917522430419922, + 1.000070333480835 + ], + "rightHandle": [ + 3.405536651611328, + 1.000070333480835 + ] + }, + { + "coords": [ + 3.5833333333333335, + 1.2000703811645508 + ], + "leftHandle": [ + 3.469463348388672, + 1.2000703811645508 + ], + "rightHandle": [ + 3.6972033182779946, + 1.2000703811645508 + ] + }, + { + "coords": [ + 3.875, + 0.8000703454017639 + ], + "leftHandle": [ + 3.7611300150553384, + 0.8000703454017639 + ], + "rightHandle": [ + 3.9888699849446616, + 0.8000703454017639 + ] + }, + { + "coords": [ + 4.166666666666667, + 1.2000703811645508 + ], + "leftHandle": [ + 4.052796681722005, + 1.2000703811645508 + ], + "rightHandle": [ + 4.248002370198567, + 1.2000703811645508 + ] + }, + { + "coords": [ + 4.375, + 1.2000703811645508 + ], + "leftHandle": [ + 4.293664296468099, + 1.2000703811645508 + ], + "rightHandle": [ + 4.456335703531901, + 1.2000703811645508 + ] + }, + { + "coords": [ + 4.583333333333333, + 1.2000703811645508 + ], + "leftHandle": [ + 4.501997629801433, + 1.2000703811645508 + ], + "rightHandle": [ + 4.664669036865234, + 1.2000703811645508 + ] + }, + { + "coords": [ + 4.791666666666667, + 1.1000703573226929 + ], + "leftHandle": [ + 4.710330963134766, + 1.1508238315582275 + ], + "rightHandle": [ + 4.873002370198567, + 1.0493168830871582 + ] + }, + { + "coords": [ + 5.0, + 0.9400703310966492 + ], + "leftHandle": [ + 4.918664296468099, + 0.9400703310966492 + ], + "rightHandle": [ + 5.081335703531901, + 0.9400703310966492 + ] + }, + { + "coords": [ + 5.208333333333333, + 1.1000703573226929 + ], + "leftHandle": [ + 5.126997629801433, + 1.1000703573226929 + ], + "rightHandle": [ + 5.2734018961588545, + 1.1000703573226929 + ] + }, + { + "coords": [ + 5.375, + 1.000070333480835 + ], + "leftHandle": [ + 5.3099314371744795, + 1.000070333480835 + ], + "rightHandle": [ + 5.7003428141276045, + 1.000070333480835 + ] + }, + { + "coords": [ + 6.208333333333333, + 1.000070333480835 + ], + "leftHandle": [ + 5.8829905192057295, + 1.000070333480835 + ], + "rightHandle": [ + 6.371004740397136, + 1.000070333480835 + ] + }, + { + "coords": [ + 6.625, + 1.2000703811645508 + ], + "leftHandle": [ + 6.462328592936198, + 1.2000703811645508 + ], + "rightHandle": [ + 7.031678517659505, + 1.2000703811645508 + ] + }, + { + "coords": [ + 6.833333333333333, + 1.2000703811645508 + ], + "leftHandle": [ + 6.426654815673828, + 1.2000703811645508 + ], + "rightHandle": [ + 6.947203318277995, + 1.2000703811645508 + ] + }, + { + "coords": [ + 7.125, + 0.8000703454017639 + ], + "leftHandle": [ + 7.011130015055339, + 0.8000703454017639 + ], + "rightHandle": [ + 7.255137125651042, + 0.8000703454017639 + ] + }, + { + "coords": [ + 7.458333333333333, + 1.2000703811645508 + ], + "leftHandle": [ + 7.376997629801433, + 1.0536658763885498 + ], + "rightHandle": [ + 7.474600474039714, + 1.229351282119751 + ] + }, + { + "coords": [ + 7.5, + 1.3000702857971191 + ], + "leftHandle": [ + 7.455289204915364, + 1.3000702857971191 + ], + "rightHandle": [ + 7.550595601399739, + 1.3000702857971191 + ] + }, + { + "coords": [ + 7.625, + 0.9400703310966492 + ], + "leftHandle": [ + 7.5773468017578125, + 0.9400703310966492 + ], + "rightHandle": [ + 7.6726531982421875, + 0.9400703310966492 + ] + }, + { + "coords": [ + 7.75, + 1.000070333480835 + ], + "leftHandle": [ + 7.699404398600261, + 1.000070333480835 + ], + "rightHandle": [ + 7.794710795084636, + 1.000070333480835 + ] + }, + { + "coords": [ + 8.708333333333334, + 1.000070333480835 + ], + "leftHandle": [ + 8.334189097086588, + 1.000070333480835 + ], + "rightHandle": [ + 8.822203318277994, + 1.000070333480835 + ] + }, + { + "coords": [ + 9.0, + 1.2000703811645508 + ], + "leftHandle": [ + 8.886130015055338, + 1.2000703811645508 + ], + "rightHandle": [ + 9.113869984944662, + 1.2000703811645508 + ] + }, + { + "coords": [ + 9.291666666666666, + 0.8000703454017639 + ], + "leftHandle": [ + 9.177796681722006, + 0.8000703454017639 + ], + "rightHandle": [ + 9.405536651611328, + 0.8000703454017639 + ] + }, + { + "coords": [ + 9.583333333333334, + 1.2000703811645508 + ], + "leftHandle": [ + 9.469462076822916, + 1.2000703811645508 + ], + "rightHandle": [ + 9.664667765299479, + 1.2000703811645508 + ] + }, + { + "coords": [ + 9.791666666666666, + 1.000070333480835 + ], + "leftHandle": [ + 9.710332234700521, + 1.000070333480835 + ], + "rightHandle": [ + 9.873001098632812, + 1.000070333480835 + ] + }, + { + "coords": [ + 10.0, + 1.000070333480835 + ], + "leftHandle": [ + 9.918665568033854, + 1.000070333480835 + ], + "rightHandle": [ + 10.081334431966146, + 1.000070333480835 + ] + }, + { + "coords": [ + 10.208333333333334, + 1.1000703573226929 + ], + "leftHandle": [ + 10.126998901367188, + 1.1000703573226929 + ], + "rightHandle": [ + 10.289667765299479, + 1.1000703573226929 + ] + }, + { + "coords": [ + 10.416666666666666, + 0.9400703310966492 + ], + "leftHandle": [ + 10.335332234700521, + 0.9400703310966492 + ], + "rightHandle": [ + 10.498001098632812, + 0.9400703310966492 + ] + }, + { + "coords": [ + 10.625, + 1.1000703573226929 + ], + "leftHandle": [ + 10.543665568033854, + 1.1000703573226929 + ], + "rightHandle": [ + 10.690068562825521, + 1.1000703573226929 + ] + }, + { + "coords": [ + 10.791666666666666, + 1.000070333480835 + ], + "leftHandle": [ + 10.726598103841146, + 1.000070333480835 + ], + "rightHandle": [ + 10.856735229492188, + 1.000070333480835 + ] + } + ] + }, + { + "channelComponentName": "Scale Z", + "keyFrames": [ + { + "coords": [ + 0.0, + 1.000070333480835 + ], + "leftHandle": [ + -0.3090757926305135, + 1.000070333480835 + ], + "rightHandle": [ + 0.3090757528940837, + 1.000070333480835 + ] + }, + { + "coords": [ + 0.7916666666666666, + 1.000070333480835 + ], + "leftHandle": [ + 0.482590913772583, + 1.000070333480835 + ], + "rightHandle": [ + 0.9543381532033285, + 1.000070333480835 + ] + }, + { + "coords": [ + 1.2083333333333333, + 1.2000703811645508 + ], + "leftHandle": [ + 1.0456618467966716, + 1.2000703811645508 + ], + "rightHandle": [ + 1.6150120099385579, + 1.2000703811645508 + ] + }, + { + "coords": [ + 1.4166666666666667, + 1.2000703811645508 + ], + "leftHandle": [ + 1.0099881490071614, + 1.2000703811645508 + ], + "rightHandle": [ + 1.5305366516113281, + 1.2000703811645508 + ] + }, + { + "coords": [ + 1.7083333333333333, + 0.8000703454017639 + ], + "leftHandle": [ + 1.5944633483886719, + 0.8000703454017639 + ], + "rightHandle": [ + 1.838470458984375, + 0.8000703454017639 + ] + }, + { + "coords": [ + 2.0416666666666665, + 1.2000703811645508 + ], + "leftHandle": [ + 1.9603309631347656, + 1.0536658763885498 + ], + "rightHandle": [ + 2.057933807373047, + 1.229351282119751 + ] + }, + { + "coords": [ + 2.0833333333333335, + 1.3000702857971191 + ], + "leftHandle": [ + 2.0386231740315757, + 1.3000702857971191 + ], + "rightHandle": [ + 2.1339289347330728, + 1.3000702857971191 + ] + }, + { + "coords": [ + 2.2083333333333335, + 0.9400703310966492 + ], + "leftHandle": [ + 2.1606807708740234, + 0.9400703310966492 + ], + "rightHandle": [ + 2.255985895792643, + 0.9400703310966492 + ] + }, + { + "coords": [ + 2.3333333333333335, + 1.000070333480835 + ], + "leftHandle": [ + 2.2827377319335938, + 1.000070333480835 + ], + "rightHandle": [ + 2.3780434926350913, + 1.000070333480835 + ] + }, + { + "coords": [ + 3.2916666666666665, + 1.000070333480835 + ], + "leftHandle": [ + 2.917522430419922, + 1.000070333480835 + ], + "rightHandle": [ + 3.405536651611328, + 1.000070333480835 + ] + }, + { + "coords": [ + 3.5833333333333335, + 1.2000703811645508 + ], + "leftHandle": [ + 3.469463348388672, + 1.2000703811645508 + ], + "rightHandle": [ + 3.6972033182779946, + 1.2000703811645508 + ] + }, + { + "coords": [ + 3.875, + 0.8000703454017639 + ], + "leftHandle": [ + 3.7611300150553384, + 0.8000703454017639 + ], + "rightHandle": [ + 3.9888699849446616, + 0.8000703454017639 + ] + }, + { + "coords": [ + 4.166666666666667, + 1.2000703811645508 + ], + "leftHandle": [ + 4.052796681722005, + 1.2000703811645508 + ], + "rightHandle": [ + 4.248002370198567, + 1.2000703811645508 + ] + }, + { + "coords": [ + 4.375, + 1.2000703811645508 + ], + "leftHandle": [ + 4.293664296468099, + 1.2000703811645508 + ], + "rightHandle": [ + 4.456335703531901, + 1.2000703811645508 + ] + }, + { + "coords": [ + 4.583333333333333, + 1.2000703811645508 + ], + "leftHandle": [ + 4.501997629801433, + 1.2000703811645508 + ], + "rightHandle": [ + 4.664669036865234, + 1.2000703811645508 + ] + }, + { + "coords": [ + 4.791666666666667, + 1.1000703573226929 + ], + "leftHandle": [ + 4.710330963134766, + 1.1508238315582275 + ], + "rightHandle": [ + 4.873002370198567, + 1.0493168830871582 + ] + }, + { + "coords": [ + 5.0, + 0.9400703310966492 + ], + "leftHandle": [ + 4.918664296468099, + 0.9400703310966492 + ], + "rightHandle": [ + 5.081335703531901, + 0.9400703310966492 + ] + }, + { + "coords": [ + 5.208333333333333, + 1.1000703573226929 + ], + "leftHandle": [ + 5.126997629801433, + 1.1000703573226929 + ], + "rightHandle": [ + 5.2734018961588545, + 1.1000703573226929 + ] + }, + { + "coords": [ + 5.375, + 1.000070333480835 + ], + "leftHandle": [ + 5.3099314371744795, + 1.000070333480835 + ], + "rightHandle": [ + 5.7003428141276045, + 1.000070333480835 + ] + }, + { + "coords": [ + 6.208333333333333, + 1.000070333480835 + ], + "leftHandle": [ + 5.8829905192057295, + 1.000070333480835 + ], + "rightHandle": [ + 6.371004740397136, + 1.000070333480835 + ] + }, + { + "coords": [ + 6.625, + 1.2000703811645508 + ], + "leftHandle": [ + 6.462328592936198, + 1.2000703811645508 + ], + "rightHandle": [ + 7.031678517659505, + 1.2000703811645508 + ] + }, + { + "coords": [ + 6.833333333333333, + 1.2000703811645508 + ], + "leftHandle": [ + 6.426654815673828, + 1.2000703811645508 + ], + "rightHandle": [ + 6.947203318277995, + 1.2000703811645508 + ] + }, + { + "coords": [ + 7.125, + 0.8000703454017639 + ], + "leftHandle": [ + 7.011130015055339, + 0.8000703454017639 + ], + "rightHandle": [ + 7.255137125651042, + 0.8000703454017639 + ] + }, + { + "coords": [ + 7.458333333333333, + 1.2000703811645508 + ], + "leftHandle": [ + 7.376997629801433, + 1.0536658763885498 + ], + "rightHandle": [ + 7.474600474039714, + 1.229351282119751 + ] + }, + { + "coords": [ + 7.5, + 1.3000702857971191 + ], + "leftHandle": [ + 7.455289204915364, + 1.3000702857971191 + ], + "rightHandle": [ + 7.550595601399739, + 1.3000702857971191 + ] + }, + { + "coords": [ + 7.625, + 0.9400703310966492 + ], + "leftHandle": [ + 7.5773468017578125, + 0.9400703310966492 + ], + "rightHandle": [ + 7.6726531982421875, + 0.9400703310966492 + ] + }, + { + "coords": [ + 7.75, + 1.000070333480835 + ], + "leftHandle": [ + 7.699404398600261, + 1.000070333480835 + ], + "rightHandle": [ + 7.794710795084636, + 1.000070333480835 + ] + }, + { + "coords": [ + 8.708333333333334, + 1.000070333480835 + ], + "leftHandle": [ + 8.334189097086588, + 1.000070333480835 + ], + "rightHandle": [ + 8.822203318277994, + 1.000070333480835 + ] + }, + { + "coords": [ + 9.0, + 1.2000703811645508 + ], + "leftHandle": [ + 8.886130015055338, + 1.2000703811645508 + ], + "rightHandle": [ + 9.113869984944662, + 1.2000703811645508 + ] + }, + { + "coords": [ + 9.291666666666666, + 0.8000703454017639 + ], + "leftHandle": [ + 9.177796681722006, + 0.8000703454017639 + ], + "rightHandle": [ + 9.405536651611328, + 0.8000703454017639 + ] + }, + { + "coords": [ + 9.583333333333334, + 1.2000703811645508 + ], + "leftHandle": [ + 9.469462076822916, + 1.2000703811645508 + ], + "rightHandle": [ + 9.664667765299479, + 1.2000703811645508 + ] + }, + { + "coords": [ + 9.791666666666666, + 1.2000703811645508 + ], + "leftHandle": [ + 9.710332234700521, + 1.2000703811645508 + ], + "rightHandle": [ + 9.873001098632812, + 1.2000703811645508 + ] + }, + { + "coords": [ + 10.0, + 1.2000703811645508 + ], + "leftHandle": [ + 9.918665568033854, + 1.2000703811645508 + ], + "rightHandle": [ + 10.081334431966146, + 1.2000703811645508 + ] + }, + { + "coords": [ + 10.208333333333334, + 1.1000703573226929 + ], + "leftHandle": [ + 10.126998901367188, + 1.1508238315582275 + ], + "rightHandle": [ + 10.289667765299479, + 1.0493168830871582 + ] + }, + { + "coords": [ + 10.416666666666666, + 0.9400703310966492 + ], + "leftHandle": [ + 10.335332234700521, + 0.9400703310966492 + ], + "rightHandle": [ + 10.498001098632812, + 0.9400703310966492 + ] + }, + { + "coords": [ + 10.625, + 1.1000703573226929 + ], + "leftHandle": [ + 10.543665568033854, + 1.1000703573226929 + ], + "rightHandle": [ + 10.690068562825521, + 1.1000703573226929 + ] + }, + { + "coords": [ + 10.791666666666666, + 1.000070333480835 + ], + "leftHandle": [ + 10.726598103841146, + 1.000070333480835 + ], + "rightHandle": [ + 10.856735229492188, + 1.000070333480835 + ] + } + ] + }, + { + "channelComponentName": "Scale Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 1.0 + ], + "leftHandle": [ + -0.30907583236694336, + 1.0 + ], + "rightHandle": [ + 0.3090757528940837, + 1.0 + ] + }, + { + "coords": [ + 0.7916666666666666, + 1.0 + ], + "leftHandle": [ + 0.44092432657877606, + 1.0 + ], + "rightHandle": [ + 0.9126714070638021, + 1.0 + ] + }, + { + "coords": [ + 1.2083333333333333, + 0.6000000238418579 + ], + "leftHandle": [ + 1.0039952596028645, + 0.6000000238418579 + ], + "rightHandle": [ + 1.5733451843261719, + 0.6000000238418579 + ] + }, + { + "coords": [ + 1.4166666666666667, + 0.6000000238418579 + ], + "leftHandle": [ + 1.0099881490071614, + 0.6000000238418579 + ], + "rightHandle": [ + 1.5305366516113281, + 0.6000000238418579 + ] + }, + { + "coords": [ + 1.7083333333333333, + 1.2000000476837158 + ], + "leftHandle": [ + 1.5527966817220051, + 1.2000000476837158 + ], + "rightHandle": [ + 1.7968037923177083, + 1.2000000476837158 + ] + }, + { + "coords": [ + 2.0416666666666665, + 0.550000011920929 + ], + "leftHandle": [ + 1.996956507364909, + 0.550000011920929 + ], + "rightHandle": [ + 2.0922622680664062, + 0.550000011920929 + ] + }, + { + "coords": [ + 2.2083333333333335, + 1.0499999523162842 + ], + "leftHandle": [ + 2.119014104207357, + 1.0499999523162842 + ], + "rightHandle": [ + 2.2143192291259766, + 1.0499999523162842 + ] + }, + { + "coords": [ + 2.3333333333333335, + 1.0 + ], + "leftHandle": [ + 2.2827377319335938, + 1.0 + ], + "rightHandle": [ + 2.3780434926350913, + 1.0 + ] + }, + { + "coords": [ + 3.2916666666666665, + 1.0 + ], + "leftHandle": [ + 2.8758557637532554, + 1.0 + ], + "rightHandle": [ + 3.3638699849446616, + 1.0 + ] + }, + { + "coords": [ + 3.5833333333333335, + 0.6000000238418579 + ], + "leftHandle": [ + 3.469463348388672, + 0.6000000238418579 + ], + "rightHandle": [ + 3.6972033182779946, + 0.6000000238418579 + ] + }, + { + "coords": [ + 3.875, + 1.100000023841858 + ], + "leftHandle": [ + 3.719463348388672, + 1.100000023841858 + ], + "rightHandle": [ + 3.9472033182779946, + 1.100000023841858 + ] + }, + { + "coords": [ + 4.125, + 0.800000011920929 + ], + "leftHandle": [ + 4.011130015055339, + 0.800000011920929 + ], + "rightHandle": [ + 4.206335703531901, + 0.800000011920929 + ] + }, + { + "coords": [ + 4.375, + 1.0 + ], + "leftHandle": [ + 4.251997629801433, + 1.0 + ], + "rightHandle": [ + 4.414669036865234, + 1.0 + ] + }, + { + "coords": [ + 4.583333333333333, + 1.0 + ], + "leftHandle": [ + 4.501997629801433, + 1.0 + ], + "rightHandle": [ + 4.664669036865234, + 1.0 + ] + }, + { + "coords": [ + 4.791666666666667, + 0.8999999761581421 + ], + "leftHandle": [ + 4.668664296468099, + 0.8999999761581421 + ], + "rightHandle": [ + 4.831335703531901, + 0.8999999761581421 + ] + }, + { + "coords": [ + 5.0, + 1.0499999523162842 + ], + "leftHandle": [ + 4.918664296468099, + 1.0499999523162842 + ], + "rightHandle": [ + 5.081335703531901, + 1.0499999523162842 + ] + }, + { + "coords": [ + 5.208333333333333, + 0.8999999761581421 + ], + "leftHandle": [ + 5.085330963134766, + 0.8999999761581421 + ], + "rightHandle": [ + 5.2317352294921875, + 0.8999999761581421 + ] + }, + { + "coords": [ + 5.375, + 1.0 + ], + "leftHandle": [ + 5.2682647705078125, + 1.0 + ], + "rightHandle": [ + 5.6586761474609375, + 1.0 + ] + }, + { + "coords": [ + 6.208333333333333, + 1.0 + ], + "leftHandle": [ + 5.8413238525390625, + 1.0 + ], + "rightHandle": [ + 6.329338073730469, + 1.0 + ] + }, + { + "coords": [ + 6.625, + 0.6000000238418579 + ], + "leftHandle": [ + 6.420661926269531, + 0.6000000238418579 + ], + "rightHandle": [ + 6.990011850992839, + 0.6000000238418579 + ] + }, + { + "coords": [ + 6.791666666666667, + 0.6000000238418579 + ], + "leftHandle": [ + 6.384988149007161, + 0.6000000238418579 + ], + "rightHandle": [ + 6.905536651611328, + 0.6000000238418579 + ] + }, + { + "coords": [ + 7.125, + 1.2000000476837158 + ], + "leftHandle": [ + 6.969463348388672, + 1.2000000476837158 + ], + "rightHandle": [ + 7.213470458984375, + 1.2000000476837158 + ] + }, + { + "coords": [ + 7.458333333333333, + 0.800000011920929 + ], + "leftHandle": [ + 7.3353322347005205, + 1.0928102731704712 + ], + "rightHandle": [ + 7.4631195068359375, + 0.7886062860488892 + ] + }, + { + "coords": [ + 7.458333333333333, + 0.550000011920929 + ], + "leftHandle": [ + 7.413622538248698, + 0.550000011920929 + ], + "rightHandle": [ + 7.508928934733073, + 0.550000011920929 + ] + }, + { + "coords": [ + 7.625, + 1.0499999523162842 + ], + "leftHandle": [ + 7.5356801350911455, + 1.0499999523162842 + ], + "rightHandle": [ + 7.6309865315755205, + 1.0499999523162842 + ] + }, + { + "coords": [ + 7.75, + 1.0 + ], + "leftHandle": [ + 7.699404398600261, + 1.0 + ], + "rightHandle": [ + 7.794710795084636, + 1.0 + ] + }, + { + "coords": [ + 8.708333333333334, + 1.0 + ], + "leftHandle": [ + 8.292522430419922, + 1.0 + ], + "rightHandle": [ + 8.780536651611328, + 1.0 + ] + }, + { + "coords": [ + 8.958333333333334, + 0.6000000238418579 + ], + "leftHandle": [ + 8.844463348388672, + 0.6000000238418579 + ], + "rightHandle": [ + 9.07220458984375, + 0.6000000238418579 + ] + }, + { + "coords": [ + 9.291666666666666, + 1.100000023841858 + ], + "leftHandle": [ + 9.136128743489584, + 1.100000023841858 + ], + "rightHandle": [ + 9.363871256510416, + 1.100000023841858 + ] + }, + { + "coords": [ + 9.541666666666666, + 0.800000011920929 + ], + "leftHandle": [ + 9.42779541015625, + 0.800000011920929 + ], + "rightHandle": [ + 9.623001098632812, + 0.800000011920929 + ] + }, + { + "coords": [ + 9.791666666666666, + 1.0 + ], + "leftHandle": [ + 9.668665568033854, + 1.0 + ], + "rightHandle": [ + 9.831334431966146, + 1.0 + ] + }, + { + "coords": [ + 10.0, + 1.0 + ], + "leftHandle": [ + 9.918665568033854, + 1.0 + ], + "rightHandle": [ + 10.081334431966146, + 1.0 + ] + }, + { + "coords": [ + 10.208333333333334, + 0.8999999761581421 + ], + "leftHandle": [ + 10.085332234700521, + 0.8999999761581421 + ], + "rightHandle": [ + 10.248001098632812, + 0.8999999761581421 + ] + }, + { + "coords": [ + 10.416666666666666, + 1.0499999523162842 + ], + "leftHandle": [ + 10.335332234700521, + 1.0499999523162842 + ], + "rightHandle": [ + 10.498001098632812, + 1.0499999523162842 + ] + }, + { + "coords": [ + 10.625, + 0.8999999761581421 + ], + "leftHandle": [ + 10.501998901367188, + 0.8999999761581421 + ], + "rightHandle": [ + 10.648401896158854, + 0.8999999761581421 + ] + }, + { + "coords": [ + 10.791666666666666, + 1.0 + ], + "leftHandle": [ + 10.684931437174479, + 1.0 + ], + "rightHandle": [ + 10.815068562825521, + 1.0 + ] + } + ] + } + ], + "channelName": "Scale", + "jointIndex": 0 + }, + { + "channelComponents": [ + { + "channelComponentName": "Rotation W", + "keyFrames": [ + { + "coords": [ + 0.0, + 1.0 + ], + "leftHandle": [ + -0.3090757727622986, + 1.0 + ], + "rightHandle": [ + 0.3090757528940837, + 1.0 + ] + }, + { + "coords": [ + 0.7916666666666666, + 1.0 + ], + "leftHandle": [ + 0.482590913772583, + 1.0 + ], + "rightHandle": [ + 0.9543381532033285, + 1.0 + ] + }, + { + "coords": [ + 1.2083333333333333, + 1.0 + ], + "leftHandle": [ + 1.0456618467966716, + 1.0 + ], + "rightHandle": [ + 1.2896690368652344, + 1.0 + ] + }, + { + "coords": [ + 1.4166666666666667, + 1.0 + ], + "leftHandle": [ + 1.3353309631347656, + 1.0 + ], + "rightHandle": [ + 1.4817352294921875, + 1.0 + ] + }, + { + "coords": [ + 1.5833333333333333, + 0.9848077893257141 + ], + "leftHandle": [ + 1.5182647705078125, + 0.9848077893257141 + ], + "rightHandle": [ + 1.6809361775716145, + 0.9848077893257141 + ] + }, + { + "coords": [ + 1.8333333333333333, + 0.9961948394775391 + ], + "leftHandle": [ + 1.735730489095052, + 0.9930806159973145 + ], + "rightHandle": [ + 1.9146690368652344, + 0.9987900257110596 + ] + }, + { + "coords": [ + 2.0416666666666665, + 1.000000238418579 + ], + "leftHandle": [ + 1.9603309631347656, + 1.000000238418579 + ], + "rightHandle": [ + 2.448345343271891, + 1.000000238418579 + ] + }, + { + "coords": [ + 3.2916666666666665, + 1.000000238418579 + ], + "leftHandle": [ + 2.8036524454752603, + 1.000000238418579 + ], + "rightHandle": [ + 3.405536651611328, + 1.000000238418579 + ] + }, + { + "coords": [ + 3.5833333333333335, + 1.000000238418579 + ], + "leftHandle": [ + 3.469463348388672, + 1.000000238418579 + ], + "rightHandle": [ + 3.6972033182779946, + 1.000000238418579 + ] + }, + { + "coords": [ + 3.875, + 0.8191520571708679 + ], + "leftHandle": [ + 3.7611300150553384, + 0.9475935697555542 + ], + "rightHandle": [ + 3.9888699849446616, + 0.6907105445861816 + ] + }, + { + "coords": [ + 4.166666666666667, + 0.3420201539993286 + ], + "leftHandle": [ + 4.052796681722005, + 0.3420201539993286 + ], + "rightHandle": [ + 4.248002370198567, + 0.3420201539993286 + ] + }, + { + "coords": [ + 4.375, + 0.3420201539993286 + ], + "leftHandle": [ + 4.293664296468099, + 0.3420201539993286 + ], + "rightHandle": [ + 4.456335703531901, + 0.3420201539993286 + ] + }, + { + "coords": [ + 4.583333333333333, + 0.3420201539993286 + ], + "leftHandle": [ + 4.501997629801433, + 0.3420201539993286 + ], + "rightHandle": [ + 4.664669036865234, + 0.3420201539993286 + ] + }, + { + "coords": [ + 4.791666666666667, + 0.3420201539993286 + ], + "leftHandle": [ + 4.710330963134766, + 0.3420201539993286 + ], + "rightHandle": [ + 4.873002370198567, + 0.3420201539993286 + ] + }, + { + "coords": [ + 5.0, + 0.17364823818206787 + ], + "leftHandle": [ + 4.918664296468099, + 0.24041254818439484 + ], + "rightHandle": [ + 5.081335703531901, + 0.1068839281797409 + ] + }, + { + "coords": [ + 5.208333333333333, + -5.960464477539063e-08 + ], + "leftHandle": [ + 5.126997629801433, + -5.960464477539063e-08 + ], + "rightHandle": [ + 5.598744710286458, + -5.960464477539063e-08 + ] + }, + { + "coords": [ + 6.208333333333333, + 0.0 + ], + "leftHandle": [ + 5.817921956380208, + -5.960464477539063e-08 + ], + "rightHandle": [ + 6.371004740397136, + 2.4835268064293814e-08 + ] + }, + { + "coords": [ + 6.625, + 2.384185791015625e-07 + ], + "leftHandle": [ + 6.462328592936198, + 2.384185791015625e-07 + ], + "rightHandle": [ + 7.031678517659505, + 2.384185791015625e-07 + ] + }, + { + "coords": [ + 6.833333333333333, + 2.384185791015625e-07 + ], + "leftHandle": [ + 6.5079905192057295, + 2.384185791015625e-07 + ], + "rightHandle": [ + 6.8984018961588545, + 2.384185791015625e-07 + ] + }, + { + "coords": [ + 7.0, + 1.9185245037078857e-07 + ], + "leftHandle": [ + 6.9349314371744795, + 1.9185245037078857e-07 + ], + "rightHandle": [ + 7.097602844238281, + 1.9185245037078857e-07 + ] + }, + { + "coords": [ + 7.25, + -4.353933036327362e-08 + ], + "leftHandle": [ + 7.152397155761719, + 0.003114179940894246 + ], + "rightHandle": [ + 7.331335703531901, + -0.0025952300056815147 + ] + }, + { + "coords": [ + 7.458333333333333, + 0.0 + ], + "leftHandle": [ + 7.376997629801433, + 0.0 + ], + "rightHandle": [ + 7.865011850992839, + 0.0 + ] + }, + { + "coords": [ + 8.708333333333334, + 0.0 + ], + "leftHandle": [ + 8.220319112141928, + 0.0 + ], + "rightHandle": [ + 8.82220458984375, + 0.0 + ] + }, + { + "coords": [ + 9.0, + 0.0 + ], + "leftHandle": [ + 8.886128743489584, + 0.0 + ], + "rightHandle": [ + 9.113871256510416, + 0.0 + ] + }, + { + "coords": [ + 9.291666666666666, + 0.5735764503479004 + ], + "leftHandle": [ + 9.178207397460938, + 0.3380364775657654 + ], + "rightHandle": [ + 9.428712209065756, + 0.8580812215805054 + ] + }, + { + "coords": [ + 9.583333333333334, + 0.9396926164627075 + ], + "leftHandle": [ + 9.469462076822916, + 0.9396926164627075 + ], + "rightHandle": [ + 9.664667765299479, + 0.9396926164627075 + ] + }, + { + "coords": [ + 9.791666666666666, + 0.9396926164627075 + ], + "leftHandle": [ + 9.710332234700521, + 0.9396926164627075 + ], + "rightHandle": [ + 9.873001098632812, + 0.9396926164627075 + ] + }, + { + "coords": [ + 10.0, + 0.9396926164627075 + ], + "leftHandle": [ + 9.918665568033854, + 0.9396926164627075 + ], + "rightHandle": [ + 10.081334431966146, + 0.9396926164627075 + ] + }, + { + "coords": [ + 10.208333333333334, + 0.9396926164627075 + ], + "leftHandle": [ + 10.126998901367188, + 0.9396926164627075 + ], + "rightHandle": [ + 10.289667765299479, + 0.9396926164627075 + ] + }, + { + "coords": [ + 10.416666666666666, + 0.9848077297210693 + ], + "leftHandle": [ + 10.335332234700521, + 0.9627091884613037 + ], + "rightHandle": [ + 10.498001098632812, + 1.006906270980835 + ] + }, + { + "coords": [ + 10.625, + 1.0 + ], + "leftHandle": [ + 10.543665568033854, + 1.0 + ], + "rightHandle": [ + 10.706334431966146, + 1.0 + ] + } + ] + }, + { + "channelComponentName": "Rotation X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.3090757727622986, + 0.0 + ], + "rightHandle": [ + 0.3090757528940837, + 0.0 + ] + }, + { + "coords": [ + 0.7916666666666666, + 0.0 + ], + "leftHandle": [ + 0.482590913772583, + 0.0 + ], + "rightHandle": [ + 0.9543381532033285, + 0.0 + ] + }, + { + "coords": [ + 1.2083333333333333, + 0.0 + ], + "leftHandle": [ + 1.0456618467966716, + 0.0 + ], + "rightHandle": [ + 1.2896690368652344, + 0.0 + ] + }, + { + "coords": [ + 1.4166666666666667, + 0.0 + ], + "leftHandle": [ + 1.3353309631347656, + 0.0 + ], + "rightHandle": [ + 1.4817352294921875, + 0.0 + ] + }, + { + "coords": [ + 1.5833333333333333, + 0.0 + ], + "leftHandle": [ + 1.5182647705078125, + 0.0 + ], + "rightHandle": [ + 1.6809361775716145, + 0.0 + ] + }, + { + "coords": [ + 1.8333333333333333, + 0.0 + ], + "leftHandle": [ + 1.735730489095052, + 0.0 + ], + "rightHandle": [ + 1.9146690368652344, + 0.0 + ] + }, + { + "coords": [ + 2.0416666666666665, + 0.0 + ], + "leftHandle": [ + 1.9603309631347656, + 0.0 + ], + "rightHandle": [ + 2.448345343271891, + 0.0 + ] + }, + { + "coords": [ + 3.2916666666666665, + 0.0 + ], + "leftHandle": [ + 2.8036524454752603, + 0.0 + ], + "rightHandle": [ + 3.405536651611328, + 0.0 + ] + }, + { + "coords": [ + 3.5833333333333335, + 0.0 + ], + "leftHandle": [ + 3.469463348388672, + 0.0 + ], + "rightHandle": [ + 3.6972033182779946, + 0.0 + ] + }, + { + "coords": [ + 3.875, + 4.2734766836360905e-09 + ], + "leftHandle": [ + 3.7611300150553384, + 2.906791696233313e-09 + ], + "rightHandle": [ + 3.9888699849446616, + 5.640161671038868e-09 + ] + }, + { + "coords": [ + 4.166666666666667, + 7.001254243022004e-09 + ], + "leftHandle": [ + 4.052796681722005, + 7.001254243022004e-09 + ], + "rightHandle": [ + 4.248002370198567, + 7.001254243022004e-09 + ] + }, + { + "coords": [ + 4.375, + 7.001254243022004e-09 + ], + "leftHandle": [ + 4.293664296468099, + 7.001254243022004e-09 + ], + "rightHandle": [ + 4.456335703531901, + 7.001254243022004e-09 + ] + }, + { + "coords": [ + 4.583333333333333, + 7.001254243022004e-09 + ], + "leftHandle": [ + 4.501997629801433, + 7.001254243022004e-09 + ], + "rightHandle": [ + 4.664669036865234, + 7.001254243022004e-09 + ] + }, + { + "coords": [ + 4.791666666666667, + 7.001254243022004e-09 + ], + "leftHandle": [ + 4.710330963134766, + 7.001254243022004e-09 + ], + "rightHandle": [ + 4.873002370198567, + 7.001254243022004e-09 + ] + }, + { + "coords": [ + 5.0, + 7.337388030492775e-09 + ], + "leftHandle": [ + 4.918664296468099, + 7.249677302922919e-09 + ], + "rightHandle": [ + 5.081335703531901, + 7.4250987580626315e-09 + ] + }, + { + "coords": [ + 5.208333333333333, + 7.450578376477779e-09 + ], + "leftHandle": [ + 5.126997629801433, + 7.450578376477779e-09 + ], + "rightHandle": [ + 5.598744710286458, + 7.450578376477779e-09 + ] + }, + { + "coords": [ + 6.208333333333333, + 0.0 + ], + "leftHandle": [ + 5.817921956380208, + 0.0 + ], + "rightHandle": [ + 6.371004740397136, + 0.0 + ] + }, + { + "coords": [ + 6.625, + 0.0 + ], + "leftHandle": [ + 6.462328592936198, + 0.0 + ], + "rightHandle": [ + 6.706335703531901, + 0.0 + ] + }, + { + "coords": [ + 6.833333333333333, + 0.0 + ], + "leftHandle": [ + 6.751997629801433, + 0.0 + ], + "rightHandle": [ + 6.8984018961588545, + 0.0 + ] + }, + { + "coords": [ + 7.0, + -0.1736481785774231 + ], + "leftHandle": [ + 6.9349314371744795, + -0.1736481785774231 + ], + "rightHandle": [ + 7.097602844238281, + -0.1736481785774231 + ] + }, + { + "coords": [ + 7.25, + 0.08715573698282242 + ], + "leftHandle": [ + 7.152397155761719, + 0.08715573698282242 + ], + "rightHandle": [ + 7.331335703531901, + 0.08715573698282242 + ] + }, + { + "coords": [ + 7.458333333333333, + 0.0 + ], + "leftHandle": [ + 7.376997629801433, + 0.0 + ], + "rightHandle": [ + 7.865011850992839, + 0.0 + ] + }, + { + "coords": [ + 8.708333333333334, + 0.0 + ], + "leftHandle": [ + 8.220319112141928, + 0.0 + ], + "rightHandle": [ + 8.822203318277994, + 0.0 + ] + }, + { + "coords": [ + 9.0, + 0.0 + ], + "leftHandle": [ + 8.886130015055338, + 0.0 + ], + "rightHandle": [ + 9.113869984944662, + 0.0 + ] + }, + { + "coords": [ + 9.291666666666666, + -2.410053712154081e-09 + ], + "leftHandle": [ + 9.177796681722006, + -1.8343819796484695e-09 + ], + "rightHandle": [ + 9.405536651611328, + -2.9857254446596926e-09 + ] + }, + { + "coords": [ + 9.583333333333334, + -2.9857254446596926e-09 + ], + "leftHandle": [ + 9.469463348388672, + -2.9857254446596926e-09 + ], + "rightHandle": [ + 9.664669036865234, + -2.9857254446596926e-09 + ] + }, + { + "coords": [ + 9.791666666666666, + -2.9857254446596926e-09 + ], + "leftHandle": [ + 9.710330963134766, + -2.9857254446596926e-09 + ], + "rightHandle": [ + 9.873002370198568, + -2.9857254446596926e-09 + ] + }, + { + "coords": [ + 10.0, + -2.9857254446596926e-09 + ], + "leftHandle": [ + 9.9186642964681, + -2.9857254446596926e-09 + ], + "rightHandle": [ + 10.0813357035319, + -2.9857254446596926e-09 + ] + }, + { + "coords": [ + 10.208333333333334, + -2.9857254446596926e-09 + ], + "leftHandle": [ + 10.126997629801432, + -2.9857254446596926e-09 + ], + "rightHandle": [ + 10.289669036865234, + -2.9857254446596926e-09 + ] + }, + { + "coords": [ + 10.416666666666666, + -1.5745631465335919e-09 + ], + "leftHandle": [ + 10.335330963134766, + -2.2619428552417276e-09 + ], + "rightHandle": [ + 10.498002370198568, + -8.871833823143049e-10 + ] + }, + { + "coords": [ + 10.625, + 5.355835774878415e-10 + ], + "leftHandle": [ + 10.5436642964681, + 5.355835774878415e-10 + ], + "rightHandle": [ + 10.7063357035319, + 5.355835774878415e-10 + ] + } + ] + }, + { + "channelComponentName": "Rotation Z", + "keyFrames": [ + { + "coords": [ + 0.0, + -0.0 + ], + "leftHandle": [ + -0.3090757727622986, + -0.0 + ], + "rightHandle": [ + 0.3090757528940837, + -0.0 + ] + }, + { + "coords": [ + 0.7916666666666666, + -0.0 + ], + "leftHandle": [ + 0.482590913772583, + -0.0 + ], + "rightHandle": [ + 0.9543381532033285, + -0.0 + ] + }, + { + "coords": [ + 1.2083333333333333, + -0.0 + ], + "leftHandle": [ + 1.0456618467966716, + -0.0 + ], + "rightHandle": [ + 1.2896690368652344, + -0.0 + ] + }, + { + "coords": [ + 1.4166666666666667, + -0.0 + ], + "leftHandle": [ + 1.3353309631347656, + -0.0 + ], + "rightHandle": [ + 1.4817352294921875, + -0.0 + ] + }, + { + "coords": [ + 1.5833333333333333, + -0.1736481785774231 + ], + "leftHandle": [ + 1.5182647705078125, + -0.1736481785774231 + ], + "rightHandle": [ + 1.6809361775716145, + -0.1736481785774231 + ] + }, + { + "coords": [ + 1.8333333333333333, + 0.08715575933456421 + ], + "leftHandle": [ + 1.735730489095052, + 0.08715575933456421 + ], + "rightHandle": [ + 1.9146690368652344, + 0.08715575933456421 + ] + }, + { + "coords": [ + 2.0416666666666665, + 7.450580596923828e-09 + ], + "leftHandle": [ + 1.9603309631347656, + 7.450580596923828e-09 + ], + "rightHandle": [ + 2.448345343271891, + 7.450580596923828e-09 + ] + }, + { + "coords": [ + 3.2916666666666665, + 7.450580596923828e-09 + ], + "leftHandle": [ + 2.8036524454752603, + 7.450580596923828e-09 + ], + "rightHandle": [ + 3.405536651611328, + 7.450580596923828e-09 + ] + }, + { + "coords": [ + 3.5833333333333335, + 7.450580596923828e-09 + ], + "leftHandle": [ + 3.469463348388672, + 7.450580596923828e-09 + ], + "rightHandle": [ + 3.6972033182779946, + 7.450580596923828e-09 + ] + }, + { + "coords": [ + 3.875, + 6.1031566467306675e-09 + ], + "leftHandle": [ + 3.7611300150553384, + 7.060120044144469e-09 + ], + "rightHandle": [ + 3.9888699849446616, + 5.146193249316866e-09 + ] + }, + { + "coords": [ + 4.166666666666667, + 2.5482482790550876e-09 + ], + "leftHandle": [ + 4.052796681722005, + 2.5482482790550876e-09 + ], + "rightHandle": [ + 4.248002370198567, + 2.5482482790550876e-09 + ] + }, + { + "coords": [ + 4.375, + 2.5482482790550876e-09 + ], + "leftHandle": [ + 4.293664296468099, + 2.5482482790550876e-09 + ], + "rightHandle": [ + 4.456335703531901, + 2.5482482790550876e-09 + ] + }, + { + "coords": [ + 4.583333333333333, + 2.5482482790550876e-09 + ], + "leftHandle": [ + 4.501997629801433, + 2.5482482790550876e-09 + ], + "rightHandle": [ + 4.664669036865234, + 2.5482482790550876e-09 + ] + }, + { + "coords": [ + 4.791666666666667, + 2.5482482790550876e-09 + ], + "leftHandle": [ + 4.710330963134766, + 2.5482482790550876e-09 + ], + "rightHandle": [ + 4.873002370198567, + 2.5482482790550876e-09 + ] + }, + { + "coords": [ + 5.0, + 1.2937797500001125e-09 + ], + "leftHandle": [ + 4.918664296468099, + 1.7912125116481548e-09 + ], + "rightHandle": [ + 5.081335703531901, + 7.96346932840919e-10 + ] + }, + { + "coords": [ + 5.208333333333333, + -4.440892098500626e-16 + ], + "leftHandle": [ + 5.126997629801433, + -4.440892098500626e-16 + ], + "rightHandle": [ + 5.598744710286458, + -4.440892098500626e-16 + ] + }, + { + "coords": [ + 6.208333333333333, + -0.0 + ], + "leftHandle": [ + 5.817921956380208, + -0.0 + ], + "rightHandle": [ + 6.371004740397136, + -0.0 + ] + }, + { + "coords": [ + 6.625, + -0.0 + ], + "leftHandle": [ + 6.462328592936198, + -0.0 + ], + "rightHandle": [ + 6.706335703531901, + -0.0 + ] + }, + { + "coords": [ + 6.833333333333333, + -0.0 + ], + "leftHandle": [ + 6.751997629801433, + -0.0 + ], + "rightHandle": [ + 6.8984018961588545, + -0.0 + ] + }, + { + "coords": [ + 7.0, + 2.9802322387695312e-08 + ], + "leftHandle": [ + 6.9349314371744795, + 2.9802322387695312e-08 + ], + "rightHandle": [ + 7.097602844238281, + 2.9802322387695312e-08 + ] + }, + { + "coords": [ + 7.25, + -7.450580596923828e-09 + ], + "leftHandle": [ + 7.152397155761719, + -7.450580596923828e-09 + ], + "rightHandle": [ + 7.331335703531901, + -7.450580596923828e-09 + ] + }, + { + "coords": [ + 7.458333333333333, + 7.450580596923828e-09 + ], + "leftHandle": [ + 7.376997629801433, + 7.450580596923828e-09 + ], + "rightHandle": [ + 7.865011850992839, + 7.450580596923828e-09 + ] + }, + { + "coords": [ + 8.708333333333334, + 7.450580596923828e-09 + ], + "leftHandle": [ + 8.220319112141928, + 7.450580596923828e-09 + ], + "rightHandle": [ + 8.822203318277994, + 7.450580596923828e-09 + ] + }, + { + "coords": [ + 9.0, + 7.450580596923828e-09 + ], + "leftHandle": [ + 8.886130015055338, + 7.450580596923828e-09 + ], + "rightHandle": [ + 9.113869984944662, + 7.450580596923828e-09 + ] + }, + { + "coords": [ + 9.291666666666666, + 1.0482139600753726e-08 + ], + "leftHandle": [ + 9.177796681722006, + 8.819545094240766e-09 + ], + "rightHandle": [ + 9.405536651611328, + 1.2144734107266686e-08 + ] + }, + { + "coords": [ + 9.583333333333334, + 1.5967721367360355e-08 + ], + "leftHandle": [ + 9.469463348388672, + 1.5967721367360355e-08 + ], + "rightHandle": [ + 9.664669036865234, + 1.5967721367360355e-08 + ] + }, + { + "coords": [ + 9.791666666666666, + 1.5967721367360355e-08 + ], + "leftHandle": [ + 9.710330963134766, + 1.5967721367360355e-08 + ], + "rightHandle": [ + 9.873002370198568, + 1.5967721367360355e-08 + ] + }, + { + "coords": [ + 10.0, + 1.5967721367360355e-08 + ], + "leftHandle": [ + 9.9186642964681, + 1.5967721367360355e-08 + ], + "rightHandle": [ + 10.0813357035319, + 1.5967721367360355e-08 + ] + }, + { + "coords": [ + 10.208333333333334, + 1.5967721367360355e-08 + ], + "leftHandle": [ + 10.126997629801432, + 1.5967721367360355e-08 + ], + "rightHandle": [ + 10.289669036865234, + 1.5967721367360355e-08 + ] + }, + { + "coords": [ + 10.416666666666666, + 1.7476175173669617e-08 + ], + "leftHandle": [ + 10.335330963134766, + 1.7084600401062744e-08 + ], + "rightHandle": [ + 10.498002370198568, + 1.786774994627649e-08 + ] + }, + { + "coords": [ + 10.625, + 1.7973679433680445e-08 + ], + "leftHandle": [ + 10.5436642964681, + 1.7973679433680445e-08 + ], + "rightHandle": [ + 10.7063357035319, + 1.7973679433680445e-08 + ] + } + ] + }, + { + "channelComponentName": "Rotation Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.3090757727622986, + 0.0 + ], + "rightHandle": [ + 0.3090757528940837, + 0.0 + ] + }, + { + "coords": [ + 0.7916666666666666, + 0.0 + ], + "leftHandle": [ + 0.482590913772583, + 0.0 + ], + "rightHandle": [ + 0.9543381532033285, + 0.0 + ] + }, + { + "coords": [ + 1.2083333333333333, + 0.0 + ], + "leftHandle": [ + 1.0456618467966716, + 0.0 + ], + "rightHandle": [ + 1.2896690368652344, + 0.0 + ] + }, + { + "coords": [ + 1.4166666666666667, + 0.0 + ], + "leftHandle": [ + 1.3353309631347656, + 0.0 + ], + "rightHandle": [ + 1.4817352294921875, + 0.0 + ] + }, + { + "coords": [ + 1.5833333333333333, + 0.0 + ], + "leftHandle": [ + 1.5182647705078125, + 0.0 + ], + "rightHandle": [ + 1.6809361775716145, + 0.0 + ] + }, + { + "coords": [ + 1.8333333333333333, + 0.0 + ], + "leftHandle": [ + 1.735730489095052, + 0.0 + ], + "rightHandle": [ + 1.9146690368652344, + 0.0 + ] + }, + { + "coords": [ + 2.0416666666666665, + 0.0 + ], + "leftHandle": [ + 1.9603309631347656, + 0.0 + ], + "rightHandle": [ + 2.448345343271891, + 0.0 + ] + }, + { + "coords": [ + 3.2916666666666665, + 0.0 + ], + "leftHandle": [ + 2.8036524454752603, + 0.0 + ], + "rightHandle": [ + 3.405536651611328, + 0.0 + ] + }, + { + "coords": [ + 3.5833333333333335, + 0.0 + ], + "leftHandle": [ + 3.469463348388672, + 0.0 + ], + "rightHandle": [ + 3.6972033182779946, + 0.0 + ] + }, + { + "coords": [ + 3.875, + 0.5735764503479004 + ], + "leftHandle": [ + 3.7611300150553384, + 0.3901430368423462 + ], + "rightHandle": [ + 3.9888699849446616, + 0.7570098638534546 + ] + }, + { + "coords": [ + 4.166666666666667, + 0.9396926164627075 + ], + "leftHandle": [ + 4.052796681722005, + 0.9396926164627075 + ], + "rightHandle": [ + 4.248002370198567, + 0.9396926164627075 + ] + }, + { + "coords": [ + 4.375, + 0.9396926164627075 + ], + "leftHandle": [ + 4.293664296468099, + 0.9396926164627075 + ], + "rightHandle": [ + 4.456335703531901, + 0.9396926164627075 + ] + }, + { + "coords": [ + 4.583333333333333, + 0.9396926164627075 + ], + "leftHandle": [ + 4.501997629801433, + 0.9396926164627075 + ], + "rightHandle": [ + 4.664669036865234, + 0.9396926164627075 + ] + }, + { + "coords": [ + 4.791666666666667, + 0.9396926164627075 + ], + "leftHandle": [ + 4.710330963134766, + 0.9396926164627075 + ], + "rightHandle": [ + 4.873002370198567, + 0.9396926164627075 + ] + }, + { + "coords": [ + 5.0, + 0.9848077297210693 + ], + "leftHandle": [ + 4.918664296468099, + 0.9730353951454163 + ], + "rightHandle": [ + 5.081335703531901, + 0.9965800642967224 + ] + }, + { + "coords": [ + 5.208333333333333, + 1.0 + ], + "leftHandle": [ + 5.126997629801433, + 1.0 + ], + "rightHandle": [ + 5.598744710286458, + 1.0 + ] + }, + { + "coords": [ + 6.208333333333333, + 1.0 + ], + "leftHandle": [ + 5.817921956380208, + 1.0 + ], + "rightHandle": [ + 6.371004740397136, + 1.0 + ] + }, + { + "coords": [ + 6.625, + 1.000000238418579 + ], + "leftHandle": [ + 6.462328592936198, + 1.000000238418579 + ], + "rightHandle": [ + 7.031678517659505, + 1.000000238418579 + ] + }, + { + "coords": [ + 6.833333333333333, + 1.000000238418579 + ], + "leftHandle": [ + 6.5079905192057295, + 1.000000238418579 + ], + "rightHandle": [ + 6.8984018961588545, + 1.000000238418579 + ] + }, + { + "coords": [ + 7.0, + 1.0 + ], + "leftHandle": [ + 6.9349314371744795, + 1.0 + ], + "rightHandle": [ + 7.097605387369792, + 1.0 + ] + }, + { + "coords": [ + 7.25, + 1.0 + ], + "leftHandle": [ + 7.152397155761719, + 1.0 + ], + "rightHandle": [ + 7.331335703531901, + 1.0 + ] + }, + { + "coords": [ + 7.458333333333333, + 1.000000238418579 + ], + "leftHandle": [ + 7.376997629801433, + 1.000000238418579 + ], + "rightHandle": [ + 7.865011850992839, + 1.000000238418579 + ] + }, + { + "coords": [ + 8.708333333333334, + 1.000000238418579 + ], + "leftHandle": [ + 8.220319112141928, + 1.000000238418579 + ], + "rightHandle": [ + 8.82220458984375, + 1.000000238418579 + ] + }, + { + "coords": [ + 9.0, + 1.000000238418579 + ], + "leftHandle": [ + 8.886128743489584, + 1.000000238418579 + ], + "rightHandle": [ + 9.113871256510416, + 1.000000238418579 + ] + }, + { + "coords": [ + 9.291666666666666, + 0.8191520571708679 + ], + "leftHandle": [ + 9.17779541015625, + 0.932508647441864 + ], + "rightHandle": [ + 9.405537923177084, + 0.7057954668998718 + ] + }, + { + "coords": [ + 9.583333333333334, + 0.3420201241970062 + ], + "leftHandle": [ + 9.469462076822916, + 0.3420201241970062 + ], + "rightHandle": [ + 9.664667765299479, + 0.3420201241970062 + ] + }, + { + "coords": [ + 9.791666666666666, + 0.3420201241970062 + ], + "leftHandle": [ + 9.710332234700521, + 0.3420201241970062 + ], + "rightHandle": [ + 9.873001098632812, + 0.3420201241970062 + ] + }, + { + "coords": [ + 10.0, + 0.3420201241970062 + ], + "leftHandle": [ + 9.918665568033854, + 0.3420201241970062 + ], + "rightHandle": [ + 10.081334431966146, + 0.3420201241970062 + ] + }, + { + "coords": [ + 10.208333333333334, + 0.3420201241970062 + ], + "leftHandle": [ + 10.126998901367188, + 0.3420201241970062 + ], + "rightHandle": [ + 10.289667765299479, + 0.3420201241970062 + ] + }, + { + "coords": [ + 10.416666666666666, + 0.1736481785774231 + ], + "leftHandle": [ + 10.335413614908854, + 0.2643083930015564 + ], + "rightHandle": [ + 10.498001098632812, + 0.08289717137813568 + ] + }, + { + "coords": [ + 10.625, + 0.0 + ], + "leftHandle": [ + 10.543665568033854, + 0.0 + ], + "rightHandle": [ + 10.706334431966146, + 0.0 + ] + } + ] + } + ], + "channelName": "Rotation", + "jointIndex": 0 + } + ] + } + ] +} diff --git a/tests/manual/skinned-mesh/main.cpp b/tests/manual/skinned-mesh/main.cpp index dba6e0bff..8e2ebcbfb 100644 --- a/tests/manual/skinned-mesh/main.cpp +++ b/tests/manual/skinned-mesh/main.cpp @@ -49,12 +49,14 @@ ****************************************************************************/ #include <Qt3DQuickExtras/qt3dquickwindow.h> +#include <Qt3DAnimation/QAnimationAspect> #include <QGuiApplication> int main(int argc, char* argv[]) { QGuiApplication app(argc, argv); Qt3DExtras::Quick::Qt3DQuickWindow view; + view.registerAspect(new Qt3DAnimation::QAnimationAspect()); view.setSource(QUrl("qrc:/main.qml")); view.show(); diff --git a/tests/manual/skinned-mesh/main.qml b/tests/manual/skinned-mesh/main.qml index 6e8adbf50..174d54f83 100644 --- a/tests/manual/skinned-mesh/main.qml +++ b/tests/manual/skinned-mesh/main.qml @@ -51,6 +51,7 @@ import Qt3D.Core 2.10 import Qt3D.Render 2.10 import Qt3D.Input 2.0 +import Qt3D.Animation 2.10 import Qt3D.Extras 2.10 import QtQuick 2.9 @@ -61,10 +62,150 @@ DefaultSceneEntity { id: skinnedPbrEffect } + Timer { + interval: 2000 + running: true + repeat: false + onTriggered: { + animator1.running = true + animator2.running = true + animator3.running = true + animator4.running = true + animator5.running = true + } + } + + SkinnedEntity { + id: riggedFigure1 + effect: skinnedPbrEffect + source: "qrc:/assets/gltf/2.0/RiggedFigure/RiggedFigure.gltf" + baseColor: "red" + + components: [ +// ClipAnimator { +// loops: 3 +// clip: AnimationClipLoader { source: "qrc:/jump.json" } +// channelMapper: ChannelMapper { +// mappings: [ +// SkeletonChannelMapping { target: riggedFigure.skeleton } +// ] +// } +// } + BlendedClipAnimator { + id: animator1 + loops: 5 + blendTree: ClipBlendValue { + clip: AnimationClipLoader { source: "qrc:/jump.json" } + } + channelMapper: ChannelMapper { + mappings: [ + SkeletonMapping { skeleton: riggedFigure1.skeleton } + ] + } + + onRunningChanged: console.log("running = " + running) + } + ] + } + SkinnedEntity { - id: riggedFigure + id: riggedFigure2 effect: skinnedPbrEffect source: "qrc:/assets/gltf/2.0/RiggedFigure/RiggedFigure.gltf" + baseColor: "purple" + transform.translation: Qt.vector3d(0.0, 0.0, -1.0); + + components: [ + BlendedClipAnimator { + id: animator2 + loops: 5 + blendTree: ClipBlendValue { + clip: AnimationClipLoader { source: "qrc:/jump.json" } + } + channelMapper: ChannelMapper { + mappings: [ + SkeletonMapping { skeleton: riggedFigure2.skeleton } + ] + } + + onRunningChanged: console.log("running = " + running) + } + ] + } + + SkinnedEntity { + id: riggedFigure3 + effect: skinnedPbrEffect + source: "qrc:/assets/gltf/2.0/RiggedFigure/RiggedFigure.gltf" + baseColor: "blue" + transform.translation: Qt.vector3d(0.0, 0.0, -2.0); + + components: [ + BlendedClipAnimator { + id: animator3 + loops: 5 + blendTree: ClipBlendValue { + clip: AnimationClipLoader { source: "qrc:/jump.json" } + } + channelMapper: ChannelMapper { + mappings: [ + SkeletonMapping { skeleton: riggedFigure3.skeleton } + ] + } + + onRunningChanged: console.log("running = " + running) + } + ] + } + + SkinnedEntity { + id: riggedFigure4 + effect: skinnedPbrEffect + source: "qrc:/assets/gltf/2.0/RiggedFigure/RiggedFigure.gltf" + baseColor: "green" + transform.translation: Qt.vector3d(0.0, 0.0, -3.0); + + components: [ + BlendedClipAnimator { + id: animator4 + loops: 5 + blendTree: ClipBlendValue { + clip: AnimationClipLoader { source: "qrc:/jump.json" } + } + channelMapper: ChannelMapper { + mappings: [ + SkeletonMapping { skeleton: riggedFigure4.skeleton } + ] + } + + onRunningChanged: console.log("running = " + running) + } + ] + } + + SkinnedEntity { + id: riggedFigure5 + effect: skinnedPbrEffect + source: "qrc:/assets/gltf/2.0/RiggedFigure/RiggedFigure.gltf" + baseColor: "orange" + transform.translation: Qt.vector3d(0.0, 0.0, -4.0); + + components: [ + BlendedClipAnimator { + id: animator5 + loops: 5 + blendTree: ClipBlendValue { + clip: AnimationClipLoader { source: "qrc:/jump.json" } + } + channelMapper: ChannelMapper { + mappings: [ + SkeletonMapping { skeleton: riggedFigure5.skeleton } + ] + } + + onRunningChanged: console.log("running = " + running) + } + ] } SkinnedEntity { diff --git a/tests/manual/skinned-mesh/skinned-mesh.pro b/tests/manual/skinned-mesh/skinned-mesh.pro index dc5fd3730..380b1bb35 100644 --- a/tests/manual/skinned-mesh/skinned-mesh.pro +++ b/tests/manual/skinned-mesh/skinned-mesh.pro @@ -2,7 +2,7 @@ error( "Couldn't find the manual.pri file!" ) } -QT += 3dcore 3drender 3dinput 3dquick qml quick 3dquickextras +QT += 3dcore 3drender 3dinput 3dquick qml quick 3dquickextras 3danimation SOURCES += \ main.cpp diff --git a/tests/manual/skinned-mesh/skinned-mesh.qrc b/tests/manual/skinned-mesh/skinned-mesh.qrc index e062e6be4..f34f93f37 100644 --- a/tests/manual/skinned-mesh/skinned-mesh.qrc +++ b/tests/manual/skinned-mesh/skinned-mesh.qrc @@ -5,5 +5,6 @@ <file>skinnedPbr.vert</file> <file>SkinnedEntity.qml</file> <file>SkinnedPbrEffect.qml</file> + <file>jump.json</file> </qresource> </RCC> |