summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Harmer <sean.harmer@kdab.com>2018-01-22 12:37:25 +0000
committerSean Harmer <sean.harmer@kdab.com>2018-01-22 12:37:25 +0000
commit2d264ae985cf0e83b55959549093aed8c19298aa (patch)
treedc6b8553c433d9fa109ff02befa82ab9c1289699
parent2b19bde378e084331b1b7ba9aa076270492999bb (diff)
parent10d54271444d8a8de6a25cbf18fcd78f073a5a68 (diff)
downloadqt3d-2d264ae985cf0e83b55959549093aed8c19298aa.tar.gz
Merge branch '5.9' into 5.10
Conflicts: src/render/frontend/qcamera.cpp tests/auto/render/render.pro Change-Id: I8f848a1f863d07eecb328965fbe27d74b8d442f1
-rw-r--r--src/render/backend/renderview.cpp13
-rw-r--r--src/render/frontend/qcamera.cpp67
-rw-r--r--src/render/frontend/qcamera_p.h8
-rw-r--r--src/render/jobs/loadgeometryjob.cpp1
-rw-r--r--tests/auto/render/qcamera/qcamera.pro12
-rw-r--r--tests/auto/render/qcamera/tst_qcamera.cpp244
-rw-r--r--tests/auto/render/render.pro3
7 files changed, 323 insertions, 25 deletions
diff --git a/src/render/backend/renderview.cpp b/src/render/backend/renderview.cpp
index 31de8c1c8..f488b7e44 100644
--- a/src/render/backend/renderview.cpp
+++ b/src/render/backend/renderview.cpp
@@ -732,7 +732,18 @@ QVector<RenderCommand *> RenderView::buildComputeRenderCommands(const QVector<En
void RenderView::updateMatrices()
{
if (m_data.m_renderCameraNode && m_data.m_renderCameraLens && m_data.m_renderCameraLens->isEnabled()) {
- setViewMatrix(*m_data.m_renderCameraNode->worldTransform());
+ const QMatrix4x4 cameraWorld = *(m_data.m_renderCameraNode->worldTransform());
+
+ const QVector4D position = cameraWorld * QVector4D(0.0f, 0.0f, 0.0f, 1.0f);
+ // OpenGL convention is looking down -Z
+ const QVector4D viewDirection = cameraWorld * QVector4D(0.0f, 0.0f, -1.0f, 0.0f);
+ const QVector4D upVector = cameraWorld * QVector4D(0.0f, 1.0f, 0.0f, 0.0f);
+
+ QMatrix4x4 m;
+ m.lookAt(position.toVector3D(), (position + viewDirection).toVector3D(), upVector.toVector3D());
+
+ setViewMatrix(m);
+
setViewProjectionMatrix(m_data.m_renderCameraLens->projection() * viewMatrix());
//To get the eyePosition of the camera, we need to use the inverse of the
//camera's worldTransform matrix.
diff --git a/src/render/frontend/qcamera.cpp b/src/render/frontend/qcamera.cpp
index 13d689e0e..73ec2c71f 100644
--- a/src/render/frontend/qcamera.cpp
+++ b/src/render/frontend/qcamera.cpp
@@ -59,7 +59,28 @@ QCameraPrivate::QCameraPrivate()
, m_lens(new QCameraLens())
, m_transform(new Qt3DCore::QTransform())
{
- updateViewMatrix();
+ updateViewMatrixAndTransform(false);
+}
+
+void QCameraPrivate::updateViewMatrixAndTransform(bool doEmit)
+{
+ Q_Q(QCamera);
+
+ const QVector3D viewDirection = (m_viewCenter - m_position).normalized();
+
+ QMatrix4x4 transformMatrix;
+ transformMatrix.translate(m_position);
+
+ // Negative viewDirection because OpenGL convention is looking down -Z
+ transformMatrix.rotate(QQuaternion::fromDirection(-viewDirection, m_upVector.normalized()));
+
+ m_transform->setMatrix(transformMatrix);
+
+ QMatrix4x4 viewMatrix;
+ viewMatrix.lookAt(m_position, m_viewCenter, m_upVector);
+ m_viewMatrix = viewMatrix;
+ if (doEmit)
+ emit q->viewMatrixChanged();
}
/*!
@@ -292,29 +313,35 @@ QCameraPrivate::QCameraPrivate()
/*!
* \qmlproperty vector3d Qt3D.Render::Camera::position
- * Holds the current position of the camera.
+ * Holds the current position of the camera in coordinates relative to
+ * the parent entity.
*/
/*!
* \qmlproperty vector3d Qt3D.Render::Camera::upVector
- * Holds the current up vector of the camera.
+ * Holds the current up vector of the camera in coordinates relative to
+ * the parent entity.
*/
/*!
* \qmlproperty vector3d Qt3D.Render::Camera::viewCenter
- * Holds the current view center of the camera.
+ * Holds the current view center of the camera in coordinates relative to
+ * the parent entity.
* \readonly
*/
/*!
* \qmlproperty vector3d Qt3D.Render::Camera::viewVector
- * Holds the camera's view vector.
+ * Holds the camera's view vector in coordinates relative to
+ * the parent entity.
* \readonly
*/
/*!
* \qmlproperty matrix4x4 Qt3D.Render::Camera::viewMatrix
- * Holds the camera's view matrix.
+ * \deprecated
+ * Holds the camera's view matrix in coordinates relative
+ * to the parent entity.
* \readonly
*/
@@ -384,27 +411,33 @@ QCameraPrivate::QCameraPrivate()
/*!
* \property QCamera::position
- * Holds the camera's position.
+ * Holds the camera's position in coordinates relative to
+ * the parent entity.
*/
/*!
* \property QCamera::upVector
- * Holds the camera's up vector.
+ * Holds the camera's up vector in coordinates relative to
+ * the parent entity.
*/
/*!
* \property QCamera::viewCenter
- * Holds the camera's view center.
+ * Holds the camera's view center in coordinates relative to
+ * the parent entity.
*/
/*!
* \property QCamera::viewVector
- * Holds the camera's view vector.
+ * Holds the camera's view vector in coordinates relative to
+ * the parent entity.
*/
/*!
* \property QCamera::viewMatrix
- * Holds the camera's view matrix.
+ * \deprecated
+ * Holds the camera's view matrix in coordinates relative to
+ * the parent entity.
*/
/*!
@@ -426,7 +459,7 @@ QCamera::QCamera(Qt3DCore::QNode *parent)
QObject::connect(d_func()->m_lens, SIGNAL(projectionMatrixChanged(const QMatrix4x4 &)), this, SIGNAL(projectionMatrixChanged(const QMatrix4x4 &)));
QObject::connect(d_func()->m_lens, SIGNAL(exposureChanged(float)), this, SIGNAL(exposureChanged(float)));
QObject::connect(d_func()->m_lens, &QCameraLens::viewSphere, this, &QCamera::viewSphere);
- QObject::connect(d_func()->m_transform, SIGNAL(matrixChanged()), this, SIGNAL(viewMatrixChanged()));
+
addComponent(d_func()->m_lens);
addComponent(d_func()->m_transform);
}
@@ -455,7 +488,7 @@ QCamera::QCamera(QCameraPrivate &dd, Qt3DCore::QNode *parent)
QObject::connect(d_func()->m_lens, SIGNAL(topChanged(float)), this, SIGNAL(topChanged(float)));
QObject::connect(d_func()->m_lens, SIGNAL(projectionMatrixChanged(const QMatrix4x4 &)), this, SIGNAL(projectionMatrixChanged(const QMatrix4x4 &)));
QObject::connect(d_func()->m_lens, &QCameraLens::viewSphere, this, &QCamera::viewSphere);
- QObject::connect(d_func()->m_transform, SIGNAL(matrixChanged()), this, SIGNAL(viewMatrixChanged()));
+
addComponent(d_func()->m_lens);
addComponent(d_func()->m_transform);
}
@@ -894,7 +927,7 @@ void QCamera::setPosition(const QVector3D &position)
d->m_viewMatrixDirty = true;
emit positionChanged(position);
emit viewVectorChanged(d->m_cameraToCenter);
- d->updateViewMatrix();
+ d->updateViewMatrixAndTransform();
}
}
@@ -914,7 +947,7 @@ void QCamera::setUpVector(const QVector3D &upVector)
d->m_upVector = upVector;
d->m_viewMatrixDirty = true;
emit upVectorChanged(upVector);
- d->updateViewMatrix();
+ d->updateViewMatrixAndTransform();
}
}
@@ -936,7 +969,7 @@ void QCamera::setViewCenter(const QVector3D &viewCenter)
d->m_viewMatrixDirty = true;
emit viewCenterChanged(viewCenter);
emit viewVectorChanged(d->m_cameraToCenter);
- d->updateViewMatrix();
+ d->updateViewMatrixAndTransform();
}
}
@@ -955,7 +988,7 @@ QVector3D QCamera::viewVector() const
QMatrix4x4 QCamera::viewMatrix() const
{
Q_D(const QCamera);
- return d->m_transform->matrix();
+ return d->m_viewMatrix;
}
} // Qt3DRender
diff --git a/src/render/frontend/qcamera_p.h b/src/render/frontend/qcamera_p.h
index 2ef53818c..1e8464d05 100644
--- a/src/render/frontend/qcamera_p.h
+++ b/src/render/frontend/qcamera_p.h
@@ -67,12 +67,7 @@ public:
Q_DECLARE_PUBLIC(QCamera)
- void updateViewMatrix()
- {
- QMatrix4x4 m;
- m.lookAt(m_position, m_viewCenter, m_upVector);
- m_transform->setMatrix(m);
- }
+ void updateViewMatrixAndTransform(bool doEmit = true);
QVector3D m_position;
QVector3D m_viewCenter;
@@ -84,6 +79,7 @@ public:
// Components
QCameraLens *m_lens;
Qt3DCore::QTransform *m_transform;
+ QMatrix4x4 m_viewMatrix;
};
} // namespace Qt3DRender
diff --git a/src/render/jobs/loadgeometryjob.cpp b/src/render/jobs/loadgeometryjob.cpp
index 106ccbd86..d28b15a7c 100644
--- a/src/render/jobs/loadgeometryjob.cpp
+++ b/src/render/jobs/loadgeometryjob.cpp
@@ -51,6 +51,7 @@ namespace Render {
LoadGeometryJob::LoadGeometryJob(const HGeometryRenderer &handle)
: QAspectJob()
, m_handle(handle)
+ , m_nodeManagers(nullptr)
{
SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadGeometry, 0);
}
diff --git a/tests/auto/render/qcamera/qcamera.pro b/tests/auto/render/qcamera/qcamera.pro
new file mode 100644
index 000000000..0ce2d23bc
--- /dev/null
+++ b/tests/auto/render/qcamera/qcamera.pro
@@ -0,0 +1,12 @@
+TEMPLATE = app
+
+TARGET = tst_qcamera
+
+QT += 3dcore 3dcore-private 3drender 3drender-private testlib
+
+CONFIG += testcase
+
+SOURCES += tst_qcamera.cpp
+
+include(../../core/common/common.pri)
+include(../commons/commons.pri)
diff --git a/tests/auto/render/qcamera/tst_qcamera.cpp b/tests/auto/render/qcamera/tst_qcamera.cpp
new file mode 100644
index 000000000..82a6d8b89
--- /dev/null
+++ b/tests/auto/render/qcamera/tst_qcamera.cpp
@@ -0,0 +1,244 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** 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 <QObject>
+#include <QSignalSpy>
+
+#include <qbackendnodetester.h>
+
+#include <Qt3DCore/QEntity>
+#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
+#include <Qt3DCore/private/qaspectjobmanager_p.h>
+#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DCore/qnodecreatedchange.h>
+#include <Qt3DCore/qtransform.h>
+
+#include <Qt3DRender/qcamera.h>
+#include <Qt3DRender/qcameralens.h>
+#include <Qt3DRender/qrenderaspect.h>
+#include <Qt3DRender/private/entity_p.h>
+#include <Qt3DRender/private/qcamera_p.h>
+#include <Qt3DRender/private/cameralens_p.h>
+#include <Qt3DRender/private/managers_p.h>
+#include <Qt3DRender/private/nodemanagers_p.h>
+#include <Qt3DRender/private/transform_p.h>
+#include <Qt3DRender/private/qrenderaspect_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+class TestAspect : public Qt3DRender::QRenderAspect
+{
+public:
+ TestAspect(Qt3DCore::QNode *root)
+ : Qt3DRender::QRenderAspect(Qt3DRender::QRenderAspect::Synchronous)
+ , m_sceneRoot(nullptr)
+ {
+ QRenderAspect::onRegistered();
+
+ const Qt3DCore::QNodeCreatedChangeGenerator generator(root);
+ const QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges = generator.creationChanges();
+
+ d_func()->setRootAndCreateNodes(qobject_cast<Qt3DCore::QEntity *>(root), creationChanges);
+
+ Render::Entity *rootEntity = nodeManagers()->lookupResource<Render::Entity, Render::EntityManager>(rootEntityId());
+ Q_ASSERT(rootEntity);
+ m_sceneRoot = rootEntity;
+ }
+
+ ~TestAspect()
+ {
+ QRenderAspect::onUnregistered();
+ }
+
+ void onRegistered() { QRenderAspect::onRegistered(); }
+ void onUnregistered() { QRenderAspect::onUnregistered(); }
+
+ Qt3DRender::Render::NodeManagers *nodeManagers() const { return d_func()->m_renderer->nodeManagers(); }
+ Qt3DRender::Render::FrameGraphNode *frameGraphRoot() const { return d_func()->m_renderer->frameGraphRoot(); }
+ Qt3DRender::Render::RenderSettings *renderSettings() const { return d_func()->m_renderer->settings(); }
+ Qt3DRender::Render::Entity *sceneRoot() const { return m_sceneRoot; }
+
+private:
+ Render::Entity *m_sceneRoot;
+};
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+namespace {
+
+void runRequiredJobs(Qt3DRender::TestAspect *test)
+{
+ Qt3DRender::Render::UpdateWorldTransformJob updateWorldTransform;
+ updateWorldTransform.setRoot(test->sceneRoot());
+ updateWorldTransform.run();
+}
+
+void fuzzyCompareMatrix(const QMatrix4x4 &a, const QMatrix4x4 &b)
+{
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ // Fuzzy comparison. qFuzzyCompare is not suitable because zero is compared to small numbers.
+ QVERIFY(qAbs(a(i, j) - b(i, j)) < 1.0e-6f);
+ }
+ }
+}
+
+} // anonymous
+
+class tst_QCamera : public Qt3DCore::QBackendNodeTester
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+
+ void initTestCase()
+ {
+ }
+
+ void checkDefaultConstruction()
+ {
+ // GIVEN
+ Qt3DRender::QCamera camera;
+
+ // THEN
+ QCOMPARE(camera.projectionType(), Qt3DRender::QCameraLens::PerspectiveProjection);
+ QCOMPARE(camera.nearPlane(), 0.1f);
+ QCOMPARE(camera.farPlane(), 1024.0f);
+ QCOMPARE(camera.fieldOfView(), 25.0f);
+ QCOMPARE(camera.aspectRatio(), 1.0f);
+ QCOMPARE(camera.left(), -0.5f);
+ QCOMPARE(camera.right(), 0.5f);
+ QCOMPARE(camera.bottom(), -0.5f);
+ QCOMPARE(camera.top(), 0.5f);
+ QCOMPARE(camera.exposure(), 0.0f);
+ }
+
+ void checkTransformWithParent()
+ {
+ // GIVEN
+ QScopedPointer<Qt3DCore::QEntity> root(new Qt3DCore::QEntity);
+
+ QScopedPointer<Qt3DCore::QEntity> parent(new Qt3DCore::QEntity(root.data()));
+ Qt3DCore::QTransform *parentTransform = new Qt3DCore::QTransform();
+ parentTransform->setTranslation(QVector3D(10, 9, 8));
+ parentTransform->setRotationX(10.f);
+ parentTransform->setRotationY(20.f);
+ parentTransform->setRotationZ(30.f);
+ parent->addComponent(parentTransform);
+
+ QScopedPointer<Qt3DRender::QCamera> camera(new Qt3DRender::QCamera(parent.data()));
+
+ QScopedPointer<Qt3DRender::TestAspect> test(new Qt3DRender::TestAspect(root.data()));
+ runRequiredJobs(test.data());
+
+ Qt3DRender::Render::Entity *cameraEntity = test->nodeManagers()->lookupResource<Qt3DRender::Render::Entity, Qt3DRender::Render::EntityManager>(camera->id());
+
+ // THEN
+ QVERIFY(qFuzzyCompare(*cameraEntity->worldTransform(), parentTransform->matrix()));
+ }
+
+ void checkTransformWithParentAndLookAt()
+ {
+ // GIVEN
+ QScopedPointer<Qt3DCore::QEntity> root(new Qt3DCore::QEntity);
+
+ QScopedPointer<Qt3DCore::QEntity> parent(new Qt3DCore::QEntity(root.data()));
+ Qt3DCore::QTransform *parentTransform = new Qt3DCore::QTransform();
+ parentTransform->setRotationZ(90.f);
+ parent->addComponent(parentTransform);
+
+ QScopedPointer<Qt3DRender::QCamera> camera(new Qt3DRender::QCamera(parent.data()));
+ camera->setPosition(QVector3D(1.f, 0.f, 0.f));
+ camera->setViewCenter(QVector3D(1.f, 0.f, -1.f)); // look in -z
+ camera->setUpVector(QVector3D(0.f, 1.f, 0.f));
+
+ QScopedPointer<Qt3DRender::TestAspect> test(new Qt3DRender::TestAspect(root.data()));
+ runRequiredJobs(test.data());
+
+ Qt3DRender::Render::Entity *cameraEntity = test->nodeManagers()->lookupResource<Qt3DRender::Render::Entity, Qt3DRender::Render::EntityManager>(camera->id());
+
+ // THEN
+ QMatrix4x4 m;
+ m.translate(0.f, 1.f, 0.f); // 90 deg z-rotation + x-translation = y-translation
+ m.rotate(90.f, QVector3D(0.f, 0.f, 1.f));
+
+ const QMatrix4x4 worldTransform = *cameraEntity->worldTransform();
+ fuzzyCompareMatrix(worldTransform, m);
+
+ }
+
+ void checkTransformOfChild()
+ {
+ // GIVEN
+ QScopedPointer<Qt3DCore::QEntity> root(new Qt3DCore::QEntity);
+
+ QScopedPointer<Qt3DCore::QEntity> parent(new Qt3DCore::QEntity(root.data()));
+ Qt3DCore::QTransform *parentTransform = new Qt3DCore::QTransform();
+ parentTransform->setTranslation(QVector3D(10, 9, 8));
+ parent->addComponent(parentTransform);
+
+ QScopedPointer<Qt3DRender::QCamera> camera(new Qt3DRender::QCamera(parent.data()));
+ camera->setPosition(QVector3D(2.f, 3.f, 4.f));
+ camera->setViewCenter(QVector3D(1.f, 3.f, 4.f)); // looking in -x = 90 deg y-rotation
+ camera->setUpVector(QVector3D(0.f, 1.f, 0.f));
+
+ // Child coordinate system:
+ // y = camera up vector = global y
+ // z = negative camera look direction = global x
+ // x = y cross z = global -z
+ QScopedPointer<Qt3DCore::QEntity> child(new Qt3DCore::QEntity(camera.data()));
+ Qt3DCore::QTransform *childTransform = new Qt3DCore::QTransform();
+ childTransform->setTranslation(QVector3D(1.f, 2.f, 3.f));
+ child->addComponent(childTransform);
+
+ QScopedPointer<Qt3DRender::TestAspect> test(new Qt3DRender::TestAspect(root.data()));
+ runRequiredJobs(test.data());
+
+ Qt3DRender::Render::Entity *childEntity = test->nodeManagers()->lookupResource<Qt3DRender::Render::Entity, Qt3DRender::Render::EntityManager>(child->id());
+
+ // THEN
+ QMatrix4x4 m;
+ m.translate(10.f, 9.f, 8.f); // parent's world translation
+ m.translate(2.f, 3.f, 4.f); // camera's world translation
+ m.translate(3.f, 2.f, -1.f); // child's world translation
+ m.rotate(90.f, QVector3D(0.f, 1.f, 0.f)); // camera's rotation
+
+ fuzzyCompareMatrix(*childEntity->worldTransform(), m);
+ }
+};
+
+
+QTEST_MAIN(tst_QCamera)
+
+#include "tst_qcamera.moc"
diff --git a/tests/auto/render/render.pro b/tests/auto/render/render.pro
index 32a7b35fc..da01dd95f 100644
--- a/tests/auto/render/render.pro
+++ b/tests/auto/render/render.pro
@@ -109,7 +109,8 @@ qtConfig(private_tests) {
proximityfilter \
proximityfiltering \
qblitframebuffer \
- blitframebuffer
+ blitframebuffer \
+ qcamera
QT_FOR_CONFIG = 3dcore-private
qtConfig(qt3d-extras) {