diff options
135 files changed, 3023 insertions, 1471 deletions
diff --git a/src/animation/doc/src/qt3danimation-module.qdoc b/src/animation/doc/src/qt3danimation-module.qdoc index a056447e8..3aaf819db 100644 --- a/src/animation/doc/src/qt3danimation-module.qdoc +++ b/src/animation/doc/src/qt3danimation-module.qdoc @@ -29,8 +29,9 @@ /*! \module Qt3DAnimation \title Qt 3D Animation C++ Classes + \keyword Qt 3D Animation - \brief The Qt 3D Animation modules provides a set of prebuilt elements to help + \brief The Qt 3D Animation module provides a set of prebuilt elements to help you get started with Qt 3D. This module is still in tech preview. This means it is unstable, likely to diff --git a/src/animation/frontend/qanimationcliploader.cpp b/src/animation/frontend/qanimationcliploader.cpp index 8c59a4e10..f71ca40f7 100644 --- a/src/animation/frontend/qanimationcliploader.cpp +++ b/src/animation/frontend/qanimationcliploader.cpp @@ -61,7 +61,7 @@ void QAnimationClipLoaderPrivate::setStatus(QAnimationClipLoader::Status status) } /*! - \enum QAnimationClipLoader::Status + \enum Qt3DAnimation::QAnimationClipLoader::Status This enum identifies the status of animation clip. @@ -70,7 +70,17 @@ void QAnimationClipLoaderPrivate::setStatus(QAnimationClipLoader::Status status) \value Error An error occurred while loading the clip */ /*! - \class QAnimationClipLoader + \property Qt3DAnimation::QAnimationClipLoader::status + + This property contains the status of the animation clip. +*/ +/*! + \property Qt3DAnimation::QAnimationClipLoader::source + + Holds the source URL from which to load the animation clip. +*/ +/*! + \class Qt3DAnimation::QAnimationClipLoader \inherits QAbstractAnimationClip \inmodule Qt3DAnimation \brief Enables loading key frame animation data from a file @@ -103,6 +113,9 @@ QUrl QAnimationClipLoader::source() const return d->m_source; } +/*! + Returns the status of the animation clip. +*/ QAnimationClipLoader::Status QAnimationClipLoader::status() const { Q_D(const QAnimationClipLoader); @@ -119,6 +132,9 @@ void QAnimationClipLoader::setSource(const QUrl &source) emit sourceChanged(source); } +/*! + \internal +*/ void QAnimationClipLoader::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) { Q_D(QAnimationClipLoader); diff --git a/src/animation/frontend/qclipblendvalue.cpp b/src/animation/frontend/qclipblendvalue.cpp index a17c63a69..c20609050 100644 --- a/src/animation/frontend/qclipblendvalue.cpp +++ b/src/animation/frontend/qclipblendvalue.cpp @@ -58,6 +58,11 @@ QClipBlendValuePrivate::QClipBlendValuePrivate() \inmodule Qt3DAnimation \brief Class used for including a clip in a blend tree. */ +/*! + \property Qt3DAnimation::QClipBlendValue::clip + + The animation clip that needs to be included in the blend tree. +*/ QClipBlendValue::QClipBlendValue(Qt3DCore::QNode *parent) : QAbstractClipBlendNode(*new QClipBlendValuePrivate(), parent) { diff --git a/src/animation/frontend/qclock.cpp b/src/animation/frontend/qclock.cpp index 6dd851b88..717982902 100644 --- a/src/animation/frontend/qclock.cpp +++ b/src/animation/frontend/qclock.cpp @@ -61,6 +61,11 @@ QClock::QClock(QClockPrivate &dd, Qt3DCore::QNode *parent) QClock::~QClock() { } +/*! + \property Qt3DAnimation::QClock::playbackRate + + The playback speed of the animation. +*/ double QClock::playbackRate() const { diff --git a/src/core/changes/qcomponentaddedchange.cpp b/src/core/changes/qcomponentaddedchange.cpp index e00c4ffab..41f7a2340 100644 --- a/src/core/changes/qcomponentaddedchange.cpp +++ b/src/core/changes/qcomponentaddedchange.cpp @@ -75,7 +75,7 @@ QComponentAddedChangePrivate::QComponentAddedChangePrivate(const QEntity *entity */ /*! - * Constructs a new QComponentAddedChange with with \a entity and \a component. + * Constructs a new QComponentAddedChange which will notify \a entity that \a component was added */ QComponentAddedChange::QComponentAddedChange(const QEntity *entity, const QComponent *component) @@ -84,6 +84,16 @@ QComponentAddedChange::QComponentAddedChange(const QEntity *entity, { } +/*! + * Constructs a new QComponentAddedChange which will notify \a component that it was added to \a entity + */ +QComponentAddedChange::QComponentAddedChange(const QComponent *component, + const QEntity *entity) + : QSceneChange(*new QComponentAddedChangePrivate(entity, component), + ComponentAdded, component->id()) +{ +} + QComponentAddedChange::~QComponentAddedChange() { } diff --git a/src/core/changes/qcomponentaddedchange.h b/src/core/changes/qcomponentaddedchange.h index a62cac116..e7676a026 100644 --- a/src/core/changes/qcomponentaddedchange.h +++ b/src/core/changes/qcomponentaddedchange.h @@ -55,6 +55,8 @@ class QT3DCORESHARED_EXPORT QComponentAddedChange : public QSceneChange public: explicit QComponentAddedChange(const QEntity *entity, const QComponent *component); + explicit QComponentAddedChange(const QComponent *component, + const QEntity *entity); ~QComponentAddedChange(); QNodeId entityId() const Q_DECL_NOTHROW; diff --git a/src/core/changes/qcomponentremovedchange.cpp b/src/core/changes/qcomponentremovedchange.cpp index 5e5dfa5aa..e2129169a 100644 --- a/src/core/changes/qcomponentremovedchange.cpp +++ b/src/core/changes/qcomponentremovedchange.cpp @@ -75,7 +75,7 @@ QComponentRemovedChangePrivate::QComponentRemovedChangePrivate(const QEntity *en */ /*! - * Constructs a new QComponentRemovedChange with \a entity and \a component. + * Constructs a new QComponentRemovedChange which will notify \a entity that \a component was removed. */ QComponentRemovedChange::QComponentRemovedChange(const QEntity *entity, const QComponent *component) @@ -84,6 +84,17 @@ QComponentRemovedChange::QComponentRemovedChange(const QEntity *entity, { } +/*! + * Constructs a new QComponentRemovedChange which will notify \a component that it was removed from \a entity + */ +QComponentRemovedChange::QComponentRemovedChange(const QComponent *component, + const QEntity *entity) + : QSceneChange(*new QComponentRemovedChangePrivate(entity, component), + ComponentRemoved, component->id()) +{ + +} + QComponentRemovedChange::~QComponentRemovedChange() { } diff --git a/src/core/changes/qcomponentremovedchange.h b/src/core/changes/qcomponentremovedchange.h index 3c57fe26f..66743b1ae 100644 --- a/src/core/changes/qcomponentremovedchange.h +++ b/src/core/changes/qcomponentremovedchange.h @@ -55,6 +55,8 @@ class QT3DCORESHARED_EXPORT QComponentRemovedChange : public QSceneChange public: explicit QComponentRemovedChange(const QEntity *entity, const QComponent *component); + explicit QComponentRemovedChange(const QComponent *component, + const QEntity *entity); ~QComponentRemovedChange(); QNodeId entityId() const Q_DECL_NOTHROW; diff --git a/src/core/configure.json b/src/core/configure.json index 871f6bfa4..fc938444a 100644 --- a/src/core/configure.json +++ b/src/core/configure.json @@ -86,7 +86,7 @@ "purpose": "Use SSE2 SIMD instructions to accelerate matrix operations", "autoDetect": "features.sse2", "enable": "input.qt3d-simd == 'sse2' || input.qt3d-simd == 'avx2'", - "disable": "input.qt3d-simd == 'no' || (config.win32 && arch.i386)", + "disable": "input.qt3d-simd == 'no' || arch.i386", "output": [ "privateFeature" ] }, "qt3d-simd-avx2": { @@ -94,7 +94,7 @@ "purpose": "Use AVX2 SIMD instructions to accelerate matrix operations", "autoDetect": false, "enable": "input.qt3d-simd == 'avx2'", - "disable": "input.qt3d-simd == 'sse2' || input.qt3d-simd == 'no' || (config.win32 && arch.i386)", + "disable": "input.qt3d-simd == 'sse2' || input.qt3d-simd == 'no' || arch.i386", "output": [ "privateFeature" ] } }, diff --git a/src/core/nodes/qcomponent.cpp b/src/core/nodes/qcomponent.cpp index 8e337adf6..f4e59e058 100644 --- a/src/core/nodes/qcomponent.cpp +++ b/src/core/nodes/qcomponent.cpp @@ -73,7 +73,7 @@ void QComponentPrivate::addEntity(QEntity *entity) m_scene->addEntityForComponent(m_id, entity->id()); } - const auto componentAddedChange = QComponentAddedChangePtr::create(entity, q); + const auto componentAddedChange = QComponentAddedChangePtr::create(q, entity); notifyObservers(componentAddedChange); Q_EMIT q->addedToEntity(entity); } @@ -86,7 +86,7 @@ void QComponentPrivate::removeEntity(QEntity *entity) m_entities.removeAll(entity); - const auto componentRemovedChange = QComponentRemovedChangePtr::create(entity, q); + const auto componentRemovedChange = QComponentRemovedChangePtr::create(q, entity); notifyObservers(componentRemovedChange); Q_EMIT q->removedFromEntity(entity); } diff --git a/src/core/nodes/qnode.cpp b/src/core/nodes/qnode.cpp index e5a3aca71..083fda7df 100644 --- a/src/core/nodes/qnode.cpp +++ b/src/core/nodes/qnode.cpp @@ -388,28 +388,43 @@ void QNodePrivate::propertyChanged(int propertyIndex) if (m_blockNotifications) return; + const auto toBackendValue = [this](const QVariant &data) -> QVariant + { + if (data.canConvert<QNode*>()) { + QNode *node = data.value<QNode*>(); + + // Ensure the node has issued a node creation change. We can end + // up here if a newly created node with a parent is immediately set + // as a property on another node. In this case the deferred call to + // _q_postConstructorInit() will not have happened yet as the event + // loop will still be blocked. So force it here and we catch this + // eventuality in the _q_postConstructorInit() function so that we + // do not repeat the creation and new child scene change events. + if (node) + QNodePrivate::get(node)->_q_postConstructorInit(); + + const QNodeId id = node ? node->id() : QNodeId(); + return QVariant::fromValue(id); + } + + return data; + }; + Q_Q(QNode); const QMetaProperty property = q->metaObject()->property(propertyIndex); const QVariant data = property.read(q); - if (data.canConvert<QNode*>()) { - QNode *node = data.value<QNode*>(); - - // Ensure the node has issued a node creation change. We can end - // up here if a newly created node with a parent is immediately set - // as a property on another node. In this case the deferred call to - // _q_postConstructorInit() will not have happened yet as the event - // loop will still be blocked. So force it here and we catch this - // eventuality in the _q_postConstructorInit() function so that we - // do not repeat the creation and new child scene change events. - if (node) - QNodePrivate::get(node)->_q_postConstructorInit(); - - const QNodeId id = node ? node->id() : QNodeId(); - notifyPropertyChange(property.name(), QVariant::fromValue(id)); + + if (data.type() == QVariant::List) { + QSequentialIterable iterable = data.value<QSequentialIterable>(); + QVariantList variants; + variants.reserve(iterable.size()); + for (const auto &v : iterable) + variants.append(toBackendValue(v)); + notifyPropertyChange(property.name(), variants); } else { - notifyPropertyChange(property.name(), data); + notifyPropertyChange(property.name(), toBackendValue(data)); } } diff --git a/src/core/resources/qresourcemanager_p.h b/src/core/resources/qresourcemanager_p.h index 038f3d551..e620b40d1 100644 --- a/src/core/resources/qresourcemanager_p.h +++ b/src/core/resources/qresourcemanager_p.h @@ -60,6 +60,8 @@ #include <limits> #include <Qt3DCore/private/qhandle_p.h> +#include <QtCore/private/qsimd_p.h> +#include <Qt3DCore/private/qt3dcore-config_p.h> // Silence complaints about unreferenced local variables in // ArrayAllocatingPolicy::deallocateBuckets() when the compiler @@ -313,7 +315,17 @@ private: void allocateBucket() { // no free handle, allocate a new - Bucket *b = new Bucket; + Bucket *b = nullptr; + // allocate aligned memory +#if QT_CONFIG(qt3d_simd_avx2) && defined(__AVX2__) && defined(QT_COMPILER_SUPPORTS_AVX2) + b = static_cast<Bucket*>(_mm_malloc(sizeof(Bucket), 32)); +#elif QT_CONFIG(qt3d_simd_sse2) && defined(__SSE2__) && defined(QT_COMPILER_SUPPORTS_SSE2) + b = static_cast<Bucket*>(_mm_malloc(sizeof(Bucket), 16)); +#else + b = static_cast<Bucket*>(malloc(sizeof(Bucket))); +#endif + // placement new + new (b) Bucket; b->header.next = firstBucket; firstBucket = b; @@ -329,7 +341,16 @@ private: Bucket *b = firstBucket; while (b) { Bucket *n = b->header.next; - delete b; + // Call dtor explicitly + b->~Bucket(); + // Release aligned memory +#if QT_CONFIG(qt3d_simd_avx2) && defined(__AVX2__) && defined(QT_COMPILER_SUPPORTS_AVX2) + _mm_free(b); +#elif QT_CONFIG(qt3d_simd_sse2) && defined(__SSE2__) && defined(QT_COMPILER_SUPPORTS_SSE2) + _mm_free(b); +#else + free(b); +#endif b = n; } } diff --git a/src/core/transforms/matrix4x4_p.h b/src/core/transforms/matrix4x4_p.h index 18f5db4c3..d100d3d3b 100644 --- a/src/core/transforms/matrix4x4_p.h +++ b/src/core/transforms/matrix4x4_p.h @@ -83,4 +83,16 @@ QT_END_NAMESPACE #endif +template<typename UsingType> +Q_ALWAYS_INLINE QMatrix4x4 convertToQMatrix4x4(const UsingType &v) +{ + return v.toQMatrix4x4(); +} + +template<> +Q_ALWAYS_INLINE QMatrix4x4 convertToQMatrix4x4<QMatrix4x4>(const QMatrix4x4 &v) +{ + return v; +} + #endif // QT3DCORE_MATRIX4X4_P_H diff --git a/src/core/transforms/vector3d_p.h b/src/core/transforms/vector3d_p.h index 6467d7686..80e936903 100644 --- a/src/core/transforms/vector3d_p.h +++ b/src/core/transforms/vector3d_p.h @@ -74,4 +74,16 @@ QT_END_NAMESPACE #endif +template<typename UsingType> +Q_ALWAYS_INLINE QVector3D convertToQVector3D(const UsingType &v) +{ + return v.toQVector3D(); +} + +template<> +Q_ALWAYS_INLINE QVector3D convertToQVector3D<QVector3D>(const QVector3D &v) +{ + return v; +} + #endif // QT3DCORE_VECTOR3D_P_H diff --git a/src/core/transforms/vector4d_p.h b/src/core/transforms/vector4d_p.h index a03dc234f..dbfaffffd 100644 --- a/src/core/transforms/vector4d_p.h +++ b/src/core/transforms/vector4d_p.h @@ -74,4 +74,16 @@ QT_END_NAMESPACE #endif +template<typename UsingType> +Q_ALWAYS_INLINE QVector4D convertToQVector4D(const UsingType &v) +{ + return v.toQVector4D(); +} + +template<> +Q_ALWAYS_INLINE QVector4D convertToQVector4D<QVector4D>(const QVector4D &v) +{ + return v; +} + #endif // QT3DCORE_VECTOR4D_P_H diff --git a/src/extras/defaults/qabstractcameracontroller.h b/src/extras/defaults/qabstractcameracontroller.h index f13079f5f..e5d14745a 100644 --- a/src/extras/defaults/qabstractcameracontroller.h +++ b/src/extras/defaults/qabstractcameracontroller.h @@ -96,6 +96,7 @@ protected: Qt3DInput::QKeyboardDevice *keyboardDevice() const; Qt3DInput::QMouseDevice *mouseDevice() const; +public: struct InputState { float rxAxisValue; diff --git a/src/extras/doc/src/qt3dextras-module.qdoc b/src/extras/doc/src/qt3dextras-module.qdoc index 5461a5b09..a90d29a51 100644 --- a/src/extras/doc/src/qt3dextras-module.qdoc +++ b/src/extras/doc/src/qt3dextras-module.qdoc @@ -42,7 +42,7 @@ \title Qt 3D Extras C++ Classes \keyword Qt 3D Extras - \brief The Qt 3D Extras modules provides a set of prebuilt elements to help + \brief The Qt 3D Extras module provides a set of prebuilt elements to help you get started with Qt 3D. This module is still in tech preview. This means it is unstable, likely to diff --git a/src/input/frontend/qphysicaldevicecreatedchange.cpp b/src/input/frontend/qphysicaldevicecreatedchange.cpp index 0abeea520..807fdc014 100644 --- a/src/input/frontend/qphysicaldevicecreatedchange.cpp +++ b/src/input/frontend/qphysicaldevicecreatedchange.cpp @@ -71,7 +71,7 @@ QPhysicalDeviceCreatedChangeBase::~QPhysicalDeviceCreatedChangeBase() /*! Returns a list of node ids. */ -Qt3DCore::QNodeIdVector QPhysicalDeviceCreatedChangeBase::axisSettingIds() const +Qt3DCore::QNodeIdVector Qt3DInput::QPhysicalDeviceCreatedChangeBase::axisSettingIds() const { Q_D(const QPhysicalDeviceCreatedChangeBase); return d->m_axisSettingIds; diff --git a/src/plugins/sceneparsers/assimp/assimpimporter.cpp b/src/plugins/sceneparsers/assimp/assimpimporter.cpp index 219a75ce4..ad53916fd 100644 --- a/src/plugins/sceneparsers/assimp/assimpimporter.cpp +++ b/src/plugins/sceneparsers/assimp/assimpimporter.cpp @@ -227,13 +227,13 @@ QAttribute *createAttribute(QBuffer *buffer, return attribute; } -QAttribute *createAttribute(QBuffer *buffer, - QAttribute::VertexBaseType vertexBaseType, - uint vertexSize, - uint count, - uint byteOffset = 0, - uint byteStride = 0, - QNode *parent = nullptr) +QAttribute *createIndexAttribute(QBuffer *buffer, + QAttribute::VertexBaseType vertexBaseType, + uint vertexSize, + uint count, + uint byteOffset = 0, + uint byteStride = 0, + QNode *parent = nullptr) { QAttribute *attribute = QAbstractNodeFactory::createNode<QAttribute>("QAttribute"); attribute->setBuffer(buffer); @@ -603,7 +603,8 @@ void AssimpImporter::readSceneFile(const QString &path) aiProcess_GenSmoothNormals| aiProcess_FlipUVs); if (m_scene->m_aiScene == nullptr) { - qCWarning(AssimpImporterLog) << "Assimp scene import failed"; + qCWarning(AssimpImporterLog) << "Assimp scene import failed" << m_scene->m_importer->GetErrorString(); + QSceneImporter::logError(QString::fromUtf8(m_scene->m_importer->GetErrorString())); return ; } parse(); @@ -828,7 +829,7 @@ QGeometryRenderer *AssimpImporter::loadMesh(uint meshIndex) indexBuffer->setData(ibufferContent); // Add indices attributes - QAttribute *indexAttribute = createAttribute(indexBuffer, indiceType, 1, indices); + QAttribute *indexAttribute = createIndexAttribute(indexBuffer, indiceType, 1, indices); indexAttribute->setAttributeType(QAttribute::IndexAttribute); meshGeometry->addAttribute(indexAttribute); diff --git a/src/plugins/sceneparsers/assimp/assimpimporter.h b/src/plugins/sceneparsers/assimp/assimpimporter.h index 5cbace362..9a020b3e3 100644 --- a/src/plugins/sceneparsers/assimp/assimpimporter.h +++ b/src/plugins/sceneparsers/assimp/assimpimporter.h @@ -143,7 +143,6 @@ private: QHash<aiTextureType, QString> m_textureToParameterName; QVector<Qt3DAnimation::QKeyframeAnimation *> m_animations; QVector<Qt3DAnimation::QMorphingAnimation *> m_morphAnimations; -// QMap<aiNode*, Light*> m_lights; }; QDir m_sceneDir; diff --git a/src/quick3d/imports/scene3d/scene3drenderer.cpp b/src/quick3d/imports/scene3d/scene3drenderer.cpp index 1c9fec4d2..b2e541d35 100644 --- a/src/quick3d/imports/scene3d/scene3drenderer.cpp +++ b/src/quick3d/imports/scene3d/scene3drenderer.cpp @@ -135,7 +135,6 @@ Scene3DRenderer::Scene3DRenderer(Scene3DItem *item, Qt3DCore::QAspectEngine *asp , m_multisample(false) // this value is not used, will be synced from the Scene3DItem instead , m_lastMultisample(false) , m_needsShutdown(true) - , m_blocking(false) { Q_CHECK_PTR(m_item); Q_CHECK_PTR(m_item->window()); @@ -155,9 +154,6 @@ Scene3DRenderer::Scene3DRenderer(Scene3DItem *item, Qt3DCore::QAspectEngine *asp ContextSaver saver; static_cast<QRenderAspectPrivate*>(QRenderAspectPrivate::get(m_renderAspect))->renderInitialize(saver.context()); scheduleRootEntityChange(); - - const bool blockingRendermode = !qgetenv("SCENE3D_BLOCKING_RENDERMODE").isEmpty(); - m_blocking = blockingRendermode; } Scene3DRenderer::~Scene3DRenderer() @@ -207,6 +203,8 @@ void Scene3DRenderer::shutdown() // would return early m_item = nullptr; + static_cast<QRenderAspectPrivate*>(QRenderAspectPrivate::get(m_renderAspect))->abortRenderJobs(); + // Exit the simulation loop so no more jobs are asked for. Once this // returns it is safe to shutdown the renderer. if (m_aspectEngine) { @@ -311,7 +309,7 @@ void Scene3DRenderer::render() m_finalFBO->bind(); // Render Qt3D Scene - static_cast<QRenderAspectPrivate*>(QRenderAspectPrivate::get(m_renderAspect))->renderSynchronous(m_blocking); + static_cast<QRenderAspectPrivate*>(QRenderAspectPrivate::get(m_renderAspect))->tryRenderSynchronous(); // We may have called doneCurrent() so restore the context if the rendering surface was changed // Note: keep in mind that the ContextSave also restores the surface when destroyed diff --git a/src/quick3d/imports/scene3d/scene3drenderer_p.h b/src/quick3d/imports/scene3d/scene3drenderer_p.h index eb2b930ef..7a85bc774 100644 --- a/src/quick3d/imports/scene3d/scene3drenderer_p.h +++ b/src/quick3d/imports/scene3d/scene3drenderer_p.h @@ -109,7 +109,6 @@ private: bool m_multisample; bool m_lastMultisample; bool m_needsShutdown; - bool m_blocking; friend class Scene3DCleaner; }; diff --git a/src/quick3d/quick3dscene2d/items/scene2d.cpp b/src/quick3d/quick3dscene2d/items/scene2d.cpp index 1147abf68..7e3334f00 100644 --- a/src/quick3d/quick3dscene2d/items/scene2d.cpp +++ b/src/quick3d/quick3dscene2d/items/scene2d.cpp @@ -469,10 +469,10 @@ void Scene2D::handlePickEvent(int type, const Qt3DRender::QPickEventPtr &ev) CoordinateReader reader(renderer()->nodeManagers()); if (reader.setGeometry(entity->renderComponent<GeometryRenderer>(), QAttribute::defaultTextureCoordinateAttributeName())) { - QVector4D c0 = reader.getCoordinate(pickTriangle->vertex1Index()); - QVector4D c1 = reader.getCoordinate(pickTriangle->vertex2Index()); - QVector4D c2 = reader.getCoordinate(pickTriangle->vertex3Index()); - QVector4D ci = c0 * pickTriangle->uvw().x() + Vector4D c0 = reader.getCoordinate(pickTriangle->vertex1Index()); + Vector4D c1 = reader.getCoordinate(pickTriangle->vertex2Index()); + Vector4D c2 = reader.getCoordinate(pickTriangle->vertex3Index()); + Vector4D ci = c0 * pickTriangle->uvw().x() + c1 * pickTriangle->uvw().y() + c2 * pickTriangle->uvw().z(); ci.setW(1.0f); diff --git a/src/render/aligned_malloc_p.h b/src/render/aligned_malloc_p.h new file mode 100644 index 000000000..a2a619b03 --- /dev/null +++ b/src/render/aligned_malloc_p.h @@ -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:LGPL$ +** 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 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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DRENDER_RENDER_ALIGNED_MALLOC_P_H +#define QT3DRENDER_RENDER_ALIGNED_MALLOC_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 <QtCore/private/qsimd_p.h> +#include <Qt3DCore/private/qt3dcore-config_p.h> + +#if QT_CONFIG(qt3d_simd_avx2) && defined(__AVX2__) && defined(QT_COMPILER_SUPPORTS_AVX2) +# define QT3D_ALIGNED_MALLOC(s) _mm_malloc(s, 32) +#elif QT_CONFIG(qt3d_simd_sse2) && defined(__SSE2__) && defined(QT_COMPILER_SUPPORTS_SSE2) +# define QT3D_ALIGNED_MALLOC(s) _mm_malloc(s, 16) +#else + #define QT3D_ALIGNED_MALLOC(s) malloc(s) +#endif + +#if (QT_CONFIG(qt3d_simd_avx2) && defined(__AVX2__) && defined(QT_COMPILER_SUPPORTS_AVX2)) || (QT_CONFIG(qt3d_simd_sse2) && defined(__SSE2__) && defined(QT_COMPILER_SUPPORTS_SSE2)) +# define QT3D_ALIGNED_FREE(ptr) _mm_free(ptr) +#else +# define QT3D_ALIGNED_FREE(ptr) free(ptr) +#endif + +#define QT3D_ALIGNED_MALLOC_AND_FREE() \ + static void *operator new(size_t s) \ + { \ + return QT3D_ALIGNED_MALLOC(s); \ + } \ + static void operator delete(void *ptr) \ + { \ + QT3D_ALIGNED_FREE(ptr); \ + } + +#endif // QT3DRENDER_RENDER_ALIGNED_MALLOC_P_H diff --git a/src/render/backend/abstractrenderer_p.h b/src/render/backend/abstractrenderer_p.h index 54f37ea21..bf05bdec8 100644 --- a/src/render/backend/abstractrenderer_p.h +++ b/src/render/backend/abstractrenderer_p.h @@ -134,7 +134,7 @@ public: // Threaded renderer virtual void render() = 0; // Synchronous renderer - virtual void doRender(bool scene3dBlocking = false) = 0; + virtual void doRender() = 0; virtual void cleanGraphicsResources() = 0; @@ -151,7 +151,7 @@ public: virtual QVector<Qt3DCore::QAspectJobPtr> renderBinJobs() = 0; virtual Qt3DCore::QAspectJobPtr pickBoundingVolumeJob() = 0; virtual Qt3DCore::QAspectJobPtr rayCastingJob() = 0; - virtual Qt3DCore::QAspectJobPtr syncTextureLoadingJob() = 0; + virtual Qt3DCore::QAspectJobPtr syncSkeletonLoadingJob() = 0; virtual Qt3DCore::QAspectJobPtr expandBoundingVolumeJob() = 0; virtual void setSceneRoot(Qt3DCore::QBackendNodeFactory *factory, Entity *root) = 0; @@ -170,6 +170,12 @@ public: virtual void setOffscreenSurfaceHelper(OffscreenSurfaceHelper *helper) = 0; virtual QSurfaceFormat format() = 0; virtual QOpenGLContext *shareContext() const = 0; + + virtual void lockSurfaceAndRender() = 0; + virtual bool releaseRendererAndRequestPromiseToRender() = 0; + virtual bool waitForRenderJobs() = 0; + virtual bool tryWaitForRenderJobs(int timeout) = 0; + virtual void abortRenderJobs() = 0; }; Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractRenderer::BackendNodeDirtySet) diff --git a/src/render/backend/buffervisitor_p.h b/src/render/backend/buffervisitor_p.h index 4870171b1..98749b62c 100644 --- a/src/render/backend/buffervisitor_p.h +++ b/src/render/backend/buffervisitor_p.h @@ -195,7 +195,7 @@ protected: const uint byteStride, const uint count) { - const uint stride = byteStride / sizeof(Coordinate); + const uint stride = byteStride ? byteStride / sizeof(Coordinate) : 2; for (uint ndx = 0; ndx < count; ++ndx) { visit(ndx, coordinates[0], coordinates[1]); coordinates += stride; @@ -211,7 +211,7 @@ protected: bool primitiveRestartEnabled, int primitiveRestartIndex) { - const uint stride = byteStride / sizeof(Coordinate); + const uint stride = byteStride ? byteStride / sizeof(Coordinate) : 2; for (uint i = 0; i < count; ++i) { if (!primitiveRestartEnabled || indices[i] != primitiveRestartIndex) { const uint n = stride * indices[i]; @@ -225,7 +225,7 @@ protected: const uint byteStride, const uint count) { - const uint stride = byteStride / sizeof(Coordinate); + const uint stride = byteStride ? byteStride / sizeof(Coordinate) : 3; for (uint ndx = 0; ndx < count; ++ndx) { visit(ndx, coordinates[0], coordinates[1], coordinates[2]); coordinates += stride; @@ -240,7 +240,7 @@ protected: bool primitiveRestartEnabled, int primitiveRestartIndex) { - const uint stride = byteStride / sizeof(Coordinate); + const uint stride = byteStride ? byteStride / sizeof(Coordinate) : 3; for (uint i = 0; i < count; ++i) { if (!primitiveRestartEnabled || indices[i] != primitiveRestartIndex) { const uint n = stride * indices[i]; @@ -254,7 +254,7 @@ protected: const uint byteStride, const uint count) { - const uint stride = byteStride / sizeof(Coordinate); + const uint stride = byteStride ? byteStride / sizeof(Coordinate) : 4; for (uint ndx = 0; ndx < count; ++ndx) { visit(ndx, coordinates[0], coordinates[1], coordinates[2], coordinates[3]); coordinates += stride; @@ -269,7 +269,7 @@ protected: bool primitiveRestartEnabled, int primitiveRestartIndex) { - const uint stride = byteStride / sizeof(Coordinate); + const uint stride = byteStride ? byteStride / sizeof(Coordinate) : 4; for (uint i = 0; i < count; ++i) { if (!primitiveRestartEnabled || indices[i] != primitiveRestartIndex) { const uint n = stride * indices[i]; diff --git a/src/render/backend/cameralens.cpp b/src/render/backend/cameralens.cpp index e127b5885..b540b24c8 100644 --- a/src/render/backend/cameralens.cpp +++ b/src/render/backend/cameralens.cpp @@ -105,23 +105,25 @@ void CameraLens::setRenderAspect(QRenderAspect *renderAspect) m_renderAspect = renderAspect; } -QMatrix4x4 CameraLens::viewMatrix(const QMatrix4x4 &worldTransform) +Matrix4x4 CameraLens::viewMatrix(const Matrix4x4 &worldTransform) { - const QVector4D position = worldTransform * QVector4D(0.0f, 0.0f, 0.0f, 1.0f); + const Vector4D position = worldTransform * Vector4D(0.0f, 0.0f, 0.0f, 1.0f); // OpenGL convention is looking down -Z - const QVector4D viewDirection = worldTransform * QVector4D(0.0f, 0.0f, -1.0f, 0.0f); - const QVector4D upVector = worldTransform * QVector4D(0.0f, 1.0f, 0.0f, 0.0f); + const Vector4D viewDirection = worldTransform * Vector4D(0.0f, 0.0f, -1.0f, 0.0f); + const Vector4D upVector = worldTransform * Vector4D(0.0f, 1.0f, 0.0f, 0.0f); QMatrix4x4 m; - m.lookAt(position.toVector3D(), (position + viewDirection).toVector3D(), upVector.toVector3D()); - return m; + m.lookAt(convertToQVector3D(Vector3D(position)), + convertToQVector3D(Vector3D(position + viewDirection)), + convertToQVector3D(Vector3D(upVector))); + return Matrix4x4(m); } void CameraLens::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) { const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QCameraLensData>>(change); const auto &data = typedChange->data; - m_projection = data.projectionMatrix; + m_projection = Matrix4x4(data.projectionMatrix); m_exposure = data.exposure; } @@ -160,7 +162,7 @@ void CameraLens::notifySceneBoundingVolume(const Sphere &sphere, QNodeCommand::C } } -void CameraLens::setProjection(const QMatrix4x4 &projection) +void CameraLens::setProjection(const Matrix4x4 &projection) { m_projection = projection; } @@ -178,7 +180,7 @@ void CameraLens::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) if (propertyChange->propertyName() == QByteArrayLiteral("projectionMatrix")) { QMatrix4x4 projectionMatrix = propertyChange->value().value<QMatrix4x4>(); - m_projection = projectionMatrix; + m_projection = Matrix4x4(projectionMatrix); } else if (propertyChange->propertyName() == QByteArrayLiteral("exposure")) { setExposure(propertyChange->value().toFloat()); } @@ -212,7 +214,7 @@ void CameraLens::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) } bool CameraLens::viewMatrixForCamera(EntityManager* manager, Qt3DCore::QNodeId cameraId, - QMatrix4x4 &viewMatrix, QMatrix4x4 &projectionMatrix) + Matrix4x4 &viewMatrix, Matrix4x4 &projectionMatrix) { Entity *camNode = manager->lookupResource(cameraId); if (!camNode) diff --git a/src/render/backend/cameralens_p.h b/src/render/backend/cameralens_p.h index 9e237cfda..d00358fb8 100644 --- a/src/render/backend/cameralens_p.h +++ b/src/render/backend/cameralens_p.h @@ -53,7 +53,7 @@ #include <Qt3DRender/private/backendnode_p.h> #include <Qt3DCore/private/qnodecommand_p.h> -#include <QMatrix4x4> +#include <Qt3DCore/private/matrix4x4_p.h> #include <QRectF> QT_BEGIN_NAMESPACE @@ -89,10 +89,10 @@ public: void setRenderAspect(QRenderAspect* renderAspect); - QMatrix4x4 viewMatrix(const QMatrix4x4 &worldTransform); + Matrix4x4 viewMatrix(const Matrix4x4 &worldTransform); - void setProjection(const QMatrix4x4 &projection); - inline QMatrix4x4 projection() const { return m_projection; } + void setProjection(const Matrix4x4 &projection); + inline Matrix4x4 projection() const { return m_projection; } void setExposure(float exposure); inline float exposure() const { return m_exposure; } @@ -101,7 +101,7 @@ public: void notifySceneBoundingVolume(const Sphere &sphere, Qt3DCore::QNodeCommand::CommandId commandId); static bool viewMatrixForCamera(EntityManager *manager, Qt3DCore::QNodeId cameraId, - QMatrix4x4 &viewMatrix, QMatrix4x4 &projectionMatrix); + Matrix4x4 &viewMatrix, Matrix4x4 &projectionMatrix); private: void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; @@ -110,8 +110,8 @@ private: Qt3DCore::QNodeCommand::CommandId commandId); QRenderAspect *m_renderAspect; - QMatrix4x4 m_projection; Qt3DCore::QNodeCommand::CommandId m_pendingViewAllCommand; + Matrix4x4 m_projection; float m_exposure; }; diff --git a/src/render/backend/entity.cpp b/src/render/backend/entity.cpp index 1a0e877d6..85334d1d3 100644 --- a/src/render/backend/entity.cpp +++ b/src/render/backend/entity.cpp @@ -291,12 +291,12 @@ QVector<Entity *> Entity::children() const return childrenVector; } -QMatrix4x4 *Entity::worldTransform() +Matrix4x4 *Entity::worldTransform() { return m_nodeManagers->worldMatrixManager()->data(m_worldTransform); } -const QMatrix4x4 *Entity::worldTransform() const +const Matrix4x4 *Entity::worldTransform() const { return m_nodeManagers->worldMatrixManager()->data(m_worldTransform); } diff --git a/src/render/backend/entity_p.h b/src/render/backend/entity_p.h index 5448b5297..075871d85 100644 --- a/src/render/backend/entity_p.h +++ b/src/render/backend/entity_p.h @@ -104,8 +104,8 @@ public: QVector<Entity *> children() const; bool hasChildren() const { return !m_childrenHandles.empty(); } - QMatrix4x4 *worldTransform(); - const QMatrix4x4 *worldTransform() const; + Matrix4x4 *worldTransform(); + const Matrix4x4 *worldTransform() const; Sphere *localBoundingVolume() const { return m_localBoundingVolume.data(); } Sphere *worldBoundingVolume() const { return m_worldBoundingVolume.data(); } Sphere *worldBoundingVolumeWithChildren() const { return m_worldBoundingVolumeWithChildren.data(); } diff --git a/src/render/backend/handle_types_p.h b/src/render/backend/handle_types_p.h index bec2e3a9a..035bbfc91 100644 --- a/src/render/backend/handle_types_p.h +++ b/src/render/backend/handle_types_p.h @@ -53,11 +53,10 @@ #include <Qt3DRender/qt3drender_global.h> #include <Qt3DCore/private/qhandle_p.h> +#include <Qt3DCore/private/matrix4x4_p.h> QT_BEGIN_NAMESPACE -class QMatrix4x4; - namespace Qt3DRender { class QTextureImageData; @@ -109,7 +108,7 @@ typedef Qt3DCore::QHandle<FrameGraphNode *> HFrameGraphNode; typedef Qt3DCore::QHandle<Layer> HLayer; typedef Qt3DCore::QHandle<LevelOfDetail> HLevelOfDetail; typedef Qt3DCore::QHandle<Material> HMaterial; -typedef Qt3DCore::QHandle<QMatrix4x4> HMatrix; +typedef Qt3DCore::QHandle<Matrix4x4> HMatrix; typedef Qt3DCore::QHandle<OpenGLVertexArrayObject> HVao; typedef Qt3DCore::QHandle<Shader> HShader; typedef Qt3DCore::QHandle<ShaderBuilder> HShaderBuilder; diff --git a/src/render/backend/managers_p.h b/src/render/backend/managers_p.h index b3e7b6f27..c9bcb799e 100644 --- a/src/render/backend/managers_p.h +++ b/src/render/backend/managers_p.h @@ -52,6 +52,7 @@ // #include <Qt3DCore/private/qresourcemanager_p.h> +#include <Qt3DCore/private/matrix4x4_p.h> #include <Qt3DRender/private/rendertargetoutput_p.h> #include <Qt3DRender/private/cameralens_p.h> #include <Qt3DRender/private/filterkey_p.h> @@ -189,7 +190,7 @@ public: }; class MatrixManager : public Qt3DCore::QResourceManager< - QMatrix4x4, + Matrix4x4, Qt3DCore::QNodeId, Qt3DCore::NonLockingPolicy> { diff --git a/src/render/backend/nodemanagers.cpp b/src/render/backend/nodemanagers.cpp index 035d4d8d4..5db35082d 100644 --- a/src/render/backend/nodemanagers.cpp +++ b/src/render/backend/nodemanagers.cpp @@ -174,7 +174,7 @@ MaterialManager *NodeManagers::manager<Material>() const Q_DECL_NOTHROW } template<> -MatrixManager *NodeManagers::manager<QMatrix4x4*>() const Q_DECL_NOTHROW +MatrixManager *NodeManagers::manager<Matrix4x4>() const Q_DECL_NOTHROW { return m_worldMatrixManager; } diff --git a/src/render/backend/pointsvisitor.cpp b/src/render/backend/pointsvisitor.cpp index 663488357..750182b19 100644 --- a/src/render/backend/pointsvisitor.cpp +++ b/src/render/backend/pointsvisitor.cpp @@ -72,7 +72,7 @@ void traverseCoordinatesIndexed(Index *indices, const uint maxVerticesDataSize = qMin(vertexInfo.dataSize, 3U); uint ndx; - QVector3D abc; + Vector3D abc; while (i < indexInfo.count) { ndx = indices[i]; const uint idx = ndx * verticesStride; @@ -94,7 +94,7 @@ void traverseCoordinates(Vertex *vertices, const uint maxVerticesDataSize = qMin(vertexInfo.dataSize, 3U); uint ndx = 0; - QVector3D abc; + Vector3D abc; while (ndx < vertexInfo.count) { const uint idx = ndx * verticesStride; for (uint j = 0; j < maxVerticesDataSize; ++j) diff --git a/src/render/backend/pointsvisitor_p.h b/src/render/backend/pointsvisitor_p.h index 9d44ffec5..1614f185b 100644 --- a/src/render/backend/pointsvisitor_p.h +++ b/src/render/backend/pointsvisitor_p.h @@ -52,6 +52,7 @@ // #include <Qt3DCore/qnodeid.h> +#include <Qt3DCore/private/vector3d_p.h> QT_BEGIN_NAMESPACE @@ -75,7 +76,7 @@ public: void apply(const Qt3DCore::QEntity *entity); void apply(const GeometryRenderer *renderer, const Qt3DCore::QNodeId id); - virtual void visit(uint ndx, const QVector3D &c) = 0; + virtual void visit(uint ndx, const Vector3D &c) = 0; protected: NodeManagers *m_manager; diff --git a/src/render/backend/render-backend.pri b/src/render/backend/render-backend.pri index f7f30b5c9..a3df90f8c 100644 --- a/src/render/backend/render-backend.pri +++ b/src/render/backend/render-backend.pri @@ -45,7 +45,8 @@ HEADERS += \ $$PWD/visitorutils_p.h \ $$PWD/segmentsvisitor_p.h \ $$PWD/pointsvisitor_p.h \ - $$PWD/renderercache_p.h + $$PWD/renderercache_p.h \ + $$PWD/renderbarrierjob_p.h SOURCES += \ $$PWD/renderthread.cpp \ @@ -82,7 +83,8 @@ SOURCES += \ $$PWD/resourceaccessor.cpp \ $$PWD/segmentsvisitor.cpp \ $$PWD/commandthread.cpp \ - $$PWD/pointsvisitor.cpp + $$PWD/pointsvisitor.cpp \ + $$PWD/renderbarrierjob.cpp include($$QT3D_BUILD_ROOT/src/core/qt3dcore-config.pri) QT_FOR_CONFIG += 3dcore-private diff --git a/src/render/backend/renderbarrierjob.cpp b/src/render/backend/renderbarrierjob.cpp new file mode 100644 index 000000000..c60c9f368 --- /dev/null +++ b/src/render/backend/renderbarrierjob.cpp @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "renderbarrierjob_p.h" + +#include <Qt3DRender/private/renderlogging_p.h> + +#include <QtCore/QThread> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { +namespace Render { + +QDebug operator<<(QDebug debug, JobTypes::JobType type) +{ + switch (type) { + case JobTypes::ReadRenderQueueSizeBarrier: + debug << "ReadRenderQueueSize"; + break; + case JobTypes::BeginDrawingBarrier: + debug << "BeginDrawing"; + break; + case JobTypes::UpdateGLResourcesBarrier: + debug << "UpdateGLResources"; + break; + case JobTypes::PrepareCommandSubmissionBarrier: + debug << "PrepareCommandSubmission"; + break; + case JobTypes::EndDrawingBarrier: + debug << "EndDrawing"; + break; + default: + break; + } + return debug; +} + +RenderBarrierJob::RenderBarrierJob(JobTypes::JobType type) + : QAspectJob() + , m_type(type) + , m_begin(0) + , m_end(0) +{ + SET_JOB_RUN_STAT_TYPE(this, type, 0); +} + +void RenderBarrierJob::waitForDependencies() +{ + qCDebug(Jobs) << Q_FUNC_INFO << m_type << "waiting for job on" << QThread::currentThread(); + m_begin.acquire(); + qCDebug(Jobs) << Q_FUNC_INFO << m_type << "done waiting for job on" << QThread::currentThread(); + Q_ASSERT(m_begin.available() == 0); +} + +void RenderBarrierJob::allowToProceed() +{ + qCDebug(Jobs) << Q_FUNC_INFO << m_type << "releasing job on" << QThread::currentThread(); + m_end.release(); +} + +void RenderBarrierJob::run() +{ + qCDebug(Jobs) << Q_FUNC_INFO << m_type << "job releasing render thread on" << QThread::currentThread(); + m_begin.release(); + qCDebug(Jobs) << Q_FUNC_INFO << m_type << "job waiting for render thread on" << QThread::currentThread(); + m_end.acquire(); + qCDebug(Jobs) << Q_FUNC_INFO << m_type << "job done on" << QThread::currentThread(); + Q_ASSERT(m_end.available() == 0); +} + +} // namespace Render +} // namespace Qt3DRender + +QT_END_NAMESPACE diff --git a/src/render/backend/renderbarrierjob_p.h b/src/render/backend/renderbarrierjob_p.h new file mode 100644 index 000000000..a39b2aa83 --- /dev/null +++ b/src/render/backend/renderbarrierjob_p.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DRENDER_RENDER_RENDERBARRIERJOB_P_H +#define QT3DRENDER_RENDER_RENDERBARRIERJOB_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 <Qt3DCore/QAspectJob> + +#include <Qt3DRender/private/qt3drender_global_p.h> +#include <Qt3DRender/private/job_common_p.h> + +#include <QtCore/qsemaphore.h> + +#include <functional> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { +namespace Render { + +class QT3DRENDERSHARED_PRIVATE_EXPORT RenderBarrierJob : public Qt3DCore::QAspectJob +{ +public: + RenderBarrierJob(JobTypes::JobType type); + // Called from render thread + void waitForDependencies(); + // Called from render thread + void allowToProceed(); + + void run() final; +private: + JobTypes::JobType m_type; + QSemaphore m_begin; + QSemaphore m_end; +}; + +using RenderBarrierJobPtr = QSharedPointer<RenderBarrierJob>; + +} // namespace Render +} // namespace Qt3DRender + +QT_END_NAMESPACE + +#endif // QT3DRENDER_RENDER_RENDERBARRIERJOB_P_H diff --git a/src/render/backend/renderer.cpp b/src/render/backend/renderer.cpp index bb0585e6f..d89813f57 100644 --- a/src/render/backend/renderer.cpp +++ b/src/render/backend/renderer.cpp @@ -89,11 +89,14 @@ #include <Qt3DRender/private/buffercapture_p.h> #include <Qt3DRender/private/offscreensurfacehelper_p.h> #include <Qt3DRender/private/renderviewbuilder_p.h> +#include <Qt3DRender/private/loadtexturedatajob_p.h> +#include <Qt3DRender/private/renderbarrierjob_p.h> #include <Qt3DRender/qcameralens.h> #include <Qt3DCore/private/qeventfilterservice_p.h> #include <Qt3DCore/private/qabstractaspectjobmanager_p.h> #include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> +#include <private/rendersurfaceselector_p.h> #if QT_CONFIG(qt3d_profile_jobs) #include <Qt3DCore/private/aspectcommanddebugger_p.h> @@ -185,10 +188,16 @@ Renderer::Renderer(QRenderAspect::RenderType type) , m_bufferGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForDirtyBuffers(); }, JobTypes::DirtyBufferGathering)) , m_vaoGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForAbandonedVaos(); }, JobTypes::DirtyVaoGathering)) , m_textureGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForDirtyTextures(); }, JobTypes::DirtyTextureGathering)) + , m_loadTextureJob(Render::LoadTextureDataJobPtr::create()) , m_shaderGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForDirtyShaders(); }, JobTypes::DirtyShaderGathering)) - , m_syncTextureLoadingJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([] {}, JobTypes::SyncTextureLoading)) + , m_syncSkeletonLoadingJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([] {}, JobTypes::SyncSkeletonLoading)) , m_ownedContext(false) , m_offscreenHelper(nullptr) + , m_readRenderQueueSizeBarrierJob(RenderBarrierJobPtr::create(JobTypes::ReadRenderQueueSizeBarrier)) + , m_beginDrawingBarrierJob(RenderBarrierJobPtr::create(JobTypes::BeginDrawingBarrier)) + , m_updateGLResourcesBarrierJob(RenderBarrierJobPtr::create(JobTypes::UpdateGLResourcesBarrier)) + , m_prepareCommandSubmissionBarrierJob(RenderBarrierJobPtr::create(JobTypes::PrepareCommandSubmissionBarrier)) + , m_endDrawingBarrierJob(RenderBarrierJobPtr::create(JobTypes::EndDrawingBarrier)) #if QT_CONFIG(qt3d_profile_jobs) , m_commandExecuter(new Qt3DRender::Debug::CommandExecuter(this)) #endif @@ -199,27 +208,49 @@ Renderer::Renderer(QRenderAspect::RenderType type) if (m_renderThread) m_renderThread->waitForStart(); + // Render thread barrier interdependencies + m_beginDrawingBarrierJob->addDependency(m_readRenderQueueSizeBarrierJob); + m_updateGLResourcesBarrierJob->addDependency(m_beginDrawingBarrierJob); + m_prepareCommandSubmissionBarrierJob->addDependency(m_updateGLResourcesBarrierJob); + m_endDrawingBarrierJob->addDependency(m_prepareCommandSubmissionBarrierJob); + // Create jobs to update transforms and bounding volumes // We can only update bounding volumes once all world transforms are known - m_calculateBoundingVolumeJob->addDependency(m_updateTreeEnabledJob); m_updateWorldBoundingVolumeJob->addDependency(m_worldTransformJob); m_updateWorldBoundingVolumeJob->addDependency(m_calculateBoundingVolumeJob); m_expandBoundingVolumeJob->addDependency(m_updateWorldBoundingVolumeJob); m_updateShaderDataTransformJob->addDependency(m_worldTransformJob); m_pickBoundingVolumeJob->addDependency(m_expandBoundingVolumeJob); - - // Dirty texture gathering depends on m_syncTextureLoadingJob - // m_syncTextureLoadingJob will depend on the texture loading jobs - m_textureGathererJob->addDependency(m_syncTextureLoadingJob); + // m_calculateBoundingVolumeJob's dependency on m_updateTreeEnabledJob is set in renderBinJobs // Ensures all skeletons are loaded before we try to update them - m_updateSkinningPaletteJob->addDependency(m_syncTextureLoadingJob); + m_updateSkinningPaletteJob->addDependency(m_syncSkeletonLoadingJob); // All world stuff depends on the RenderEntity's localBoundingVolume m_updateLevelOfDetailJob->addDependency(m_updateMeshTriangleListJob); m_pickBoundingVolumeJob->addDependency(m_updateMeshTriangleListJob); m_rayCastingJob->addDependency(m_updateMeshTriangleListJob); + // Independent job dependencies + m_beginDrawingBarrierJob->addDependency(m_vaoGathererJob); + + // Make sure we do not try to filter techniques before we have proper context + m_filterCompatibleTechniqueJob->addDependency(m_beginDrawingBarrierJob); + + // Make sure we have gathered dirty shaders, textures and buffers before calling updateGLResources + m_updateGLResourcesBarrierJob->addDependency(m_bufferGathererJob); + m_updateGLResourcesBarrierJob->addDependency(m_shaderGathererJob); + m_updateGLResourcesBarrierJob->addDependency(m_textureGathererJob); + + // Make sure we load textures after gathering + m_loadTextureJob->addDependency(m_updateGLResourcesBarrierJob); + m_loadTextureJob->addDependency(m_textureGathererJob); + + // Make sure we prepare command submission after textures are loaded + m_prepareCommandSubmissionBarrierJob->addDependency(m_loadTextureJob); + + // Make sure we have found compatible techniques before gathering shaders + m_updateGLResourcesBarrierJob->addDependency(m_filterCompatibleTechniqueJob); m_shaderGathererJob->addDependency(m_filterCompatibleTechniqueJob); m_filterCompatibleTechniqueJob->setRenderer(this); @@ -288,6 +319,7 @@ void Renderer::setNodeManagers(NodeManagers *managers) m_updateSkinningPaletteJob->setManagers(m_nodesManager); m_updateMeshTriangleListJob->setManagers(m_nodesManager); m_filterCompatibleTechniqueJob->setManager(m_nodesManager->techniqueManager()); + m_loadTextureJob->setNodeManagers(m_nodesManager); } void Renderer::setServices(QServiceLocator *services) @@ -406,12 +438,17 @@ void Renderer::shutdown() m_renderQueue->reset(); if (!m_renderThread) { + // Make sure the aspect thread is not left behind + m_willRenderPromise.store(0); + m_rendererReadySemaphore.release(); releaseGraphicsResources(); } else { // Wake up the render thread in case it is waiting for some renderviews // to be ready. The isReadyToSubmit() function checks for a shutdown // having been requested. - m_submitRenderViewsSemaphore.release(1); + m_willRenderPromise.store(0); + m_rendererReadySemaphore.release(1); + m_renderJobsReadySemaphore.release(1); m_renderThread->wait(); } } @@ -527,7 +564,7 @@ void Renderer::setSceneRoot(QBackendNodeFactory *factory, Entity *sgRoot) m_updateTreeEnabledJob->setRoot(m_renderSceneRoot); // Set all flags to dirty - m_dirtyBits.marked |= AbstractRenderer::AllDirty; + m_dirtyBits |= AbstractRenderer::AllDirty; } void Renderer::registerEventFilter(QEventFilterService *service) @@ -546,6 +583,123 @@ RenderSettings *Renderer::settings() const return m_settings; } +bool Renderer::createSurfaceLockAndMakeCurrent() +{ + FrameGraphVisitor visitor(nodeManagers()->frameGraphManager()); + const QVector<FrameGraphNode *> fgLeaves = visitor.traverse(frameGraphRoot()); + for (FrameGraphNode *leafNode : fgLeaves) { + FrameGraphNode *node = leafNode; + while (node) { + if (!node->isEnabled() || node->nodeType() != FrameGraphNode::Surface) { + node = node->parent(); + continue; + } + const auto *surfaceSelector = static_cast<const RenderSurfaceSelector *>(node); + auto locker = QSharedPointer<SurfaceLocker>::create(surfaceSelector->surface()); + if (!locker->isSurfaceValid()) + return false; + + m_surfaceLockers.append(locker); + node = node->parent(); + + if (!m_graphicsContext->makeCurrent(surfaceSelector->surface())) + return false; + + // TODO: The same surface may appear twice here, so we return early to avoid a deadlock. + // We may want to fix this at some point and make sure we properly lock multiple + // surfaces. + return true; + } + } + // No surface found + return false; +} + +// Called by render() or Scene3D on render thread +void Renderer::lockSurfaceAndRender() +{ + // Make sure we can lock the surface before rendering. This cannot be done in a job, + // because we would otherwise risk rendering into a surface that could get destroyed. + // We could lock/unlock while rendering, but that requires a fair amount of extra + // logic to be able to recover gracefully from a partially completed render. + if (!createSurfaceLockAndMakeCurrent()) { + m_surfaceLockers.clear(); + abortRenderJobs(); + // We cannot render because we could not lock the surface or the surface is a nullptr. + // However, the surface might change in the next frontend/backend sync. + // We therefore need to make sure the aspect thread does not get stuck waiting for + // the next frame. + m_vsyncFrameAdvanceService->proceedToNextFrame(); + return; + } + // Let the aspect thread know that we promise to render + m_willRenderPromise.store(1); + // Release the aspect thread + m_rendererReadySemaphore.release(); + doRender(); + // Release the surface lockers + m_surfaceLockers.clear(); +} + +/*! + * \internal + * Called by RenderAspect on aspect thread, returns false if + * the render thread has not promised to render the next frame. + * + * If this function returns false, the aspect thread + * bails out and does not issue the renderBinJobs. + * + * This keeps us from ending up in a deadlock where the barriers are + * waiting for doRender to release them. +*/ +bool Renderer::releaseRendererAndRequestPromiseToRender() +{ + // Release the render thread, which could be waiting in waitForRenderJobs + // or is about to call tryWaitForRenderJobs + m_renderJobsReadySemaphore.release(); + // Wait for the render thread to allow us to continue + m_rendererReadySemaphore.acquire(); + // Check if the render thread has promised to call doRender + return m_willRenderPromise.testAndSetOrdered(1, 0); +} + +/*! + * \internal + * Called by render(), returns false if we are no longer running +*/ +bool Renderer::waitForRenderJobs() +{ + // Wait for the aspect thread to arrive at releaseRendererAndRequestPromiseToRender, + // which is right before it will create the renderBinJobs + m_renderJobsReadySemaphore.acquire(); + // Check if we have not shut down in the meantime and rather want to bail out + return m_running.load(); +} + +/*! + * \internal + * Called by Scene3D, returns true if we could acquire +*/ +bool Renderer::tryWaitForRenderJobs(int timeout) +{ + // See if the aspect thread has arrived at releaseRendererAndRequestPromiseToRender. + // If not, Scene3D needs to continue to avoid locking up the render thread. + return m_renderJobsReadySemaphore.tryAcquire(1, timeout) && m_running.load(); +} + +/*! + * \internal + * Called by Scene3D, in shutdown +*/ +void Renderer::abortRenderJobs() +{ + // Make sure the aspect does not start render jobs + m_willRenderPromise.store(0); + // Release the aspect so it gets out of the job creation + m_rendererReadySemaphore.release(); +} + + void Renderer::render() { // Traversing the framegraph tree from root to lead node @@ -562,168 +716,102 @@ void Renderer::render() // One scene description // One framegraph description - while (m_running.load() > 0) { - doRender(); + while (waitForRenderJobs()) { + lockSurfaceAndRender(); // TO DO: Restore windows exposed detection // Probably needs to happens some place else though } } -void Renderer::doRender(bool scene3dBlocking) +/*! + * \internal + * The doRender function is called either by Renderer::render or + * QRenderAspect::tryRenderSynchronous (Scene3D). + * Jobs that it depends on are guaranteed to have been spawned by the aspect thread. + * It will run once for each set of renderBinJobs. + * Throughout the function call, the jobs are kept in sync using barriers. + * This guarantees the state of the GL context for the jobs. + * It is therefore important that any job that needs this function to be in at a specific point + * in the executio depends on the right barrier. +*/ +void Renderer::doRender() { - Renderer::ViewSubmissionResultData submissionData; - bool hasCleanedQueueAndProceeded = false; - bool preprocessingComplete = false; - bool beganDrawing = false; - const bool canSubmit = isReadyToSubmit(); - - // Lock the mutex to protect access to the renderQueue while we look for its state - QMutexLocker locker(m_renderQueue->mutex()); - bool queueIsComplete = m_renderQueue->isFrameQueueComplete(); + m_readRenderQueueSizeBarrierJob->waitForDependencies(); + const bool queueIsComplete = m_renderQueue->isFrameQueueComplete(); const bool queueIsEmpty = m_renderQueue->targetRenderViewCount() == 0; + Q_ASSERT(queueIsComplete && !queueIsEmpty); + m_readRenderQueueSizeBarrierJob->allowToProceed(); - // Scene3D Blocking Mode - if (scene3dBlocking && !queueIsComplete && !queueIsEmpty) { - int i = 0; - // We wait at most 10ms to avoid a case we could never recover from - while (!queueIsComplete && i++ < 10) { - QThread::msleep(1); - qCDebug(Backend) << Q_FUNC_INFO << "Waiting for ready queue (try:" << i << "/ 10)"; - locker.unlock(); - queueIsComplete = m_renderQueue->isFrameQueueComplete(); - locker.relock(); - } - } - - // When using synchronous rendering (QtQuick) - // We are not sure that the frame queue is actually complete - // Since a call to render may not be synched with the completions - // of the RenderViewJobs - // In such a case we return early, waiting for a next call with - // the frame queue complete at this point - - // RenderQueue is complete (but that means it may be of size 0) - if (canSubmit && (queueIsComplete && !queueIsEmpty)) { - const QVector<Render::RenderView *> renderViews = m_renderQueue->nextFrameQueue(); - + const QVector<Render::RenderView *> renderViews = m_renderQueue->nextFrameQueue(); #if QT_CONFIG(qt3d_profile_jobs) - // Save start of frame - JobRunStats submissionStatsPart1; - JobRunStats submissionStatsPart2; - submissionStatsPart1.jobId.typeAndInstance[0] = JobTypes::FrameSubmissionPart1; - submissionStatsPart1.jobId.typeAndInstance[1] = 0; - submissionStatsPart1.threadId = reinterpret_cast<quint64>(QThread::currentThreadId()); - submissionStatsPart1.startTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed(); - submissionStatsPart2.jobId.typeAndInstance[0] = JobTypes::FrameSubmissionPart2; - submissionStatsPart2.jobId.typeAndInstance[1] = 0; - submissionStatsPart2.threadId = reinterpret_cast<quint64>(QThread::currentThreadId()); + // Save start of frame + JobRunStats submissionStatsPart1; + JobRunStats submissionStatsPart2; + submissionStatsPart1.jobId.typeAndInstance[0] = JobTypes::FrameSubmissionPart1; + submissionStatsPart1.jobId.typeAndInstance[1] = 0; + submissionStatsPart1.threadId = reinterpret_cast<quint64>(QThread::currentThreadId()); + submissionStatsPart1.startTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed(); + submissionStatsPart2.jobId.typeAndInstance[0] = JobTypes::FrameSubmissionPart2; + submissionStatsPart2.jobId.typeAndInstance[1] = 0; + submissionStatsPart2.threadId = reinterpret_cast<quint64>(QThread::currentThreadId()); #endif - if (canRender()) { - { // Scoped to destroy surfaceLock - QSurface *surface = nullptr; - for (const Render::RenderView *rv: renderViews) { - surface = rv->surface(); - if (surface) - break; - } - - SurfaceLocker surfaceLock(surface); - const bool surfaceIsValid = (surface && surfaceLock.isSurfaceValid()); - if (surfaceIsValid) { - // Reset state for each draw if we don't have complete control of the context - if (!m_ownedContext) - m_graphicsContext->setCurrentStateSet(nullptr); - beganDrawing = m_graphicsContext->beginDrawing(surface); - if (beganDrawing) { - // 1) Execute commands for buffer uploads, texture updates, shader loading first - updateGLResources(); - // 2) Update VAO and copy data into commands to allow concurrent submission - prepareCommandsSubmission(renderViews); - preprocessingComplete = true; - } - } - } - // 2) Proceed to next frame and start preparing frame n + 1 - m_renderQueue->reset(); - locker.unlock(); // Done protecting RenderQueue - m_vsyncFrameAdvanceService->proceedToNextFrame(); - hasCleanedQueueAndProceeded = true; + // Reset state for each draw if we don't have complete control of the context + if (!m_ownedContext) + m_graphicsContext->setCurrentStateSet(nullptr); + // Initialize context + m_beginDrawingBarrierJob->waitForDependencies(); + m_graphicsContext->beginDrawing(); + m_beginDrawingBarrierJob->allowToProceed(); + // Execute commands for buffer uploads, texture updates, shader loading first + m_updateGLResourcesBarrierJob->waitForDependencies(); + updateGLResources(); + m_updateGLResourcesBarrierJob->allowToProceed(); + // Update VAO and copy data into commands to allow concurrent submission + m_prepareCommandSubmissionBarrierJob->waitForDependencies(); + prepareCommandsSubmission(renderViews); + m_prepareCommandSubmissionBarrierJob->allowToProceed(); + + // Proceed to next frame and start preparing frame n + 1 + m_renderQueue->reset(); + m_vsyncFrameAdvanceService->proceedToNextFrame(); #if QT_CONFIG(qt3d_profile_jobs) - if (preprocessingComplete) { - submissionStatsPart2.startTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed(); - submissionStatsPart1.endTime = submissionStatsPart2.startTime; - } + submissionStatsPart2.startTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed(); + submissionStatsPart1.endTime = submissionStatsPart2.startTime; #endif - // Only try to submit the RenderViews if the preprocessing was successful - // This part of the submission is happening in parallel to the RV building for the next frame - if (preprocessingComplete) { - // 3) Submit the render commands for frame n (making sure we never reference something that could be changing) - // Render using current device state and renderer configuration - submissionData = submitRenderViews(renderViews); - - // Perform any required cleanup of the Graphics resources (Buffers deleted, Shader deleted...) - cleanGraphicsResources(); - } - } + // Submit the render commands for frame n (making sure we never reference something that could be changing) + // Render using current device state and renderer configuration + Renderer::ViewSubmissionResultData submissionData = submitRenderViews(renderViews); + // Perform any required cleanup of the Graphics resources (Buffers deleted, Shader deleted...) + cleanGraphicsResources(); #if QT_CONFIG(qt3d_profile_jobs) - // Execute the pending shell commands - m_commandExecuter->performAsynchronousCommandExecution(renderViews); + // Execute the pending shell commands + m_commandExecuter->performAsynchronousCommandExecution(renderViews); #endif - // Delete all the RenderViews which will clear the allocators - // that were used for their allocation - qDeleteAll(renderViews); + // Delete all the RenderViews which will clear the allocators + // that were used for their allocation + qDeleteAll(renderViews); #if QT_CONFIG(qt3d_profile_jobs) - if (preprocessingComplete) { - // Save submission elapsed time - submissionStatsPart2.endTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed(); - // Note this is safe since proceedToNextFrame is the one going to trigger - // the write to the file, and this is performed after this step - Qt3DCore::QThreadPooler::addSubmissionLogStatsEntry(submissionStatsPart1); - Qt3DCore::QThreadPooler::addSubmissionLogStatsEntry(submissionStatsPart2); - Profiling::GLTimeRecorder::writeResults(); - } + // Save submission elapsed time + submissionStatsPart2.endTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed(); + // Note this is safe since proceedToNextFrame is the one going to trigger + // the write to the file, and this is performed after this step + Qt3DCore::QThreadPooler::addSubmissionLogStatsEntry(submissionStatsPart1); + Qt3DCore::QThreadPooler::addSubmissionLogStatsEntry(submissionStatsPart2); + Profiling::GLTimeRecorder::writeResults(); #endif - } - - // Only reset renderQueue and proceed to next frame if the submission - // succeeded or if we are using a render thread and that is wasn't performed - // already - - // If hasCleanedQueueAndProceeded isn't true this implies that something went wrong - // with the rendering and/or the renderqueue is incomplete from some reason - // (in the case of scene3d the render jobs may be taking too long ....) - // or alternatively it could be complete but empty (RenderQueue of size 0) - if (!hasCleanedQueueAndProceeded && - (m_renderThread || queueIsComplete || queueIsEmpty)) { - // RenderQueue was full but something bad happened when - // trying to render it and therefore proceedToNextFrame was not called - // Note: in this case the renderQueue mutex is still locked - - // Reset the m_renderQueue so that we won't try to render - // with a queue used by a previous frame with corrupted content - // if the current queue was correctly submitted - m_renderQueue->reset(); - - // We allow the RenderTickClock service to proceed to the next frame - // In turn this will allow the aspect manager to request a new set of jobs - // to be performed for each aspect - m_vsyncFrameAdvanceService->proceedToNextFrame(); - } // Perform the last swapBuffers calls after the proceedToNextFrame // as this allows us to gain a bit of time for the preparation of the // next frame // Finish up with last surface used in the list of RenderViews - if (beganDrawing) { - SurfaceLocker surfaceLock(submissionData.surface); - // Finish up with last surface used in the list of RenderViews - m_graphicsContext->endDrawing(submissionData.lastBoundFBOId == m_graphicsContext->defaultFBO() && surfaceLock.isSurfaceValid()); - } + m_endDrawingBarrierJob->waitForDependencies(); + m_graphicsContext->endDrawing(submissionData.lastBoundFBOId == m_graphicsContext->defaultFBO()); + m_endDrawingBarrierJob->allowToProceed(); } // Called by RenderViewJobs @@ -738,48 +826,8 @@ void Renderer::enqueueRenderView(Render::RenderView *renderView, int submitOrder // could be invalid since depending on the order of execution // the counter could be complete but the renderview not yet added to the // buffer depending on whichever order the cpu decides to process this - const bool isQueueComplete = m_renderQueue->queueRenderView(renderView, submitOrder); + m_renderQueue->queueRenderView(renderView, submitOrder); locker.unlock(); // We're done protecting the queue at this point - if (isQueueComplete) { - if (m_renderThread && m_running.load()) - Q_ASSERT(m_submitRenderViewsSemaphore.available() == 0); - m_submitRenderViewsSemaphore.release(1); - } -} - -bool Renderer::canRender() const -{ - // Make sure that we've not been told to terminate - if (m_renderThread && !m_running.load()) { - qCDebug(Rendering) << "RenderThread termination requested whilst waiting"; - return false; - } - - // TO DO: Check if all surfaces have been destroyed... - // It may be better if the last window to be closed trigger a call to shutdown - // Rather than having checks for the surface everywhere - - return true; -} - -bool Renderer::isReadyToSubmit() -{ - // If we are using a render thread, make sure that - // we've been told to render before rendering - if (m_renderThread) { // Prevent ouf of order execution - m_submitRenderViewsSemaphore.acquire(1); - - // Check if shutdown has been requested - if (m_running.load() == 0) - return false; - - // When using Thread rendering, the semaphore should only - // be released when the frame queue is complete and there's - // something to render - // The case of shutdown should have been handled just before - Q_ASSERT(m_renderQueue->isFrameQueueComplete()); - } - return true; } // Main thread @@ -890,6 +938,7 @@ void Renderer::prepareCommandsSubmission(const QVector<RenderView *> &renderView const QVector<Qt3DCore::QNodeId> attributeIds = rGeometry->attributes(); for (Qt3DCore::QNodeId attributeId : attributeIds) { Attribute *attribute = m_nodesManager->attributeManager()->lookupResource(attributeId); + Q_ASSERT(attribute); switch (attribute->attributeType()) { case QAttribute::IndexAttribute: indexAttribute = attribute; @@ -922,6 +971,7 @@ void Renderer::prepareCommandsSubmission(const QVector<RenderView *> &renderView if (command->m_drawIndirect) { command->m_indirectAttributeByteOffset = indirectAttribute->byteOffset(); command->m_indirectDrawBuffer = m_nodesManager->bufferManager()->lookupHandle(indirectAttribute->bufferId()); + Q_ASSERT(!command->m_indirectDrawBuffer.isNull()); } else { // Use the count specified by the GeometryRender // If not specify use the indexAttribute count if present @@ -1037,6 +1087,7 @@ void Renderer::lookForDirtyShaders() RenderPass *renderPass = m_nodesManager->renderPassManager()->lookupResource(passId); HShader shaderHandle = m_nodesManager->shaderManager()->lookupHandle(renderPass->shaderProgram()); Shader *shader = m_nodesManager->shaderManager()->data(shaderHandle); + Q_ASSERT(renderPass && shader); ShaderBuilder *shaderBuilder = nullptr; for (const HShaderBuilder &builderHandle : activeBuilders) { @@ -1103,6 +1154,7 @@ void Renderer::updateGLResources() const QVector<HBuffer> dirtyBufferHandles = std::move(m_dirtyBuffers); for (const HBuffer &handle: dirtyBufferHandles) { Buffer *buffer = m_nodesManager->bufferManager()->data(handle); + Q_ASSERT(buffer); // 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)) @@ -1119,6 +1171,7 @@ void Renderer::updateGLResources() ShaderManager *shaderManager = m_nodesManager->shaderManager(); for (const HShader &handle: dirtyShaderHandles) { Shader *shader = shaderManager->data(handle); + Q_ASSERT(shader); // Compile shader m_graphicsContext->loadShader(shader, shaderManager); } @@ -1129,6 +1182,7 @@ void Renderer::updateGLResources() const QVector<HTexture> activeTextureHandles = std::move(m_dirtyTextures); for (const HTexture &handle: activeTextureHandles) { Texture *texture = m_nodesManager->textureManager()->data(handle); + Q_ASSERT(texture); // Upload/Update texture updateTexture(texture); } @@ -1236,6 +1290,7 @@ void Renderer::updateTexture(Texture *texture) // Render Thread void Renderer::cleanupTexture(const Texture *texture) { + Q_ASSERT(texture); GLTextureManager *glTextureManager = m_nodesManager->glTextureManager(); GLTexture *glTexture = glTextureManager->lookupResource(texture->peerId()); @@ -1288,7 +1343,6 @@ Renderer::ViewSubmissionResultData Renderer::submitRenderViews(const QVector<Ren // If not, we have to free up the context from the previous surface // and make the context current on the new surface surface = renderView->surface(); - SurfaceLocker surfaceLock(surface); // TO DO: Make sure that the surface we are rendering too has not been unset @@ -1296,7 +1350,7 @@ Renderer::ViewSubmissionResultData Renderer::submitRenderViews(const QVector<Ren // TODO: Investigate if it's worth providing a fallback offscreen surface // to use when surface is null. Or if we should instead expose an // offscreensurface to Qt3D. - if (!surface || !surfaceLock.isSurfaceValid()) { + if (!surface) { m_lastFrameCorrect.store(0); continue; } @@ -1313,12 +1367,14 @@ Renderer::ViewSubmissionResultData Renderer::submitRenderViews(const QVector<Ren if (surfaceHasChanged) { // If we can't make the context current on the surface, skip to the // next RenderView. We won't get the full frame but we may get something - if (!m_graphicsContext->beginDrawing(surface)) { + if (!m_graphicsContext->makeCurrent(surface)) { qWarning() << "Failed to make OpenGL context current on surface"; m_lastFrameCorrect.store(0); continue; } + m_graphicsContext->beginDrawing(); + previousSurface = surface; lastBoundFBOId = m_graphicsContext->boundFrameBufferObject(); } @@ -1457,39 +1513,35 @@ Renderer::ViewSubmissionResultData Renderer::submitRenderViews(const QVector<Ren void Renderer::markDirty(BackendNodeDirtySet changes, BackendNode *node) { Q_UNUSED(node); - m_dirtyBits.marked |= changes; + m_dirtyBits|= changes; } Renderer::BackendNodeDirtySet Renderer::dirtyBits() { - return m_dirtyBits.marked; + return m_dirtyBits; } #if defined(QT_BUILD_INTERNAL) void Renderer::clearDirtyBits(BackendNodeDirtySet changes) { - m_dirtyBits.remaining &= ~changes; - m_dirtyBits.marked &= ~changes; + m_dirtyBits &= ~changes; } #endif bool Renderer::shouldRender() { + if (!m_settings) + return false; // Only render if something changed during the last frame, or the last frame // was not rendered successfully (or render-on-demand is disabled) return (m_settings->renderPolicy() == QRenderSettings::Always - || m_dirtyBits.marked != 0 - || m_dirtyBits.remaining != 0 + || m_dirtyBits != 0 || !m_lastFrameCorrect.load()); } void Renderer::skipNextFrame() { - Q_ASSERT(m_settings->renderPolicy() != QRenderSettings::Always); - - // make submitRenderViews() actually run - m_renderQueue->setNoRender(); - m_submitRenderViewsSemaphore.release(1); + m_vsyncFrameAdvanceService->proceedToNextFrame(); } // Waits to be told to create jobs for the next frame @@ -1500,28 +1552,46 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs() { QVector<QAspectJobPtr> renderBinJobs; - // Create the jobs to build the frame - const QVector<QAspectJobPtr> bufferJobs = createRenderBufferJobs(); - // Remove previous dependencies m_calculateBoundingVolumeJob->removeDependency(QWeakPointer<QAspectJob>()); m_cleanupJob->removeDependency(QWeakPointer<QAspectJob>()); - // Set dependencies - for (const QAspectJobPtr &bufferJob : bufferJobs) - m_calculateBoundingVolumeJob->addDependency(bufferJob); + // Render thread barrier jobs + renderBinJobs.append(m_readRenderQueueSizeBarrierJob); + renderBinJobs.append(m_beginDrawingBarrierJob); + renderBinJobs.append(m_updateGLResourcesBarrierJob); + renderBinJobs.append(m_prepareCommandSubmissionBarrierJob); + renderBinJobs.append(m_endDrawingBarrierJob); + // Jobs independent of dirty bits + renderBinJobs.push_back(m_updateSkinningPaletteJob); + renderBinJobs.push_back(m_updateLevelOfDetailJob); + renderBinJobs.push_back(m_cleanupJob); + renderBinJobs.push_back(m_sendRenderCaptureJob); + renderBinJobs.push_back(m_sendBufferCaptureJob); + renderBinJobs.push_back(m_vaoGathererJob); + + // Independent job properties + m_updateSkinningPaletteJob->setDirtyJoints(m_nodesManager->jointManager()->dirtyJoints()); m_updateLevelOfDetailJob->setFrameGraphRoot(frameGraphRoot()); - const BackendNodeDirtySet dirtyBitsForFrame = m_dirtyBits.marked | m_dirtyBits.remaining; - m_dirtyBits.marked = 0; - m_dirtyBits.remaining = 0; - BackendNodeDirtySet notCleared = 0; + // Buffer jobs, depends on dirty buffers + const QVector<QAspectJobPtr> bufferJobs = createRenderBufferJobs(); + for (const QAspectJobPtr &bufferJob : bufferJobs) { + m_calculateBoundingVolumeJob->addDependency(bufferJob); + m_beginDrawingBarrierJob->addDependency(bufferJob); + } + renderBinJobs.append(bufferJobs); + + // Jobs dependent on dirty bits + const BackendNodeDirtySet dirtyBitsForFrame = m_dirtyBits; + m_dirtyBits = 0; - // Add jobs const bool entitiesEnabledDirty = dirtyBitsForFrame & AbstractRenderer::EntityEnabledDirty; if (entitiesEnabledDirty) { renderBinJobs.push_back(m_updateTreeEnabledJob); + // This dependency is added here because we clear all dependencies + // at the start of this function. m_calculateBoundingVolumeJob->addDependency(m_updateTreeEnabledJob); } @@ -1541,80 +1611,55 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs() renderBinJobs.push_back(m_expandBoundingVolumeJob); } - m_updateSkinningPaletteJob->setDirtyJoints(m_nodesManager->jointManager()->dirtyJoints()); - renderBinJobs.push_back(m_updateSkinningPaletteJob); - renderBinJobs.push_back(m_updateLevelOfDetailJob); - renderBinJobs.push_back(m_cleanupJob); - renderBinJobs.push_back(m_sendRenderCaptureJob); - renderBinJobs.push_back(m_sendBufferCaptureJob); - renderBinJobs.append(bufferJobs); - - // Jobs to prepare GL Resource upload - renderBinJobs.push_back(m_vaoGathererJob); - if (dirtyBitsForFrame & AbstractRenderer::BuffersDirty) renderBinJobs.push_back(m_bufferGathererJob); if (dirtyBitsForFrame & AbstractRenderer::TexturesDirty) { - renderBinJobs.push_back(m_syncTextureLoadingJob); + renderBinJobs.push_back(m_loadTextureJob); renderBinJobs.push_back(m_textureGathererJob); } + if (dirtyBitsForFrame & AbstractRenderer::SkeletonDataDirty) + renderBinJobs.push_back(m_syncSkeletonLoadingJob); + + if (dirtyBitsForFrame & AbstractRenderer::TechniquesDirty ) + renderBinJobs.push_back(m_filterCompatibleTechniqueJob); + + if (dirtyBitsForFrame & AbstractRenderer::ShadersDirty) + renderBinJobs.push_back(m_shaderGathererJob); // Layer cache is dependent on layers, layer filters and the enabled flag // on entities const bool layersDirty = dirtyBitsForFrame & AbstractRenderer::LayersDirty; const bool layersCacheNeedsToBeRebuilt = layersDirty || entitiesEnabledDirty; - const bool materialDirty = dirtyBitsForFrame & AbstractRenderer::MaterialDirty; - QMutexLocker lock(m_renderQueue->mutex()); - if (m_renderQueue->wasReset()) { // Have we rendered yet? (Scene3D case) - // Traverse the current framegraph. For each leaf node create a - // RenderView and set its configuration then create a job to - // populate the RenderView with a set of RenderCommands that get - // their details from the RenderNodes that are visible to the - // Camera selected by the framegraph configuration - FrameGraphVisitor visitor(m_nodesManager->frameGraphManager()); - const QVector<FrameGraphNode *> fgLeaves = visitor.traverse(frameGraphRoot()); - - // Remove leaf nodes that no longer exist from cache - const QList<FrameGraphNode *> keys = m_cache.leafNodeCache.keys(); - for (FrameGraphNode *leafNode : keys) { - if (!fgLeaves.contains(leafNode)) - m_cache.leafNodeCache.remove(leafNode); - } - - const int fgBranchCount = fgLeaves.size(); - for (int i = 0; i < fgBranchCount; ++i) { - RenderViewBuilder builder(fgLeaves.at(i), i, this); - builder.setLayerCacheNeedsToBeRebuilt(layersCacheNeedsToBeRebuilt); - builder.setMaterialGathererCacheNeedsToBeRebuilt(materialDirty); - builder.prepareJobs(); - renderBinJobs.append(builder.buildJobHierachy()); - } - - // Set target number of RenderViews - m_renderQueue->setTargetRenderViewCount(fgBranchCount); - } else { - // FilterLayerEntityJob is part of the RenderViewBuilder jobs and must be run later - // if none of those jobs are started this frame - notCleared |= AbstractRenderer::EntityEnabledDirty; - notCleared |= AbstractRenderer::LayersDirty; + // Traverse the current framegraph. For each leaf node create a + // RenderView and set its configuration then create a job to + // populate the RenderView with a set of RenderCommands that get + // their details from the RenderNodes that are visible to the + // Camera selected by the framegraph configuration + FrameGraphVisitor visitor(m_nodesManager->frameGraphManager()); + const QVector<FrameGraphNode *> fgLeaves = visitor.traverse(frameGraphRoot()); + + // Remove leaf nodes that no longer exist from cache + const QList<FrameGraphNode *> keys = m_cache.leafNodeCache.keys(); + for (FrameGraphNode *leafNode : keys) { + if (!fgLeaves.contains(leafNode)) + m_cache.leafNodeCache.remove(leafNode); } - if (isRunning() && m_graphicsContext->isInitialized()) { - if (dirtyBitsForFrame & AbstractRenderer::TechniquesDirty ) - renderBinJobs.push_back(m_filterCompatibleTechniqueJob); - if (dirtyBitsForFrame & AbstractRenderer::ShadersDirty) - renderBinJobs.push_back(m_shaderGathererJob); - } else { - notCleared |= AbstractRenderer::TechniquesDirty; - notCleared |= AbstractRenderer::ShadersDirty; - notCleared |= AbstractRenderer::MaterialDirty; + const int fgBranchCount = fgLeaves.size(); + for (int i = 0; i < fgBranchCount; ++i) { + RenderViewBuilder builder(fgLeaves.at(i), i, this); + builder.setLayerCacheNeedsToBeRebuilt(layersCacheNeedsToBeRebuilt); + builder.setMaterialGathererCacheNeedsToBeRebuilt(materialDirty); + builder.prepareJobs(); + renderBinJobs.append(builder.buildJobHierachy()); } - m_dirtyBits.remaining = dirtyBitsForFrame & notCleared; + // Set target number of RenderViews + m_renderQueue->setTargetRenderViewCount(fgBranchCount); return renderBinJobs; } @@ -1645,9 +1690,9 @@ QAspectJobPtr Renderer::rayCastingJob() return m_rayCastingJob; } -QAspectJobPtr Renderer::syncTextureLoadingJob() +QAspectJobPtr Renderer::syncSkeletonLoadingJob() { - return m_syncTextureLoadingJob; + return m_syncSkeletonLoadingJob; } QAspectJobPtr Renderer::expandBoundingVolumeJob() @@ -1752,7 +1797,7 @@ void Renderer::performCompute(const RenderView *, RenderCommand *command) command->m_workGroups[2]); } // HACK: Reset the compute flag to dirty - m_dirtyBits.marked |= AbstractRenderer::ComputeDirty; + m_dirtyBits |= AbstractRenderer::ComputeDirty; #if defined(QT3D_RENDER_ASPECT_OPENGL_DEBUG) int err = m_graphicsContext->openGLContext()->functions()->glGetError(); @@ -1888,11 +1933,13 @@ bool Renderer::updateVAOWithAttributes(Geometry *geometry, for (QNodeId attributeId : attributeIds) { // TO DO: Improvement we could store handles and use the non locking policy on the attributeManager Attribute *attribute = m_nodesManager->attributeManager()->lookupResource(attributeId); + Q_ASSERT(attribute); if (attribute == nullptr) return false; Buffer *buffer = m_nodesManager->bufferManager()->lookupResource(attribute->bufferId()); + Q_ASSERT(buffer); // Buffer update was already performed at this point // Just make sure the attribute reference a valid buffer @@ -1945,6 +1992,7 @@ bool Renderer::requiresVAOAttributeUpdate(Geometry *geometry, for (QNodeId attributeId : attributeIds) { // TO DO: Improvement we could store handles and use the non locking policy on the attributeManager Attribute *attribute = m_nodesManager->attributeManager()->lookupResource(attributeId); + Q_ASSERT(attribute); if (attribute == nullptr) continue; @@ -1986,7 +2034,7 @@ void Renderer::cleanGraphicsResources() } } -QList<QMouseEvent> Renderer::pendingPickingEvents() const +QList<QPair<QObject *, QMouseEvent>> Renderer::pendingPickingEvents() const { return m_pickEventFilter->pendingMouseEvents(); } diff --git a/src/render/backend/renderer_p.h b/src/render/backend/renderer_p.h index 521d17e80..fbb29dc7c 100644 --- a/src/render/backend/renderer_p.h +++ b/src/render/backend/renderer_p.h @@ -144,6 +144,10 @@ class NodeManagers; class UpdateLevelOfDetailJob; typedef QSharedPointer<UpdateLevelOfDetailJob> UpdateLevelOfDetailJobPtr; +class LoadTextureDataJob; +using LoadTextureDataJobPtr = QSharedPointer<LoadTextureDataJob>; +class RenderBarrierJob; +using RenderBarrierJobPtr = QSharedPointer<RenderBarrierJob>; using SynchronizerJobPtr = GenericLambdaJobPtr<std::function<void()>>; @@ -171,7 +175,7 @@ public: void releaseGraphicsResources() override; void render() override; - void doRender(bool scene3dBlocking = false) override; + void doRender() override; void cleanGraphicsResources() override; bool isRunning() const override { return m_running.load(); } @@ -188,17 +192,29 @@ public: void clearDirtyBits(BackendNodeDirtySet changes) override; #endif + void lockSurfaceAndRender() override; + bool releaseRendererAndRequestPromiseToRender() override; + bool waitForRenderJobs() override; + bool tryWaitForRenderJobs(int timeout) override; + void abortRenderJobs() override; + bool shouldRender() override; void skipNextFrame() override; QVector<Qt3DCore::QAspectJobPtr> renderBinJobs() override; Qt3DCore::QAspectJobPtr pickBoundingVolumeJob() override; Qt3DCore::QAspectJobPtr rayCastingJob() override; - Qt3DCore::QAspectJobPtr syncTextureLoadingJob() override; + Qt3DCore::QAspectJobPtr syncSkeletonLoadingJob() override; Qt3DCore::QAspectJobPtr expandBoundingVolumeJob() override; QVector<Qt3DCore::QAspectJobPtr> createRenderBufferJobs() const; + inline RenderBarrierJobPtr readRenderQueueSizeBarrierJob() const { return m_readRenderQueueSizeBarrierJob; } + inline RenderBarrierJobPtr beginDrawingBarrierJob() const { return m_beginDrawingBarrierJob; } + inline RenderBarrierJobPtr updateGLResourcesBarrierJob() const { return m_updateGLResourcesBarrierJob; } + inline RenderBarrierJobPtr prepareCommandSubmissionBarrierJob() const { return m_prepareCommandSubmissionBarrierJob; } + inline RenderBarrierJobPtr endDrawingBarrierJob() const { return m_endDrawingBarrierJob; } + inline FrameCleanupJobPtr frameCleanupJob() const { return m_cleanupJob; } inline UpdateShaderDataTransformJobPtr updateShaderDataTransformJob() const { return m_updateShaderDataTransformJob; } inline CalculateBoundingVolumeJobPtr calculateBoundingVolumeJob() const { return m_calculateBoundingVolumeJob; } @@ -208,8 +224,9 @@ public: inline UpdateLevelOfDetailJobPtr updateLevelOfDetailJob() const { return m_updateLevelOfDetailJob; } inline UpdateMeshTriangleListJobPtr updateMeshTriangleListJob() const { return m_updateMeshTriangleListJob; } inline FilterCompatibleTechniqueJobPtr filterCompatibleTechniqueJob() const { return m_filterCompatibleTechniqueJob; } - inline SynchronizerJobPtr textureLoadSyncJob() const { return m_syncTextureLoadingJob; } + inline SynchronizerJobPtr textureLoadSyncJob() const { return m_syncSkeletonLoadingJob; } inline UpdateSkinningPaletteJobPtr updateSkinningPaletteJob() const { return m_updateSkinningPaletteJob; } + inline LoadTextureDataJobPtr loadTextureJob() const {return m_loadTextureJob; } Qt3DCore::QAbstractFrameAdvanceService *frameAdvanceService() const override; @@ -245,14 +262,13 @@ public: inline RenderStateSet *defaultRenderState() const { return m_defaultRenderStateSet; } - QList<QMouseEvent> pendingPickingEvents() const; + QList<QPair<QObject*, QMouseEvent>> pendingPickingEvents() const; QList<QKeyEvent> pendingKeyEvents() const; void addRenderCaptureSendRequest(Qt3DCore::QNodeId nodeId); const QVector<Qt3DCore::QNodeId> takePendingRenderCaptureSendRequests(); void enqueueRenderView(RenderView *renderView, int submitOrder); - bool isReadyToSubmit(); QVariant executeCommand(const QStringList &args) override; void setOffscreenSurfaceHelper(OffscreenSurfaceHelper *helper) override; @@ -279,7 +295,7 @@ public: private: #endif - bool canRender() const; + bool hasBeenAskedToTerminate() const; Qt3DCore::QServiceLocator *m_services; NodeManagers *m_nodesManager; @@ -301,7 +317,6 @@ private: QScopedPointer<RenderThread> m_renderThread; QScopedPointer<VSyncFrameAdvanceService> m_vsyncFrameAdvanceService; - QSemaphore m_submitRenderViewsSemaphore; QSemaphore m_waitForInitializationToBeCompleted; QAtomicInt m_running; @@ -312,11 +327,7 @@ private: QVector<Geometry *> m_dirtyGeometry; QAtomicInt m_exposed; - struct DirtyBits { - BackendNodeDirtySet marked = 0; // marked dirty since last job build - BackendNodeDirtySet remaining = 0; // remaining dirty after jobs have finished - }; - DirtyBits m_dirtyBits; + BackendNodeDirtySet m_dirtyBits; QAtomicInt m_lastFrameCorrect; QOpenGLContext *m_glContext; @@ -354,15 +365,18 @@ private: GenericLambdaJobPtr<std::function<void ()>> m_bufferGathererJob; GenericLambdaJobPtr<std::function<void ()>> m_vaoGathererJob; GenericLambdaJobPtr<std::function<void ()>> m_textureGathererJob; + LoadTextureDataJobPtr m_loadTextureJob; + GenericLambdaJobPtr<std::function<void ()>> m_shaderGathererJob; - SynchronizerJobPtr m_syncTextureLoadingJob; + SynchronizerJobPtr m_syncSkeletonLoadingJob; void lookForAbandonedVaos(); void lookForDirtyBuffers(); void lookForDownloadableBuffers(); void lookForDirtyTextures(); void lookForDirtyShaders(); + bool createSurfaceLockAndMakeCurrent(); QMutex m_abandonedVaosMutex; QVector<HVao> m_abandonedVaos; @@ -384,6 +398,18 @@ private: QMetaObject::Connection m_contextConnection; RendererCache m_cache; + + RenderBarrierJobPtr m_readRenderQueueSizeBarrierJob; + RenderBarrierJobPtr m_beginDrawingBarrierJob; + RenderBarrierJobPtr m_updateGLResourcesBarrierJob; + RenderBarrierJobPtr m_prepareCommandSubmissionBarrierJob; + RenderBarrierJobPtr m_endDrawingBarrierJob; + + QAtomicInt m_willRenderPromise; + QSemaphore m_rendererReadySemaphore; + QSemaphore m_renderJobsReadySemaphore; + + QVector<QSharedPointer<SurfaceLocker>> m_surfaceLockers; }; } // namespace Render diff --git a/src/render/backend/renderqueue.cpp b/src/render/backend/renderqueue.cpp index 2fa1cb7d2..db75558a4 100644 --- a/src/render/backend/renderqueue.cpp +++ b/src/render/backend/renderqueue.cpp @@ -90,7 +90,6 @@ bool RenderQueue::queueRenderView(RenderView *renderView, uint submissionOrderIn Q_ASSERT(!m_noRender); m_currentWorkQueue[submissionOrderIndex] = renderView; ++m_currentRenderViewCount; - Q_ASSERT(m_currentRenderViewCount <= m_targetRenderViewCount); return isFrameQueueComplete(); } diff --git a/src/render/backend/renderview.cpp b/src/render/backend/renderview.cpp index 055c14143..84de728d4 100644 --- a/src/render/backend/renderview.cpp +++ b/src/render/backend/renderview.cpp @@ -148,16 +148,16 @@ static QRectF resolveViewport(const QRectF &fractionalViewport, const QSize &sur fractionalViewport.height() * surfaceSize.height()); } -static QMatrix4x4 getProjectionMatrix(const CameraLens *lens) +static Matrix4x4 getProjectionMatrix(const CameraLens *lens) { if (!lens) qWarning() << "[Qt3D Renderer] No Camera Lens found. Add a CameraSelector to your Frame Graph or make sure that no entities will be rendered."; - return lens ? lens->projection() : QMatrix4x4(); + return lens ? lens->projection() : Matrix4x4(); } UniformValue RenderView::standardUniformValue(RenderView::StandardUniform standardUniformType, Entity *entity, - const QMatrix4x4 &model) const + const Matrix4x4 &model) const { switch (standardUniformType) { case ModelMatrix: @@ -182,24 +182,26 @@ UniformValue RenderView::standardUniformValue(RenderView::StandardUniform standa case InverseModelViewMatrix: return UniformValue((m_data.m_viewMatrix * model).inverted()); case InverseViewProjectionMatrix: { - const QMatrix4x4 viewProjectionMatrix = getProjectionMatrix(m_data.m_renderCameraLens) * m_data.m_viewMatrix; + const Matrix4x4 viewProjectionMatrix = getProjectionMatrix(m_data.m_renderCameraLens) * m_data.m_viewMatrix; return UniformValue(viewProjectionMatrix.inverted()); } case InverseModelViewProjectionMatrix: - return UniformValue((m_data.m_viewProjectionMatrix * model).inverted(0)); + return UniformValue((m_data.m_viewProjectionMatrix * model).inverted()); case ModelNormalMatrix: - return UniformValue(model.normalMatrix()); + return UniformValue(convertToQMatrix4x4(model).normalMatrix()); case ModelViewNormalMatrix: - return UniformValue((m_data.m_viewMatrix * model).normalMatrix()); + return UniformValue(convertToQMatrix4x4(m_data.m_viewMatrix * model).normalMatrix()); case ViewportMatrix: { QMatrix4x4 viewportMatrix; + // TO DO: Implement on Matrix4x4 viewportMatrix.viewport(resolveViewport(m_viewport, m_surfaceSize)); - return UniformValue(viewportMatrix); + return UniformValue(Matrix4x4(viewportMatrix)); } case InverseViewportMatrix: { QMatrix4x4 viewportMatrix; + // TO DO: Implement on Matrix4x4 viewportMatrix.viewport(resolveViewport(m_viewport, m_surfaceSize)); - return UniformValue(viewportMatrix.inverted()); + return UniformValue(Matrix4x4(viewportMatrix.inverted())); } case AspectRatio: return float(m_surfaceSize.width()) / float(m_surfaceSize.height()); @@ -518,20 +520,6 @@ void RenderView::setRenderer(Renderer *renderer) m_manager = renderer->nodeManagers(); } -class LightSourceCompare -{ -public: - LightSourceCompare(Entity *node) { p = node->worldBoundingVolume()->center(); } - bool operator()(const LightSource &a, const LightSource &b) const { - const float distA = p.distanceToPoint(a.entity->worldBoundingVolume()->center()); - const float distB = p.distanceToPoint(b.entity->worldBoundingVolume()->center()); - return distA < distB; - } - -private: - QVector3D p; -}; - void RenderView::addClearBuffers(const ClearBuffers *cb) { QClearBuffers::BufferTypeFlags type = cb->type(); @@ -603,7 +591,7 @@ QVector<RenderCommand *> RenderView::buildDrawRenderCommands(const QVector<Entit // Project the camera-to-object-center vector onto the camera // view vector. This gives a depth value suitable as the key // for BackToFront sorting. - command->m_depth = QVector3D::dotProduct(entity->worldBoundingVolume()->center() - m_data.m_eyePos, m_data.m_eyeViewDir); + command->m_depth = Vector3D::dotProduct(entity->worldBoundingVolume()->center() - m_data.m_eyePos, m_data.m_eyeViewDir); command->m_geometry = geometryHandle; command->m_geometryRenderer = geometryRendererHandle; @@ -629,8 +617,15 @@ QVector<RenderCommand *> RenderView::buildDrawRenderCommands(const QVector<Entit // Replace with more sophisticated mechanisms later. // Copy vector so that we can sort it concurrently and we only want to sort the one for the current command QVector<LightSource> lightSources = m_lightSources; - if (lightSources.size() > 1) - std::sort(lightSources.begin(), lightSources.end(), LightSourceCompare(entity)); + if (lightSources.size() > 1) { + const Vector3D entityCenter = entity->worldBoundingVolume()->center(); + std::sort(lightSources.begin(), lightSources.end(), + [&] (const LightSource &a, const LightSource &b) { + const float distA = entityCenter.distanceToPoint(a.entity->worldBoundingVolume()->center()); + const float distB = entityCenter.distanceToPoint(b.entity->worldBoundingVolume()->center()); + return distA < distB; + }); + } ParameterInfoList globalParameters = passData.parameterInfo; // setShaderAndUniforms can initialize a localData @@ -653,6 +648,7 @@ QVector<RenderCommand *> RenderView::buildDrawRenderCommands(const QVector<Entit const QVector<Qt3DCore::QNodeId> attributeIds = geometry->attributes(); for (Qt3DCore::QNodeId attributeId : attributeIds) { Attribute *attribute = m_manager->attributeManager()->lookupResource(attributeId); + Q_ASSERT(attribute != nullptr); if (attribute->attributeType() == QAttribute::IndexAttribute) indexAttribute = attribute; else if (command->m_attributes.contains(attribute->nameId())) @@ -755,21 +751,21 @@ QVector<RenderCommand *> RenderView::buildComputeRenderCommands(const QVector<En void RenderView::updateMatrices() { if (m_data.m_renderCameraNode && m_data.m_renderCameraLens && m_data.m_renderCameraLens->isEnabled()) { - const QMatrix4x4 cameraWorld = *(m_data.m_renderCameraNode->worldTransform()); + const Matrix4x4 cameraWorld = *(m_data.m_renderCameraNode->worldTransform()); setViewMatrix(m_data.m_renderCameraLens->viewMatrix(cameraWorld)); 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. - const QMatrix4x4 inverseWorldTransform = viewMatrix().inverted(); - const QVector3D eyePosition(inverseWorldTransform.column(3)); + const Matrix4x4 inverseWorldTransform = viewMatrix().inverted(); + const Vector3D eyePosition(inverseWorldTransform.column(3)); setEyePosition(eyePosition); // Get the viewing direction of the camera. Use the normal matrix to // ensure non-uniform scale works too. - QMatrix3x3 normalMat = m_data.m_viewMatrix.normalMatrix(); + const QMatrix3x3 normalMat = convertToQMatrix4x4(m_data.m_viewMatrix).normalMatrix(); // dir = normalize(QVector3D(0, 0, -1) * normalMat) - setEyeViewDirection(QVector3D(-normalMat(2, 0), -normalMat(2, 1), -normalMat(2, 2)).normalized()); + setEyeViewDirection(Vector3D(-normalMat(2, 0), -normalMat(2, 1), -normalMat(2, 2)).normalized()); } } @@ -780,14 +776,19 @@ void RenderView::setUniformValue(ShaderParameterPack &uniformPack, int nameId, c // ShaderData/Buffers would be handled as UBO/SSBO and would therefore // not be in the default uniform block if (value.valueType() == UniformValue::NodeId) { - const Qt3DCore::QNodeId texId = *value.constData<Qt3DCore::QNodeId>(); - const Texture *tex = m_manager->textureManager()->lookupResource(texId); - if (tex != nullptr) { - uniformPack.setTexture(nameId, texId); - UniformValue::Texture textureValue; - textureValue.nodeId = texId; - uniformPack.setUniform(nameId, UniformValue(textureValue)); + const Qt3DCore::QNodeId *nodeIds = value.constData<Qt3DCore::QNodeId>(); + + const int uniformArraySize = value.byteSize() / sizeof(Qt3DCore::QNodeId); + for (int i = 0; i < uniformArraySize; ++i) { + const Qt3DCore::QNodeId texId = nodeIds[i]; + const Texture *tex = m_manager->textureManager()->lookupResource(texId); + if (tex != nullptr) + uniformPack.setTexture(nameId, i, texId); } + + UniformValue textureValue(uniformArraySize * sizeof(int), UniformValue::TextureValue); + std::fill(textureValue.data<int>(), textureValue.data<int>() + uniformArraySize, -1); + uniformPack.setUniform(nameId, textureValue); } else { uniformPack.setUniform(nameId, value); } @@ -797,7 +798,7 @@ void RenderView::setStandardUniformValue(ShaderParameterPack &uniformPack, int glslNameId, int nameId, Entity *entity, - const QMatrix4x4 &worldTransform) const + const Matrix4x4 &worldTransform) const { uniformPack.setUniform(glslNameId, standardUniformValue(ms_standardUniformSetters[nameId], entity, worldTransform)); } @@ -963,7 +964,7 @@ void RenderView::setShaderAndUniforms(RenderCommand *command, !shaderStorageBlockNamesIds.isEmpty() || !attributeNamesIds.isEmpty()) { // Set default standard uniforms without bindings - QMatrix4x4 worldTransform = *(entity->worldTransform()); + const Matrix4x4 worldTransform = *(entity->worldTransform()); for (const int uniformNameId : uniformNamesIds) { if (ms_standardUniformSetters.contains(uniformNameId)) setStandardUniformValue(command->m_parameterPack, uniformNameId, uniformNameId, entity, worldTransform); @@ -1010,7 +1011,7 @@ void RenderView::setShaderAndUniforms(RenderCommand *command, if (lightIdx == MAX_LIGHTS) break; Entity *lightEntity = lightSource.entity; - const QVector3D worldPos = lightEntity->worldBoundingVolume()->center(); + const Vector3D worldPos = lightEntity->worldBoundingVolume()->center(); for (Light *light : lightSource.lights) { if (!light->isEnabled()) continue; @@ -1025,13 +1026,13 @@ void RenderView::setShaderAndUniforms(RenderCommand *command, // Note: implicit conversion of values to UniformValue setUniformValue(command->m_parameterPack, LIGHT_POSITION_NAMES[lightIdx], worldPos); setUniformValue(command->m_parameterPack, LIGHT_TYPE_NAMES[lightIdx], int(QAbstractLight::PointLight)); - setUniformValue(command->m_parameterPack, LIGHT_COLOR_NAMES[lightIdx], QVector3D(1.0f, 1.0f, 1.0f)); + setUniformValue(command->m_parameterPack, LIGHT_COLOR_NAMES[lightIdx], Vector3D(1.0f, 1.0f, 1.0f)); setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_NAMES[lightIdx], 0.5f); // There is no risk in doing that even if multithreaded // since we are sure that a shaderData is unique for a given light // and won't ever be referenced as a Component either - QMatrix4x4 *worldTransform = lightEntity->worldTransform(); + Matrix4x4 *worldTransform = lightEntity->worldTransform(); if (worldTransform) shaderData->updateWorldTransform(*worldTransform); @@ -1046,9 +1047,9 @@ void RenderView::setShaderAndUniforms(RenderCommand *command, // If no active light sources and no environment light, add a default light if (activeLightSources.isEmpty() && !environmentLight) { // Note: implicit conversion of values to UniformValue - setUniformValue(command->m_parameterPack, LIGHT_POSITION_NAMES[0], QVector3D(10.0f, 10.0f, 0.0f)); + setUniformValue(command->m_parameterPack, LIGHT_POSITION_NAMES[0], Vector3D(10.0f, 10.0f, 0.0f)); setUniformValue(command->m_parameterPack, LIGHT_TYPE_NAMES[0], int(QAbstractLight::PointLight)); - setUniformValue(command->m_parameterPack, LIGHT_COLOR_NAMES[0], QVector3D(1.0f, 1.0f, 1.0f)); + setUniformValue(command->m_parameterPack, LIGHT_COLOR_NAMES[0], Vector3D(1.0f, 1.0f, 1.0f)); setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_NAMES[0], 0.5f); } diff --git a/src/render/backend/renderview_p.h b/src/render/backend/renderview_p.h index b684cbb85..cb3c74917 100644 --- a/src/render/backend/renderview_p.h +++ b/src/render/backend/renderview_p.h @@ -67,6 +67,7 @@ #include <Qt3DRender/private/qblitframebuffer_p.h> #include <Qt3DCore/private/qframeallocator_p.h> +#include <Qt3DRender/private/aligned_malloc_p.h> // TODO: Move out once this is all refactored #include <Qt3DRender/private/renderviewjobutils_p.h> @@ -98,14 +99,14 @@ typedef QPair<QString, ActivePropertyContent > ActiveProperty; struct Q_AUTOTEST_EXPORT Plane { - explicit Plane(const QVector4D &planeEquation) + explicit Plane(const Vector4D &planeEquation) : planeEquation(planeEquation) - , normal(planeEquation.toVector3D().normalized()) - , d(planeEquation.w() / planeEquation.toVector3D().length()) + , normal(Vector3D(planeEquation).normalized()) + , d(planeEquation.w() / Vector3D(planeEquation).length()) {} - const QVector4D planeEquation; - const QVector3D normal; + const Vector4D planeEquation; + const Vector3D normal; const float d; }; @@ -136,6 +137,8 @@ public: RenderView(); ~RenderView(); + QT3D_ALIGNED_MALLOC_AND_FREE() + // TODO: Add a way to specify a sort predicate for the RenderCommands void sort(); @@ -153,17 +156,17 @@ public: inline void setRenderCameraEntity(Entity *renderCameraNode) Q_DECL_NOTHROW { m_data.m_renderCameraNode = renderCameraNode; } inline Entity *renderCameraEntity() const Q_DECL_NOTHROW { return m_data.m_renderCameraNode; } - inline void setViewMatrix(const QMatrix4x4 &viewMatrix) Q_DECL_NOTHROW { m_data.m_viewMatrix = viewMatrix; } - inline QMatrix4x4 viewMatrix() const Q_DECL_NOTHROW { return m_data.m_viewMatrix; } + inline void setViewMatrix(const Matrix4x4 &viewMatrix) Q_DECL_NOTHROW { m_data.m_viewMatrix = viewMatrix; } + inline Matrix4x4 viewMatrix() const Q_DECL_NOTHROW { return m_data.m_viewMatrix; } - inline void setViewProjectionMatrix(const QMatrix4x4 &viewProjectionMatrix) Q_DECL_NOTHROW { m_data.m_viewProjectionMatrix = viewProjectionMatrix; } - inline QMatrix4x4 viewProjectionMatrix() const Q_DECL_NOTHROW { return m_data.m_viewProjectionMatrix; } + inline void setViewProjectionMatrix(const Matrix4x4 &viewProjectionMatrix) Q_DECL_NOTHROW { m_data.m_viewProjectionMatrix = viewProjectionMatrix; } + inline Matrix4x4 viewProjectionMatrix() const Q_DECL_NOTHROW { return m_data.m_viewProjectionMatrix; } - inline void setEyePosition(const QVector3D &eyePos) Q_DECL_NOTHROW { m_data.m_eyePos = eyePos; } - inline QVector3D eyePosition() const Q_DECL_NOTHROW { return m_data.m_eyePos; } + inline void setEyePosition(const Vector3D &eyePos) Q_DECL_NOTHROW { m_data.m_eyePos = eyePos; } + inline Vector3D eyePosition() const Q_DECL_NOTHROW { return m_data.m_eyePos; } - inline void setEyeViewDirection(const QVector3D &dir) Q_DECL_NOTHROW { m_data.m_eyeViewDir = dir; } - inline QVector3D eyeViewDirection() const Q_DECL_NOTHROW { return m_data.m_eyeViewDir; } + inline void setEyeViewDirection(const Vector3D &dir) Q_DECL_NOTHROW { m_data.m_eyeViewDir = dir; } + inline Vector3D eyeViewDirection() const Q_DECL_NOTHROW { return m_data.m_eyeViewDir; } inline void appendLayerFilter(const Qt3DCore::QNodeId layerFilterId) Q_DECL_NOTHROW { m_data.m_layerFilterIds.push_back(layerFilterId); } inline Qt3DCore::QNodeIdVector layerFilters() const Q_DECL_NOTHROW { return m_data.m_layerFilterIds; } @@ -260,12 +263,12 @@ public: Entity *m_renderCameraNode; const TechniqueFilter *m_techniqueFilter; const RenderPassFilter *m_passFilter; - QMatrix4x4 m_viewMatrix; - QMatrix4x4 m_viewProjectionMatrix; + Matrix4x4 m_viewMatrix; + Matrix4x4 m_viewProjectionMatrix; Qt3DCore::QNodeIdVector m_layerFilterIds; QVector<Qt3DRender::QSortPolicy::SortType> m_sortingTypes; - QVector3D m_eyePos; - QVector3D m_eyeViewDir; + Vector3D m_eyePos; + Vector3D m_eyeViewDir; Qt3DCore::QNodeIdVector m_proximityFilterIds; }; @@ -285,7 +288,6 @@ private: Entity *entity, const QVector<LightSource> &activeLightSources, EnvironmentLight *environmentLight) const; - mutable QThreadStorage<UniformBlockValueBuilder*> m_localData; Qt3DCore::QNodeId m_renderCaptureNodeId; @@ -360,14 +362,14 @@ private: UniformValue standardUniformValue(StandardUniform standardUniformType, Entity *entity, - const QMatrix4x4 &model) const; + const Matrix4x4 &model) const; void setUniformValue(ShaderParameterPack &uniformPack, int nameId, const UniformValue &value) const; void setStandardUniformValue(ShaderParameterPack &uniformPack, int glslNameId, int nameId, Entity *entity, - const QMatrix4x4 &worldTransform) const; + const Matrix4x4 &worldTransform) const; void setUniformBlockValue(ShaderParameterPack &uniformPack, Shader *shader, const ShaderUniformBlock &block, diff --git a/src/render/backend/renderviewbuilder.cpp b/src/render/backend/renderviewbuilder.cpp index 0682018fc..495b666f5 100644 --- a/src/render/backend/renderviewbuilder.cpp +++ b/src/render/backend/renderviewbuilder.cpp @@ -39,6 +39,8 @@ #include "renderviewbuilder_p.h" +#include <Qt3DRender/private/renderbarrierjob_p.h> + #include <QThread> QT_BEGIN_NAMESPACE @@ -81,9 +83,6 @@ public: // Sort the commands rv->sort(); - - // Enqueue our fully populated RenderView with the RenderThread - m_renderer->enqueueRenderView(rv, m_renderViewJob->submitOrderIndex()); } private: @@ -125,13 +124,15 @@ public: const FilterLayerEntityJobPtr &filterEntityByLayerJob, const FilterProximityDistanceJobPtr &filterProximityJob, const QVector<MaterialParameterGathererJobPtr> &materialGathererJobs, - const QVector<RenderViewBuilderJobPtr> &renderViewBuilderJobs) + const QVector<RenderViewBuilderJobPtr> &renderViewBuilderJobs, + Renderer *renderer) : m_renderViewJob(renderViewJob) , m_frustumCullingJob(frustumCullingJob) , m_filterEntityByLayerJob(filterEntityByLayerJob) , m_filterProximityJob(filterProximityJob) , m_materialGathererJobs(materialGathererJobs) , m_renderViewBuilderJobs(renderViewBuilderJobs) + , m_renderer(renderer) {} void operator()() @@ -157,6 +158,9 @@ public: // Set whether frustum culling is enabled or not m_frustumCullingJob->setActive(rv->frustumCulling()); + + // Enqueue RenderView with the renderer + m_renderer->enqueueRenderView(rv, m_renderViewJob->submitOrderIndex()); } private: @@ -166,6 +170,7 @@ private: FilterProximityDistanceJobPtr m_filterProximityJob; QVector<MaterialParameterGathererJobPtr> m_materialGathererJobs; QVector<RenderViewBuilderJobPtr> m_renderViewBuilderJobs; + Renderer *m_renderer; }; class SyncRenderCommandBuilding @@ -355,7 +360,7 @@ RenderViewBuilder::RenderViewBuilder(Render::FrameGraphNode *leafNode, int rende , m_lightGathererJob(Render::LightGathererPtr::create()) , m_renderableEntityFilterJob(RenderableEntityFilterPtr::create()) , m_computableEntityFilterJob(ComputableEntityFilterPtr::create()) - , m_frustumCullingJob(Render::FrustumCullingJobPtr::create()) + , m_frustumCullingJob(new Render::FrustumCullingJob()) , m_syncFrustumCullingJob(SynchronizerJobPtr::create(SyncFrustumCulling(m_renderViewJob, m_frustumCullingJob), JobTypes::SyncFrustumCulling)) , m_setClearDrawBufferIndexJob(SynchronizerJobPtr::create(SetClearDrawBufferIndex(m_renderViewJob), JobTypes::ClearBufferDrawIndex)) , m_syncFilterEntityByLayerJob() @@ -519,7 +524,8 @@ void RenderViewBuilder::prepareJobs() m_filterEntityByLayerJob, m_filterProximityJob, m_materialGathererJobs, - m_renderViewBuilderJobs), + m_renderViewBuilderJobs, + m_renderer), JobTypes::SyncRenderViewInitialization); } @@ -545,11 +551,13 @@ QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const m_setClearDrawBufferIndexJob->addDependency(m_syncRenderViewInitializationJob); + m_renderer->readRenderQueueSizeBarrierJob()->addDependency(m_syncRenderViewInitializationJob); m_syncRenderViewInitializationJob->addDependency(m_renderViewJob); m_filterProximityJob->addDependency(m_renderer->expandBoundingVolumeJob()); m_filterProximityJob->addDependency(m_syncRenderViewInitializationJob); + m_syncRenderCommandBuildingJob->addDependency(m_renderer->updateGLResourcesBarrierJob()); m_syncRenderCommandBuildingJob->addDependency(m_syncRenderViewInitializationJob); m_syncRenderCommandBuildingJob->addDependency(m_renderableEntityFilterJob); m_syncRenderCommandBuildingJob->addDependency(m_computableEntityFilterJob); @@ -558,10 +566,15 @@ QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const m_syncRenderCommandBuildingJob->addDependency(m_frustumCullingJob); for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs)) { + renderViewCommandBuilder->addDependency(m_renderer->updateSkinningPaletteJob()); + renderViewCommandBuilder->addDependency(m_renderer->updateWorldBoundingVolumeJob()); + renderViewCommandBuilder->addDependency(m_renderer->updateShaderDataTransformJob()); renderViewCommandBuilder->addDependency(m_syncRenderCommandBuildingJob); + m_syncRenderViewCommandBuildersJob->addDependency(renderViewCommandBuilder); } + m_renderer->prepareCommandSubmissionBarrierJob()->addDependency(m_syncRenderViewCommandBuildersJob); m_renderer->frameCleanupJob()->addDependency(m_syncRenderViewCommandBuildersJob); m_renderer->frameCleanupJob()->addDependency(m_setClearDrawBufferIndexJob); diff --git a/src/render/backend/segmentsvisitor.cpp b/src/render/backend/segmentsvisitor.cpp index 96e2b3b6c..a3a5d059c 100644 --- a/src/render/backend/segmentsvisitor.cpp +++ b/src/render/backend/segmentsvisitor.cpp @@ -86,7 +86,7 @@ void traverseSegmentsIndexed(Index *indices, const uint maxVerticesDataSize = qMin(vertexInfo.dataSize, 3U); uint ndx[2]; - QVector3D abc[2]; + Vector3D abc[2]; while (i < indexInfo.count) { for (uint u = 0; u < 2; ++u) { ndx[u] = indices[i + u]; @@ -112,7 +112,7 @@ void traverseSegments(Vertex *vertices, const uint maxVerticesDataSize = qMin(vertexInfo.dataSize, 3U); uint ndx[2]; - QVector3D abc[2]; + Vector3D abc[2]; while (i < vertexInfo.count) { for (uint u = 0; u < 2; ++u) { ndx[u] = (i + u); @@ -139,7 +139,7 @@ void traverseSegmentStripIndexed(Index *indices, const uint maxVerticesDataSize = qMin(vertexInfo.dataSize, 3U); uint ndx[2]; - QVector3D abc[2]; + Vector3D abc[2]; ndx[0] = indices[0]; uint idx = ndx[0] * verticesStride; for (uint j = 0; j < maxVerticesDataSize; ++j) @@ -180,7 +180,7 @@ void traverseSegmentStrip(Vertex *vertices, const uint maxVerticesDataSize = qMin(vertexInfo.dataSize, 3U); uint ndx[2]; - QVector3D abc[2]; + Vector3D abc[2]; ndx[0] = i; uint idx = ndx[0] * verticesStride; for (uint j = 0; j < maxVerticesDataSize; ++j) @@ -218,7 +218,7 @@ void traverseSegmentAdjacencyIndexed(Index *indices, const uint maxVerticesDataSize = qMin(vertexInfo.dataSize, 3U); uint ndx[2]; - QVector3D abc[2]; + Vector3D abc[2]; while (i < n) { for (uint u = 0; u < 2; ++u) { ndx[u] = indices[i + u]; @@ -245,7 +245,7 @@ void traverseSegmentAdjacency(Vertex *vertices, const uint maxVerticesDataSize = qMin(vertexInfo.dataSize, 3U); uint ndx[2]; - QVector3D abc[2]; + Vector3D abc[2]; while (i < n) { for (uint u = 0; u < 2; ++u) { ndx[u] = (i + u); diff --git a/src/render/backend/segmentsvisitor_p.h b/src/render/backend/segmentsvisitor_p.h index 21867b0d5..cd5df1268 100644 --- a/src/render/backend/segmentsvisitor_p.h +++ b/src/render/backend/segmentsvisitor_p.h @@ -52,6 +52,7 @@ // #include <Qt3DCore/qnodeid.h> +#include <Qt3DCore/private/vector3d_p.h> QT_BEGIN_NAMESPACE @@ -75,8 +76,8 @@ public: void apply(const Qt3DCore::QEntity *entity); void apply(const GeometryRenderer *renderer, const Qt3DCore::QNodeId id); - virtual void visit(uint andx, const QVector3D &a, - uint bndx, const QVector3D &b) = 0; + virtual void visit(uint andx, const Vector3D &a, + uint bndx, const Vector3D &b) = 0; protected: NodeManagers *m_manager; diff --git a/src/render/backend/shaderparameterpack.cpp b/src/render/backend/shaderparameterpack.cpp index 01a977aee..f78e45a5e 100644 --- a/src/render/backend/shaderparameterpack.cpp +++ b/src/render/backend/shaderparameterpack.cpp @@ -65,17 +65,17 @@ void ShaderParameterPack::setUniform(const int glslNameId, const UniformValue &v m_uniforms.insert(glslNameId, val); } -void ShaderParameterPack::setTexture(const int glslNameId, Qt3DCore::QNodeId texId) +void ShaderParameterPack::setTexture(const int glslNameId, int uniformArrayIndex, Qt3DCore::QNodeId texId) { for (int t=0; t<m_textures.size(); ++t) { - if (m_textures[t].glslNameId != glslNameId) + if (m_textures[t].glslNameId != glslNameId || m_textures[t].uniformArrayIndex != uniformArrayIndex) continue; m_textures[t].texId = texId; return; } - m_textures.append(NamedTexture(glslNameId, texId)); + m_textures.append(NamedTexture(glslNameId, texId, uniformArrayIndex)); } // Contains Uniform Block Index and QNodeId of the ShaderData (UBO) diff --git a/src/render/backend/shaderparameterpack_p.h b/src/render/backend/shaderparameterpack_p.h index c0ab05e57..abd63a187 100644 --- a/src/render/backend/shaderparameterpack_p.h +++ b/src/render/backend/shaderparameterpack_p.h @@ -96,7 +96,7 @@ public: ~ShaderParameterPack(); void setUniform(const int glslNameId, const UniformValue &val); - void setTexture(const int glslNameId, Qt3DCore::QNodeId id); + void setTexture(const int glslNameId, int uniformArrayIndex, Qt3DCore::QNodeId id); void setUniformBuffer(BlockToUBO blockToUBO); void setShaderStorageBuffer(BlockToSSBO blockToSSBO); void setSubmissionUniform(const ShaderUniform &uniform); @@ -108,13 +108,15 @@ public: struct NamedTexture { NamedTexture() {} - NamedTexture(const int nm, Qt3DCore::QNodeId t) - : glslNameId(nm) - , texId(t) + NamedTexture(const int glslNameId, Qt3DCore::QNodeId texId, int uniformArrayIndex) + : glslNameId(glslNameId) + , texId(texId) + , uniformArrayIndex(uniformArrayIndex) { } int glslNameId; Qt3DCore::QNodeId texId; + int uniformArrayIndex; }; inline QVector<NamedTexture> textures() const { return m_textures; } diff --git a/src/render/backend/transform.cpp b/src/render/backend/transform.cpp index 636c2d103..20574d6f7 100644 --- a/src/render/backend/transform.cpp +++ b/src/render/backend/transform.cpp @@ -64,7 +64,7 @@ void Transform::cleanup() m_rotation = QQuaternion(); m_scale = QVector3D(); m_translation = QVector3D(); - m_transformMatrix = QMatrix4x4(); + m_transformMatrix = Matrix4x4(); QBackendNode::setEnabled(false); } @@ -78,7 +78,7 @@ void Transform::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &ch updateMatrix(); } -QMatrix4x4 Transform::transformMatrix() const +Matrix4x4 Transform::transformMatrix() const { return m_transformMatrix; } @@ -125,7 +125,7 @@ void Transform::updateMatrix() m.translate(m_translation); m.rotate(m_rotation); m.scale(m_scale); - m_transformMatrix = m; + m_transformMatrix = Matrix4x4(m); } } // namespace Render diff --git a/src/render/backend/transform_p.h b/src/render/backend/transform_p.h index ce026da9d..8e3e9d639 100644 --- a/src/render/backend/transform_p.h +++ b/src/render/backend/transform_p.h @@ -54,7 +54,7 @@ #include <Qt3DRender/private/backendnode_p.h> #include <QtGui/qquaternion.h> #include <QtGui/qvector3d.h> -#include <QMatrix4x4> +#include <Qt3DCore/private/matrix4x4_p.h> QT_BEGIN_NAMESPACE @@ -71,7 +71,7 @@ public: Transform(); void cleanup(); - QMatrix4x4 transformMatrix() const; + Matrix4x4 transformMatrix() const; QVector3D scale() const; QQuaternion rotation() const; QVector3D translation() const; @@ -83,7 +83,7 @@ public: private: void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - QMatrix4x4 m_transformMatrix; + Matrix4x4 m_transformMatrix; QQuaternion m_rotation; QVector3D m_scale; QVector3D m_translation; diff --git a/src/render/backend/triangleboundingvolume.cpp b/src/render/backend/triangleboundingvolume.cpp index ca2d26897..be5206657 100644 --- a/src/render/backend/triangleboundingvolume.cpp +++ b/src/render/backend/triangleboundingvolume.cpp @@ -49,35 +49,35 @@ namespace Render { // Note: a, b, c in clockwise order // RealTime Collision Detection page 192 bool intersectsSegmentTriangle(const RayCasting::QRay3D &ray, - const QVector3D &a, - const QVector3D &b, - const QVector3D &c, - QVector3D &uvw, + const Vector3D &a, + const Vector3D &b, + const Vector3D &c, + Vector3D &uvw, float &t) { - const QVector3D ab = b - a; - const QVector3D ac = c - a; - const QVector3D qp = (ray.origin() - ray.point(ray.distance())); + const Vector3D ab = b - a; + const Vector3D ac = c - a; + const Vector3D qp = (ray.origin() - ray.point(ray.distance())); - const QVector3D n = QVector3D::crossProduct(ab, ac); - const float d = QVector3D::dotProduct(qp, n); + const Vector3D n = Vector3D::crossProduct(ab, ac); + const float d = Vector3D::dotProduct(qp, n); if (d <= 0.0f) return false; - const QVector3D ap = ray.origin() - a; - t = QVector3D::dotProduct(ap, n); + const Vector3D ap = ray.origin() - a; + t = Vector3D::dotProduct(ap, n); if (t < 0.0f || t > d) return false; - const QVector3D e = QVector3D::crossProduct(qp, ap); - uvw.setY(QVector3D::dotProduct(ac, e)); + const Vector3D e = Vector3D::crossProduct(qp, ap); + uvw.setY(Vector3D::dotProduct(ac, e)); if (uvw.y() < 0.0f || uvw.y() > d) return false; - uvw.setZ(-QVector3D::dotProduct(ab, e)); + uvw.setZ(-Vector3D::dotProduct(ab, e)); if (uvw.z() < 0.0f || uvw.y() + uvw.z() > d) return false; @@ -99,7 +99,7 @@ TriangleBoundingVolume::TriangleBoundingVolume() /*! The vertices a, b, c are assumed to be in counter clockwise order. */ -TriangleBoundingVolume::TriangleBoundingVolume(Qt3DCore::QNodeId id, const QVector3D &a, const QVector3D &b, const QVector3D &c) +TriangleBoundingVolume::TriangleBoundingVolume(Qt3DCore::QNodeId id, const Vector3D &a, const Vector3D &b, const Vector3D &c) : QBoundingVolume() , m_id(id) , m_a(a) @@ -112,10 +112,10 @@ Qt3DCore::QNodeId TriangleBoundingVolume::id() const return m_id; } -bool TriangleBoundingVolume::intersects(const RayCasting::QRay3D &ray, QVector3D *q, QVector3D *uvw) const +bool TriangleBoundingVolume::intersects(const RayCasting::QRay3D &ray, Vector3D *q, Vector3D *uvw) const { float t = 0.0f; - QVector3D uvwr; + Vector3D uvwr; const float intersected = intersectsSegmentTriangle(ray, m_c, m_b, m_a, uvwr, t); if (intersected) { @@ -132,41 +132,41 @@ TriangleBoundingVolume::Type TriangleBoundingVolume::type() const return RayCasting::QBoundingVolume::Triangle; } -QVector3D TriangleBoundingVolume::a() const +Vector3D TriangleBoundingVolume::a() const { return m_a; } -QVector3D TriangleBoundingVolume::b() const +Vector3D TriangleBoundingVolume::b() const { return m_b; } -QVector3D TriangleBoundingVolume::c() const +Vector3D TriangleBoundingVolume::c() const { return m_c; } -void TriangleBoundingVolume::setA(const QVector3D &a) +void TriangleBoundingVolume::setA(const Vector3D &a) { m_a = a; } -void TriangleBoundingVolume::setB(const QVector3D &b) +void TriangleBoundingVolume::setB(const Vector3D &b) { m_b = b; } -void TriangleBoundingVolume::setC(const QVector3D &c) +void TriangleBoundingVolume::setC(const Vector3D &c) { m_c = c; } -TriangleBoundingVolume TriangleBoundingVolume::transformed(const QMatrix4x4 &mat) const +TriangleBoundingVolume TriangleBoundingVolume::transformed(const Matrix4x4 &mat) const { - const QVector3D tA = mat * m_a; - const QVector3D tB = mat * m_b; - const QVector3D tC = mat * m_c; + const Vector3D tA = mat * m_a; + const Vector3D tB = mat * m_b; + const Vector3D tC = mat * m_c; return TriangleBoundingVolume(id(), tA, tB, tC); } diff --git a/src/render/backend/triangleboundingvolume_p.h b/src/render/backend/triangleboundingvolume_p.h index 4735a1522..a45a5ed7c 100644 --- a/src/render/backend/triangleboundingvolume_p.h +++ b/src/render/backend/triangleboundingvolume_p.h @@ -53,6 +53,7 @@ #include <Qt3DRender/private/qboundingvolume_p.h> #include <Qt3DCore/qnodeid.h> +#include <Qt3DCore/private/matrix4x4_p.h> #include <QVector3D> QT_BEGIN_NAMESPACE @@ -62,10 +63,10 @@ namespace Qt3DRender { namespace Render { Q_AUTOTEST_EXPORT bool intersectsSegmentTriangle(const RayCasting::QRay3D &ray, - const QVector3D &a, - const QVector3D &b, - const QVector3D &c, - QVector3D &uvw, + const Vector3D &a, + const Vector3D &b, + const Vector3D &c, + Vector3D &uvw, float &t); class Q_AUTOTEST_EXPORT TriangleBoundingVolume : public RayCasting::QBoundingVolume @@ -73,25 +74,25 @@ class Q_AUTOTEST_EXPORT TriangleBoundingVolume : public RayCasting::QBoundingVol public: TriangleBoundingVolume(); explicit TriangleBoundingVolume(Qt3DCore::QNodeId id, - const QVector3D &a, - const QVector3D &b, - const QVector3D &c); + const Vector3D &a, + const Vector3D &b, + const Vector3D &c); Qt3DCore::QNodeId id() const final; - bool intersects(const RayCasting::QRay3D &ray, QVector3D *q, QVector3D *uvw) const final; - Type type() const final; + bool intersects(const RayCasting::QRay3D &ray, Vector3D *q, Vector3D *uvw) const final; + Type type() const final; - QVector3D a() const; - QVector3D b() const; - QVector3D c() const; + Vector3D a() const; + Vector3D b() const; + Vector3D c() const; - void setA(const QVector3D &a); - void setB(const QVector3D &b); - void setC(const QVector3D &c); + void setA(const Vector3D &a); + void setB(const Vector3D &b); + void setC(const Vector3D &c); - TriangleBoundingVolume transformed(const QMatrix4x4 &mat) const; + TriangleBoundingVolume transformed(const Matrix4x4 &mat) const; - inline TriangleBoundingVolume &transform(const QMatrix4x4 &mat) + inline TriangleBoundingVolume &transform(const Matrix4x4 &mat) { *this = transformed(mat); return *this; @@ -99,7 +100,7 @@ public: private: Qt3DCore::QNodeId m_id; - QVector3D m_a, m_b, m_c; + Vector3D m_a, m_b, m_c; }; } // namespace Render diff --git a/src/render/backend/trianglesextractor.cpp b/src/render/backend/trianglesextractor.cpp index e7a36dab3..2ddb425a0 100644 --- a/src/render/backend/trianglesextractor.cpp +++ b/src/render/backend/trianglesextractor.cpp @@ -68,7 +68,7 @@ QVector<RayCasting::QBoundingVolume *> TrianglesExtractor::extract(const Qt3DCor return m_volumes; } -void TrianglesExtractor::visit(uint andx, const QVector3D &a, uint bndx, const QVector3D &b, uint cndx, const QVector3D &c) +void TrianglesExtractor::visit(uint andx, const Vector3D &a, uint bndx, const Vector3D &b, uint cndx, const Vector3D &c) { Q_UNUSED(andx); Q_UNUSED(bndx); Q_UNUSED(cndx); m_volumes.push_back(new TriangleBoundingVolume(m_nodeId, a, b, c)); diff --git a/src/render/backend/trianglesextractor_p.h b/src/render/backend/trianglesextractor_p.h index 857c4c638..df4c20466 100644 --- a/src/render/backend/trianglesextractor_p.h +++ b/src/render/backend/trianglesextractor_p.h @@ -71,9 +71,9 @@ public: QVector<RayCasting::QBoundingVolume *> extract(const Qt3DCore::QNodeId id); private: - void visit(uint andx, const QVector3D &a, - uint bndx, const QVector3D &b, - uint cndx, const QVector3D &c) override; + void visit(uint andx, const Vector3D &a, + uint bndx, const Vector3D &b, + uint cndx, const Vector3D &c) override; GeometryRenderer *m_renderer; QVector<RayCasting::QBoundingVolume *> m_volumes; diff --git a/src/render/backend/trianglesvisitor.cpp b/src/render/backend/trianglesvisitor.cpp index 57538c8d7..87ba7bde9 100644 --- a/src/render/backend/trianglesvisitor.cpp +++ b/src/render/backend/trianglesvisitor.cpp @@ -85,11 +85,11 @@ void traverseTrianglesIndexed(index *indices, TrianglesVisitor* visitor) { uint i = 0; - const uint verticesStride = vertexInfo.byteStride / sizeof(vertex); const uint maxVerticesDataSize = qMin(vertexInfo.dataSize, 3U); + const uint verticesStride = vertexInfo.byteStride ? vertexInfo.byteStride / sizeof(vertex) : maxVerticesDataSize; uint ndx[3]; - QVector3D abc[3]; + Vector3D abc[3]; while (i < indexInfo.count) { for (uint u = 0; u < 3; ++u) { ndx[u] = indices[i + u]; @@ -111,11 +111,11 @@ void traverseTriangles(vertex *vertices, { uint i = 0; - const uint verticesStride = vertexInfo.byteStride / sizeof(vertex); const uint maxVerticesDataSize = qMin(vertexInfo.dataSize, 3U); + const uint verticesStride = vertexInfo.byteStride ? vertexInfo.byteStride / sizeof(vertex) : maxVerticesDataSize; uint ndx[3]; - QVector3D abc[3]; + Vector3D abc[3]; while (i < vertexInfo.count) { for (uint u = 0; u < 3; ++u) { ndx[u] = (i + u); @@ -147,11 +147,11 @@ void traverseTriangleStripIndexed(index *indices, TrianglesVisitor* visitor) { uint i = 0; - const uint verticesStride = vertexInfo.byteStride / sizeof(vertex); const uint maxVerticesDataSize = qMin(vertexInfo.dataSize, 3U); + const uint verticesStride = vertexInfo.byteStride ? vertexInfo.byteStride / sizeof(vertex) : maxVerticesDataSize; uint ndx[3]; - QVector3D abc[3]; + Vector3D abc[3]; while (i < indexInfo.count - 2) { bool degenerate = false; for (uint u = 0; u < 3; ++u) { @@ -178,11 +178,11 @@ void traverseTriangleStrip(vertex *vertices, { uint i = 0; - const uint verticesStride = vertexInfo.byteStride / sizeof(vertex); const uint maxVerticesDataSize = qMin(vertexInfo.dataSize, 3U); + const uint verticesStride = vertexInfo.byteStride ? vertexInfo.byteStride / sizeof(vertex) : maxVerticesDataSize; uint ndx[3]; - QVector3D abc[3]; + Vector3D abc[3]; while (i < vertexInfo.count - 2) { for (uint u = 0; u < 3; ++u) { ndx[u] = (i + u); @@ -204,11 +204,11 @@ void traverseTriangleFanIndexed(index *indices, const BufferInfo &vertexInfo, TrianglesVisitor* visitor) { - const uint verticesStride = vertexInfo.byteStride / sizeof(vertex); const uint maxVerticesDataSize = qMin(vertexInfo.dataSize, 3U); + const uint verticesStride = vertexInfo.byteStride ? vertexInfo.byteStride / sizeof(vertex) : maxVerticesDataSize; uint ndx[3]; - QVector3D abc[3]; + Vector3D abc[3]; for (uint j = 0; j < maxVerticesDataSize; ++j) { abc[0][j] = vertices[static_cast<int>(indices[0]) * verticesStride + j]; @@ -234,11 +234,11 @@ void traverseTriangleFan(vertex *vertices, const BufferInfo &vertexInfo, TrianglesVisitor* visitor) { - const uint verticesStride = vertexInfo.byteStride / sizeof(vertex); const uint maxVerticesDataSize = qMin(vertexInfo.dataSize, 3U); + const uint verticesStride = vertexInfo.byteStride ? vertexInfo.byteStride / sizeof(vertex) : maxVerticesDataSize; uint ndx[3]; - QVector3D abc[3]; + Vector3D abc[3]; for (uint j = 0; j < maxVerticesDataSize; ++j) { abc[0][j] = vertices[j]; @@ -268,11 +268,11 @@ void traverseTriangleAdjacencyIndexed(index *indices, TrianglesVisitor* visitor) { uint i = 0; - const uint verticesStride = vertexInfo.byteStride / sizeof(vertex); const uint maxVerticesDataSize = qMin(vertexInfo.dataSize, 3U); + const uint verticesStride = vertexInfo.byteStride ? vertexInfo.byteStride / sizeof(vertex) : maxVerticesDataSize; uint ndx[3]; - QVector3D abc[3]; + Vector3D abc[3]; while (i < indexInfo.count) { for (uint u = 0; u < 6; u += 2) { ndx[u / 2] = indices[i + u]; @@ -294,11 +294,11 @@ void traverseTriangleAdjacency(Vertex *vertices, { uint i = 0; - const uint verticesStride = vertexInfo.byteStride / sizeof(Vertex); const uint maxVerticesDataSize = qMin(vertexInfo.dataSize, 3U); + const uint verticesStride = vertexInfo.byteStride ? vertexInfo.byteStride / sizeof(Vertex) : maxVerticesDataSize; uint ndx[3]; - QVector3D abc[3]; + Vector3D abc[3]; while (i < vertexInfo.count) { for (uint u = 0; u < 6; u += 2) { ndx[u / 2] = (i + u); @@ -313,10 +313,10 @@ void traverseTriangleAdjacency(Vertex *vertices, } template<typename Coordinate> -QVector4D readCoordinate(const BufferInfo &info, Coordinate *coordinates, uint index) +Vector4D readCoordinate(const BufferInfo &info, Coordinate *coordinates, uint index) { - const uint stride = info.byteStride / sizeof(Coordinate); - QVector4D ret(0, 0, 0, 1.0f); + const uint stride = info.byteStride ? info.byteStride / sizeof(Coordinate) : info.dataSize; + Vector4D ret(0, 0, 0, 1.0f); coordinates += stride * index; for (uint e = 0; e < info.dataSize; ++e) ret[e] = coordinates[e]; @@ -340,7 +340,7 @@ typename EnumToType<v>::type *castToType(const QByteArray &u, uint byteOffset) return reinterpret_cast< typename EnumToType<v>::type *>(u.constData() + byteOffset); } -QVector4D readBuffer(const BufferInfo &info, uint index) +Vector4D readBuffer(const BufferInfo &info, uint index) { switch (info.type) { case QAttribute::Byte: @@ -362,7 +362,7 @@ QVector4D readBuffer(const BufferInfo &info, uint index) default: break; } - return QVector4D(); + return Vector4D(); } template<typename Index, typename Visitor> @@ -509,7 +509,7 @@ bool CoordinateReader::setGeometry(const GeometryRenderer *renderer, const QStri return true; } -QVector4D CoordinateReader::getCoordinate(uint vertexIndex) +Vector4D CoordinateReader::getCoordinate(uint vertexIndex) { return readBuffer(m_bufferInfo, vertexIndex); } diff --git a/src/render/backend/trianglesvisitor_p.h b/src/render/backend/trianglesvisitor_p.h index 9428857ac..ee206f1c9 100644 --- a/src/render/backend/trianglesvisitor_p.h +++ b/src/render/backend/trianglesvisitor_p.h @@ -54,6 +54,8 @@ #include <Qt3DCore/qnodeid.h> #include <Qt3DRender/QAttribute> #include <Qt3DRender/private/bufferutils_p.h> +#include <Qt3DCore/private/vector3d_p.h> +#include <Qt3DCore/private/vector4d_p.h> #include <private/qt3drender_global_p.h> @@ -81,9 +83,9 @@ public: void apply(const Qt3DCore::QEntity *entity); void apply(const GeometryRenderer *renderer, const Qt3DCore::QNodeId id); - virtual void visit(uint andx, const QVector3D &a, - uint bndx, const QVector3D &b, - uint cndx, const QVector3D &c) = 0; + virtual void visit(uint andx, const Vector3D &a, + uint bndx, const Vector3D &b, + uint cndx, const Vector3D &c) = 0; protected: NodeManagers *m_manager; @@ -102,7 +104,7 @@ public: bool setGeometry(const GeometryRenderer *renderer, const QString &attributeName); - QVector4D getCoordinate(uint vertexIndex); + Vector4D getCoordinate(uint vertexIndex); protected: NodeManagers *m_manager; diff --git a/src/render/backend/uniform.cpp b/src/render/backend/uniform.cpp index 03220a219..41ee24967 100644 --- a/src/render/backend/uniform.cpp +++ b/src/render/backend/uniform.cpp @@ -47,10 +47,22 @@ namespace Render { namespace { const int qNodeIdTypeId = qMetaTypeId<Qt3DCore::QNodeId>(); +const int qVector3DTypeId = qMetaTypeId<Vector3D>(); +const int qVector4DTypeId = qMetaTypeId<Vector4D>(); +const int qMatrix4x4TypeId = qMetaTypeId<Matrix4x4>(); // glUniform*fv/glUniform*iv/glUniform*uiv -> only handles sizeof(float)/sizeof(int) int byteSizeForMetaType(int type) { + if (type == qMatrix4x4TypeId) + return sizeof(Matrix4x4); + if (type == qVector3DTypeId) + return sizeof(Vector3D); + if (type == qVector4DTypeId) + return sizeof(Vector4D); + if (type == qNodeIdTypeId) + return sizeof(Qt3DCore::QNodeId); + switch (type) { case QMetaType::Bool: case QMetaType::Int: @@ -88,9 +100,9 @@ int byteSizeForMetaType(int type) case QMetaType::QVector4D: case QMetaType::QColor: return 4 * sizeof(float); - case QMetaType::QMatrix4x4: return 16 * sizeof(float); + default: Q_UNREACHABLE(); return -1; @@ -102,11 +114,22 @@ int byteSizeForMetaType(int type) UniformValue UniformValue::fromVariant(const QVariant &variant) { // Texture/Buffer case - if (variant.userType() == qNodeIdTypeId) + const int type = variant.userType(); + + if (type == qNodeIdTypeId) return UniformValue(variant.value<Qt3DCore::QNodeId>()); + if (type == qMatrix4x4TypeId) + return UniformValue(variant.value<Matrix4x4>()); + + if (type == qVector3DTypeId) + return UniformValue(variant.value<Vector3D>()); + + if (type == qVector4DTypeId) + return UniformValue(variant.value<Vector4D>()); + UniformValue v; - switch (variant.userType()) { + switch (type) { case QMetaType::Bool: v.data<bool>()[0] = variant.toBool(); break; @@ -209,6 +232,11 @@ UniformValue UniformValue::fromVariant(const QVariant &variant) break; const int listEntryType = variants.first().userType(); + + // array of textures + if (listEntryType == qNodeIdTypeId) + v.m_valueType = NodeId; + const int stride = byteSizeForMetaType(listEntryType) / sizeof(float); // Resize v.m_data v.m_data.resize(stride * variants.size()); diff --git a/src/render/backend/uniform_p.h b/src/render/backend/uniform_p.h index e0d8fedeb..e31aaa609 100644 --- a/src/render/backend/uniform_p.h +++ b/src/render/backend/uniform_p.h @@ -53,6 +53,9 @@ #include <qt3drender_global.h> #include <Qt3DCore/qnodeid.h> +#include <Qt3DCore/private/matrix4x4_p.h> +#include <Qt3DCore/private/vector3d_p.h> +#include <Qt3DCore/private/vector4d_p.h> #include <QMatrix4x4> #include <QVector2D> @@ -111,11 +114,6 @@ public: BufferValue }; - struct Texture { - int textureId = 0; // Set first so that glUniform1iv will work - Qt3DCore::QNodeId nodeId; - }; - // UniformValue implicitely converts doubles to floats to ensure // correct rendering behavior for the cases where Qt3D parameters created from // a double or QVariant(double) are used to fill uniform values that in reality @@ -135,8 +133,8 @@ public: UniformValue(double d) : UniformValue() { data<float>()[0] = d; } // Double to float conversion UniformValue(bool b) : UniformValue() { data<bool>()[0] = b; } UniformValue(const QVector2D &vec2) : UniformValue() { memcpy(m_data.data(), &vec2, sizeof(QVector2D)); } - UniformValue(const QVector3D &vec3) : UniformValue() { memcpy(m_data.data(), &vec3, sizeof(QVector3D)); } - UniformValue(const QVector4D &vec4) : m_data(4) { memcpy(m_data.data(), &vec4, sizeof(QVector4D)); } + UniformValue(const Vector3D &vec3) : UniformValue() { memcpy(m_data.data(), &vec3, sizeof(Vector3D)); } + UniformValue(const Vector4D &vec4) : m_data(sizeof(Vector4D) / sizeof(float)) { memcpy(m_data.data(), &vec4, sizeof(Vector4D)); } UniformValue(const QMatrix3x3 &mat33) : m_data(9) @@ -145,12 +143,22 @@ public: memcpy(m_data.data(), mat33.constData(), 9 * sizeof(float)); } + // We don t want the QMatrix4x4 builder to use sizeof since QMatrix4x4 contains a type flag +#if defined(__SSE2__) || defined(__AVX2__) + UniformValue(const Matrix4x4 &mat44) + : m_data(sizeof(Matrix4x4) / sizeof(float)) + { + // Use constData because we want column-major layout + memcpy(m_data.data(), &mat44, sizeof(Matrix4x4)); + } +#else UniformValue(const QMatrix4x4 &mat44) : m_data(16) { // Use constData because we want column-major layout memcpy(m_data.data(), mat44.constData(), 16 * sizeof(float)); } +#endif UniformValue(const QVector<QMatrix4x4> &v) : m_data(16 * v.size()) @@ -164,6 +172,13 @@ public: } } + // Reserve data to be filled in later + UniformValue(int byteSize, ValueType valueType) + : m_data(byteSize / sizeof(float)) + , m_valueType(valueType) + { + } + // For nodes which will later be replaced by a Texture or Buffer UniformValue(Qt3DCore::QNodeId id) : UniformValue() @@ -172,14 +187,6 @@ public: memcpy(m_data.data(), &id, sizeof(Qt3DCore::QNodeId)); } - // For textures - UniformValue(UniformValue::Texture t) - : UniformValue() - { - m_valueType = TextureValue; - memcpy(m_data.data(), &t, sizeof(Texture)); - } - ValueType valueType() const { return m_valueType; } UniformType storedType() const { return m_storedType; } diff --git a/src/render/frontend/qrenderaspect.cpp b/src/render/frontend/qrenderaspect.cpp index 3b63f43eb..5e1fea288 100644 --- a/src/render/frontend/qrenderaspect.cpp +++ b/src/render/frontend/qrenderaspect.cpp @@ -153,6 +153,8 @@ #include <private/qrenderpluginfactory_p.h> #include <private/qrenderplugin_p.h> +#include <private/framegraphvisitor_p.h> +#include <private/platformsurfacefilter_p.h> #include <Qt3DCore/qentity.h> #include <Qt3DCore/qtransform.h> @@ -188,7 +190,12 @@ QRenderAspectPrivate::QRenderAspectPrivate(QRenderAspect::RenderType type) , m_initialized(false) , m_renderType(type) , m_offscreenHelper(nullptr) + , m_blockingRendermode(false) { + // The blocking mode can be enabled to make sure we render even while + // waiting for geometries to load. This is necessary if we want + // to call doRender for every QtQuick frame when using Scene3D frame. + m_blockingRendermode = !qgetenv("SCENE3D_BLOCKING_RENDERMODE").isEmpty(); m_instances.append(this); loadSceneParsers(); } @@ -374,6 +381,11 @@ void QRenderAspectPrivate::registerBackendType(const QMetaObject &obj, q->registerBackendType(obj, functor); } +void QRenderAspectPrivate::abortRenderJobs() +{ + m_renderer->abortRenderJobs(); +} + /*! * The constructor creates a new QRenderAspect::QRenderAspect instance with the * specified \a parent. @@ -412,9 +424,17 @@ void QRenderAspectPrivate::renderInitialize(QOpenGLContext *context) } /*! \internal */ -void QRenderAspectPrivate::renderSynchronous(bool blocking) +void QRenderAspectPrivate::tryRenderSynchronous() { - m_renderer->doRender(blocking); + // If the render aspect is slow for some reason and does not build jobs + // immediately, we might want to wait for it to make sure we render + // one Qt3D frame for each QtQuick frame. If blocking mode is enabled, + // we will wait a short time. + // TODO By allowing the aspect thread to skip a couple of frames that + // are not rendered without being in sync with the QtQuick scene graph, + // we can make this into a blocking call and get rid of the timeout. + if (m_renderer->tryWaitForRenderJobs(m_blockingRendermode ? 20 : 0)) + m_renderer->lockSurfaceAndRender(); } /*! @@ -450,36 +470,16 @@ QVector<Qt3DCore::QAspectJobPtr> QRenderAspect::jobsToExecute(qint64 time) // asked for jobs to execute (this function). If that is the case, the RenderSettings will // be null and we should not generate any jobs. if (d->m_renderer->isRunning() && d->m_renderer->settings()) { - Render::NodeManagers *manager = d->m_renderer->nodeManagers(); - QAspectJobPtr textureLoadingSync = d->m_renderer->syncTextureLoadingJob(); - textureLoadingSync->removeDependency(QWeakPointer<QAspectJob>()); - - // Launch texture generator jobs - const QVector<QTextureImageDataGeneratorPtr> pendingImgGen = manager->textureImageDataManager()->pendingGenerators(); - for (const QTextureImageDataGeneratorPtr &imgGen : pendingImgGen) { - auto loadTextureJob = Render::LoadTextureDataJobPtr::create(imgGen); - textureLoadingSync->addDependency(loadTextureJob); - loadTextureJob->setNodeManagers(manager); - jobs.append(loadTextureJob); - } - const QVector<QTextureGeneratorPtr> pendingTexGen = manager->textureDataManager()->pendingGenerators(); - for (const QTextureGeneratorPtr &texGen : pendingTexGen) { - auto loadTextureJob = Render::LoadTextureDataJobPtr::create(texGen); - textureLoadingSync->addDependency(loadTextureJob); - loadTextureJob->setNodeManagers(manager); - jobs.append(loadTextureJob); - } - - // Launch skeleton loader jobs. We join on the syncTextureLoadingJob for now - // which should likely be renamed to something more generic or we introduce - // another synchronizing job for skeleton loading + QAspectJobPtr assetLoadingSync = d->m_renderer->syncSkeletonLoadingJob(); + assetLoadingSync->removeDependency(QWeakPointer<QAspectJob>()); + // Launch skeleton loader jobs const QVector<Render::HSkeleton> skeletonsToLoad = manager->skeletonManager()->dirtySkeletons(Render::SkeletonManager::SkeletonDataDirty); for (const auto &skeletonHandle : skeletonsToLoad) { auto loadSkeletonJob = Render::LoadSkeletonJobPtr::create(skeletonHandle); loadSkeletonJob->setNodeManagers(manager); - textureLoadingSync->addDependency(loadSkeletonJob); + assetLoadingSync->addDependency(loadSkeletonJob); jobs.append(loadSkeletonJob); } @@ -510,12 +510,16 @@ QVector<Qt3DCore::QAspectJobPtr> QRenderAspect::jobsToExecute(qint64 time) return jobs; } - // Traverse the current framegraph and create jobs to populate - // RenderBins with RenderCommands - // All jobs needed to create the frame and their dependencies are set by - // renderBinJobs() - const QVector<QAspectJobPtr> renderBinJobs = d->m_renderer->renderBinJobs(); - jobs.append(renderBinJobs); + // Let the rendering thread know that we are ready to spawn jobs if it + // can promise us that it will in fact call doRender. + if (d->m_renderer->releaseRendererAndRequestPromiseToRender()) { + // Traverse the current framegraph and create jobs to populate + // RenderBins with RenderCommands + // All jobs needed to create the frame and their dependencies are set by + // renderBinJobs() + const QVector<QAspectJobPtr> renderBinJobs = d->m_renderer->renderBinJobs(); + jobs.append(renderBinJobs); + } } return jobs; } diff --git a/src/render/frontend/qrenderaspect_p.h b/src/render/frontend/qrenderaspect_p.h index 26ca091f6..d18ce8b4f 100644 --- a/src/render/frontend/qrenderaspect_p.h +++ b/src/render/frontend/qrenderaspect_p.h @@ -90,9 +90,10 @@ public: void loadSceneParsers(); void loadRenderPlugin(const QString &pluginName); void renderInitialize(QOpenGLContext *context); - void renderSynchronous(bool blocking = false); + void tryRenderSynchronous(); void renderShutdown(); void registerBackendType(const QMetaObject &, const Qt3DCore::QBackendNodeMapperPtr &functor); + void abortRenderJobs(); QVector<Qt3DCore::QAspectJobPtr> createGeometryRendererJobs(); Render::NodeManagers *m_nodeManagers; @@ -104,6 +105,7 @@ public: QVector<Render::QRenderPlugin *> m_renderPlugins; QRenderAspect::RenderType m_renderType; Render::OffscreenSurfaceHelper *m_offscreenHelper; + bool m_blockingRendermode; static QMutex m_pluginLock; static QVector<QString> m_pluginConfig; diff --git a/src/render/frontend/sphere.cpp b/src/render/frontend/sphere.cpp index 2c22e0da4..740626163 100644 --- a/src/render/frontend/sphere.cpp +++ b/src/render/frontend/sphere.cpp @@ -53,18 +53,18 @@ namespace { // Intersects ray r = p + td, |d| = 1, with sphere s and, if intersecting, // returns true and intersection point q; false otherwise -bool intersectRaySphere(const Qt3DRender::RayCasting::QRay3D &ray, const Qt3DRender::Render::Sphere &s, QVector3D *q = nullptr) +bool intersectRaySphere(const Qt3DRender::RayCasting::QRay3D &ray, const Qt3DRender::Render::Sphere &s, Vector3D *q = nullptr) { - const QVector3D p = ray.origin(); - const QVector3D d = ray.direction(); - const QVector3D m = p - s.center(); - const float c = QVector3D::dotProduct(m, m) - s.radius() * s.radius(); + const Vector3D p = ray.origin(); + const Vector3D d = ray.direction(); + const Vector3D m = p - s.center(); + const float c = Vector3D::dotProduct(m, m) - s.radius() * s.radius(); // If there is definitely at least one real root, there must be an intersection if (q == nullptr && c <= 0.0f) return true; - const float b = QVector3D::dotProduct(m, d); + const float b = Vector3D::dotProduct(m, d); // Exit if r’s origin outside s (c > 0) and r pointing away from s (b > 0) if (c > 0.0f && b > 0.0f) return false; @@ -89,12 +89,12 @@ bool intersectRaySphere(const Qt3DRender::RayCasting::QRay3D &ray, const Qt3DRen return true; } -inline QPair<int, int> findExtremePoints(const QVector<QVector3D> &points) +inline QPair<int, int> findExtremePoints(const QVector<Vector3D> &points) { // Find indices of extreme points along x, y, and z axes int xMin = 0, xMax = 0, yMin = 0, yMax = 0, zMin = 0, zMax = 0; for (int i = 1; i < points.size(); ++i) { - const QVector3D &p = points.at(i); + const Vector3D &p = points.at(i); if (p.x() < points[xMin].x()) xMin = i; if (p.x() > points[xMax].x()) @@ -124,20 +124,20 @@ inline QPair<int, int> findExtremePoints(const QVector<QVector3D> &points) return extremeIndices; } -inline void sphereFromExtremePoints(Qt3DRender::Render::Sphere &s, const QVector<QVector3D> &points) +inline void sphereFromExtremePoints(Qt3DRender::Render::Sphere &s, const QVector<Vector3D> &points) { // Find two most separated points on any of the basis vectors QPair<int, int> extremeIndices = findExtremePoints(points); // Construct sphere to contain these two points - const QVector3D &p = points.at(extremeIndices.first); - const QVector3D &q = points.at(extremeIndices.second); - const QVector3D c = 0.5f * (p + q); + const Vector3D &p = points.at(extremeIndices.first); + const Vector3D &q = points.at(extremeIndices.second); + const Vector3D c = 0.5f * (p + q); s.setCenter(c); s.setRadius((q - c).length()); } -inline void constructRitterSphere(Qt3DRender::Render::Sphere &s, const QVector<QVector3D> &points) +inline void constructRitterSphere(Qt3DRender::Render::Sphere &s, const QVector<Vector3D> &points) { // Calculate the sphere encompassing two axially extreme points sphereFromExtremePoints(s, points); @@ -154,22 +154,22 @@ namespace Render { const float Sphere::ms_epsilon = 1.0e-7f; -Sphere Sphere::fromPoints(const QVector<QVector3D> &points) +Sphere Sphere::fromPoints(const QVector<Vector3D> &points) { Sphere s; s.initializeFromPoints(points); return s; } -void Sphere::initializeFromPoints(const QVector<QVector3D> &points) +void Sphere::initializeFromPoints(const QVector<Vector3D> &points) { if (!points.isEmpty()) constructRitterSphere(*this, points); } -void Sphere::expandToContain(const QVector3D &p) +void Sphere::expandToContain(const Vector3D &p) { - const QVector3D d = p - m_center; + const Vector3D d = p - m_center; const float dist2 = d.lengthSquared(); if (dist2 > m_radius * m_radius) { @@ -184,7 +184,7 @@ void Sphere::expandToContain(const QVector3D &p) void Sphere::expandToContain(const Sphere &sphere) { - const QVector3D d(sphere.m_center - m_center); + const Vector3D d(sphere.m_center - m_center); const float dist2 = d.lengthSquared(); const float dr = sphere.m_radius - m_radius; @@ -204,16 +204,16 @@ void Sphere::expandToContain(const Sphere &sphere) } } -Sphere Sphere::transformed(const QMatrix4x4 &mat) const +Sphere Sphere::transformed(const Matrix4x4 &mat) const { // Transform extremities in x, y, and z directions to find extremities // of the resulting ellipsoid - QVector3D x = mat.map(m_center + QVector3D(m_radius, 0.0f, 0.0f)); - QVector3D y = mat.map(m_center + QVector3D(0.0f, m_radius, 0.0f)); - QVector3D z = mat.map(m_center + QVector3D(0.0f, 0.0f, m_radius)); + Vector3D x = mat.map(m_center + Vector3D(m_radius, 0.0f, 0.0f)); + Vector3D y = mat.map(m_center + Vector3D(0.0f, m_radius, 0.0f)); + Vector3D z = mat.map(m_center + Vector3D(0.0f, 0.0f, m_radius)); // Transform center and find maximum radius of ellipsoid - QVector3D c = mat.map(m_center); + Vector3D c = mat.map(m_center); float rSquared = qMax(qMax((x - c).lengthSquared(), (y - c).lengthSquared()), (z - c).lengthSquared()); return Sphere(c, sqrt(rSquared), id()); } @@ -223,7 +223,7 @@ Qt3DCore::QNodeId Sphere::id() const return m_id; } -bool Sphere::intersects(const RayCasting::QRay3D &ray, QVector3D *q, QVector3D *uvw) const +bool Sphere::intersects(const RayCasting::QRay3D &ray, Vector3D *q, Vector3D *uvw) const { Q_UNUSED(uvw); return intersectRaySphere(ray, *this, q); diff --git a/src/render/frontend/sphere_p.h b/src/render/frontend/sphere_p.h index 1590b2f29..0592d8d05 100644 --- a/src/render/frontend/sphere_p.h +++ b/src/render/frontend/sphere_p.h @@ -53,10 +53,10 @@ #include <Qt3DRender/private/qt3drender_global_p.h> #include <Qt3DCore/qnodeid.h> +#include <Qt3DCore/private/matrix4x4_p.h> #include <Qt3DRender/private/boundingsphere_p.h> #include <QMatrix4x4> -#include <QVector3D> QT_BEGIN_NAMESPACE @@ -73,58 +73,58 @@ public: , m_id(i) {} - inline Sphere(const QVector3D &c, float r, Qt3DCore::QNodeId i = Qt3DCore::QNodeId()) + inline Sphere(const Vector3D &c, float r, Qt3DCore::QNodeId i = Qt3DCore::QNodeId()) : m_center(c) , m_radius(r) , m_id(i) {} - void setCenter(const QVector3D &c); - QVector3D center() const override; + void setCenter(const Vector3D &c); + Vector3D center() const override; - inline bool isNull() { return m_center == QVector3D() && m_radius == 0.0f; } + inline bool isNull() { return m_center == Vector3D() && m_radius == 0.0f; } void setRadius(float r); float radius() const override; void clear(); - void initializeFromPoints(const QVector<QVector3D> &points); - void expandToContain(const QVector3D &point); - inline void expandToContain(const QVector<QVector3D> &points) + void initializeFromPoints(const QVector<Vector3D> &points); + void expandToContain(const Vector3D &point); + inline void expandToContain(const QVector<Vector3D> &points) { - for (const QVector3D &p : points) + for (const Vector3D &p : points) expandToContain(p); } void expandToContain(const Sphere &sphere); - Sphere transformed(const QMatrix4x4 &mat) const; - inline Sphere &transform(const QMatrix4x4 &mat) + Sphere transformed(const Matrix4x4 &mat) const; + inline Sphere &transform(const Matrix4x4 &mat) { *this = transformed(mat); return *this; } Qt3DCore::QNodeId id() const final; - bool intersects(const RayCasting::QRay3D &ray, QVector3D *q, QVector3D *uvw = nullptr) const final; + bool intersects(const RayCasting::QRay3D &ray, Vector3D *q, Vector3D *uvw = nullptr) const final; Type type() const final; - static Sphere fromPoints(const QVector<QVector3D> &points); + static Sphere fromPoints(const QVector<Vector3D> &points); private: - QVector3D m_center; + Vector3D m_center; float m_radius; Qt3DCore::QNodeId m_id; static const float ms_epsilon; }; -inline void Sphere::setCenter(const QVector3D &c) +inline void Sphere::setCenter(const Vector3D &c) { m_center = c; } -inline QVector3D Sphere::center() const +inline Vector3D Sphere::center() const { return m_center; } @@ -141,15 +141,15 @@ inline float Sphere::radius() const inline void Sphere::clear() { - m_center = QVector3D(); + m_center = Vector3D(); m_radius = 0.0f; } inline bool intersects(const Sphere &a, const Sphere &b) { // Calculate squared distance between sphere centers - const QVector3D d = a.center() - b.center(); - const float distSq = QVector3D::dotProduct(d, d); + const Vector3D d = a.center() - b.center(); + const float distSq = Vector3D::dotProduct(d, d); // Spheres intersect if squared distance is less than squared // sum of radii diff --git a/src/render/geometry/geometryrenderer.cpp b/src/render/geometry/geometryrenderer.cpp index ea059c6ee..a73589507 100644 --- a/src/render/geometry/geometryrenderer.cpp +++ b/src/render/geometry/geometryrenderer.cpp @@ -42,6 +42,8 @@ #include <Qt3DRender/private/qboundingvolume_p.h> #include <Qt3DRender/private/qgeometryrenderer_p.h> #include <Qt3DRender/private/qmesh_p.h> +#include <Qt3DRender/private/managers_p.h> +#include <Qt3DRender/private/nodemanagers_p.h> #include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DCore/qpropertynodeaddedchange.h> #include <Qt3DCore/qpropertynoderemovedchange.h> diff --git a/src/render/graphicshelpers/graphicscontext.cpp b/src/render/graphicshelpers/graphicscontext.cpp index 9e8e3d610..5c3128f30 100644 --- a/src/render/graphicshelpers/graphicscontext.cpp +++ b/src/render/graphicshelpers/graphicscontext.cpp @@ -232,13 +232,10 @@ void GraphicsContext::resolveRenderTargetFormat() #undef RGBA_BITS } -bool GraphicsContext::beginDrawing(QSurface *surface) +void GraphicsContext::beginDrawing() { - Q_ASSERT(surface); Q_ASSERT(m_gl); - m_surface = surface; - // TO DO: Find a way to make to pause work if the window is not exposed // if (m_surface && m_surface->surfaceClass() == QSurface::Window) { // qDebug() << Q_FUNC_INFO << 1; @@ -247,12 +244,6 @@ bool GraphicsContext::beginDrawing(QSurface *surface) // qDebug() << Q_FUNC_INFO << 2; // } - // Makes the surface current on the OpenGLContext - // and sets the right glHelper - m_ownCurrent = !(m_gl->surface() == m_surface); - if (m_ownCurrent && !makeCurrent(m_surface)) - return false; - // TODO: cache surface format somewhere rather than doing this every time render surface changes resolveRenderTargetFormat(); @@ -293,8 +284,6 @@ bool GraphicsContext::beginDrawing(QSurface *surface) const int shaderPurgePeriod = 600; if (callCount % shaderPurgePeriod == 0) m_shaderCache.purge(); - - return true; } void GraphicsContext::clearBackBuffer(QClearBuffers::BufferTypeFlags buffers) @@ -453,6 +442,7 @@ bool GraphicsContext::makeCurrent(QSurface *surface) m_glHelper = resolveHighestOpenGLFunctions(); m_glHelpers.insert(surface, m_glHelper); } + m_surface = surface; return true; } @@ -509,14 +499,14 @@ void GraphicsContext::introspectShaderInterface(Shader *shader, QOpenGLShaderPro void GraphicsContext::loadShader(Shader *shader, ShaderManager *manager) { - QOpenGLShaderProgram *shaderProgram = m_shaderCache.getShaderProgramAndAddRef(shader->dna(), shader->peerId()); - if (!shaderProgram) { + bool wasPresent = false; + QOpenGLShaderProgram *shaderProgram = m_shaderCache.getShaderProgramAndAddRef(shader->dna(), shader->peerId(), &wasPresent); + if (!shaderProgram && !wasPresent) { // No matching QOpenGLShader in the cache so create one shaderProgram = createShaderProgram(shader); - // Store in cache - if (shaderProgram) - m_shaderCache.insert(shader->dna(), shader->peerId(), shaderProgram); + // Store in cache (even when failed and shaderProgram is null) + m_shaderCache.insert(shader->dna(), shader->peerId(), shaderProgram); } // Ensure the Shader node knows about the program interface @@ -544,7 +534,6 @@ void GraphicsContext::loadShader(Shader *shader, ShaderManager *manager) shader->setGraphicsContext(this); shader->setLoaded(true); - shader->markDirty(AbstractRenderer::AllDirty); } } @@ -1224,7 +1213,7 @@ bool GraphicsContext::setParameters(ShaderParameterPack ¶meterPack) UniformValue &texUniform = uniformValues[namedTex.glslNameId]; Q_ASSERT(texUniform.valueType() == UniformValue::TextureValue); const int texUnit = activateTexture(TextureScopeMaterial, t); - texUniform.data<UniformValue::Texture>()->textureId = texUnit; + texUniform.data<int>()[namedTex.uniformArrayIndex] = texUnit; // if the texture data from generators may not be available yet, // make sure that the next frame is rendered if (texUnit == -1) @@ -1274,11 +1263,10 @@ bool GraphicsContext::setParameters(ShaderParameterPack ¶meterPack) for (const ShaderUniform &uniform : activeUniforms) { // We can use [] as we are sure the the uniform wouldn't // be un activeUniforms if there wasn't a matching value - const auto &v = values[uniform.m_nameId]; + const UniformValue &v = values[uniform.m_nameId]; // skip invalid textures - if (v.valueType() == UniformValue::TextureValue && - v.constData<UniformValue::Texture>()->textureId == -1) + if (v.valueType() == UniformValue::TextureValue && *v.constData<int>() == -1) continue; applyUniform(uniform, v); diff --git a/src/render/graphicshelpers/graphicscontext_p.h b/src/render/graphicshelpers/graphicscontext_p.h index 24b08e45e..bca841f53 100644 --- a/src/render/graphicshelpers/graphicscontext_p.h +++ b/src/render/graphicshelpers/graphicscontext_p.h @@ -113,7 +113,7 @@ public: int id() const; // unique, small integer ID of this context - bool beginDrawing(QSurface *surface); + void beginDrawing(); void clearBackBuffer(QClearBuffers::BufferTypeFlags buffers); void endDrawing(bool swapBuffers); diff --git a/src/render/jobs/abstractpickingjob.cpp b/src/render/jobs/abstractpickingjob.cpp index 417ac6b65..ccb190cff 100644 --- a/src/render/jobs/abstractpickingjob.cpp +++ b/src/render/jobs/abstractpickingjob.cpp @@ -48,6 +48,8 @@ #include <Qt3DRender/private/rendersettings_p.h> #include <Qt3DRender/private/trianglesvisitor_p.h> #include <Qt3DRender/private/job_common_p.h> +#include <QtGui/qoffscreensurface.h> +#include <QtGui/qwindow.h> QT_BEGIN_NAMESPACE @@ -89,12 +91,12 @@ void AbstractPickingJob::run() runHelper(); } -RayCasting::QRay3D AbstractPickingJob::intersectionRay(const QPoint &pos, const QMatrix4x4 &viewMatrix, - const QMatrix4x4 &projectionMatrix, const QRect &viewport) +RayCasting::QRay3D AbstractPickingJob::intersectionRay(const QPoint &pos, const Matrix4x4 &viewMatrix, + const Matrix4x4 &projectionMatrix, const QRect &viewport) { - QVector3D nearPos = QVector3D(pos.x(), pos.y(), 0.0f); + Vector3D nearPos = Vector3D(pos.x(), pos.y(), 0.0f); nearPos = nearPos.unproject(viewMatrix, projectionMatrix, viewport); - QVector3D farPos = QVector3D(pos.x(), pos.y(), 1.0f); + Vector3D farPos = Vector3D(pos.x(), pos.y(), 1.0f); farPos = farPos.unproject(viewMatrix, projectionMatrix, viewport); return RayCasting::QRay3D(nearPos, @@ -115,18 +117,39 @@ QRect AbstractPickingJob::windowViewport(const QSize &area, const QRectF &relati return relativeViewport.toRect(); } -RayCasting::QRay3D AbstractPickingJob::rayForViewportAndCamera(const QSize &area, - const QPoint &pos, - const QRectF &relativeViewport, - const Qt3DCore::QNodeId cameraId) const +RayCasting::QRay3D AbstractPickingJob::rayForViewportAndCamera(const PickingUtils::ViewportCameraAreaDetails &vca, + QObject *eventSource, + const QPoint &pos) const { - QMatrix4x4 viewMatrix; - QMatrix4x4 projectionMatrix; - Render::CameraLens::viewMatrixForCamera(m_manager->renderNodesManager(), cameraId, viewMatrix, projectionMatrix); - const QRect viewport = windowViewport(area, relativeViewport); + static RayCasting::QRay3D invalidRay({}, {}, 0.f); + Matrix4x4 viewMatrix; + Matrix4x4 projectionMatrix; + Render::CameraLens::viewMatrixForCamera(m_manager->renderNodesManager(), + vca.cameraId, + viewMatrix, + projectionMatrix); + const QRect viewport = windowViewport(vca.area, vca.viewport); + + if (vca.area.isValid() && !viewport.contains(pos)) + return invalidRay; + if (vca.surface) { + QSurface *surface = nullptr; + if (eventSource) { + QWindow *window = qobject_cast<QWindow *>(eventSource); + if (window) { + surface = static_cast<QSurface *>(window); + } else { + QOffscreenSurface *offscreen = qobject_cast<QOffscreenSurface *>(eventSource); + if (offscreen) + surface = static_cast<QSurface *>(offscreen); + } + } + if (surface && vca.surface != surface) + return invalidRay; + } // In GL the y is inverted compared to Qt - const QPoint glCorrectPos = QPoint(pos.x(), area.isValid() ? area.height() - pos.y() : pos.y()); + const QPoint glCorrectPos = QPoint(pos.x(), vca.area.isValid() ? vca.area.height() - pos.y() : pos.y()); const auto ray = intersectionRay(glCorrectPos, viewMatrix, projectionMatrix, viewport); return ray; } diff --git a/src/render/jobs/abstractpickingjob_p.h b/src/render/jobs/abstractpickingjob_p.h index b527d754a..059c87aa7 100644 --- a/src/render/jobs/abstractpickingjob_p.h +++ b/src/render/jobs/abstractpickingjob_p.h @@ -56,6 +56,7 @@ #include <Qt3DRender/private/handle_types_p.h> #include <Qt3DRender/private/qboundingvolumeprovider_p.h> #include <Qt3DRender/private/qcollisionqueryresult_p.h> +#include <Qt3DRender/private/pickboundingvolumeutils_p.h> QT_BEGIN_NAMESPACE @@ -84,8 +85,8 @@ public: // public for unit tests virtual bool runHelper() = 0; static RayCasting::QRay3D intersectionRay(const QPoint &pos, - const QMatrix4x4 &viewMatrix, - const QMatrix4x4 &projectionMatrix, + const Matrix4x4 &viewMatrix, + const Matrix4x4 &projectionMatrix, const QRect &viewport); protected: @@ -99,10 +100,9 @@ protected: bool m_oneEnabledAtLeast; QRect windowViewport(const QSize &area, const QRectF &relativeViewport) const; - RayCasting::QRay3D rayForViewportAndCamera(const QSize &area, - const QPoint &pos, - const QRectF &relativeViewport, - const Qt3DCore::QNodeId cameraId) const; + RayCasting::QRay3D rayForViewportAndCamera(const PickingUtils::ViewportCameraAreaDetails &vca, + QObject *eventSource, + const QPoint &pos) const; }; } // namespace Render diff --git a/src/render/jobs/calcboundingvolumejob.cpp b/src/render/jobs/calcboundingvolumejob.cpp index 021478396..841a158b6 100644 --- a/src/render/jobs/calcboundingvolumejob.cpp +++ b/src/render/jobs/calcboundingvolumejob.cpp @@ -88,9 +88,10 @@ public: int primitiveRestartIndex) { FindExtremePoints findExtremePoints(m_manager); - if (!findExtremePoints.apply(positionAttribute, indexAttribute, - drawVertexCount, primitiveRestartEnabled, primitiveRestartIndex)) + if (!findExtremePoints.apply(positionAttribute, indexAttribute, drawVertexCount, + primitiveRestartEnabled, primitiveRestartIndex)) { return false; + } // Calculate squared distance for the pairs of points const float xDist2 = (findExtremePoints.xMaxPt - findExtremePoints.xMinPt).lengthSquared(); @@ -98,8 +99,8 @@ public: const float zDist2 = (findExtremePoints.zMaxPt - findExtremePoints.zMinPt).lengthSquared(); // Select most distant pair - QVector3D p = findExtremePoints.xMinPt; - QVector3D q = findExtremePoints.xMaxPt; + Vector3D p = findExtremePoints.xMinPt; + Vector3D q = findExtremePoints.xMaxPt; if (yDist2 > xDist2 && yDist2 > zDist2) { p = findExtremePoints.yMinPt; q = findExtremePoints.yMaxPt; @@ -109,13 +110,13 @@ public: q = findExtremePoints.zMaxPt; } - const QVector3D c = 0.5f * (p + q); + const Vector3D c = 0.5f * (p + q); m_volume.setCenter(c); m_volume.setRadius((q - c).length()); ExpandSphere expandSphere(m_manager, m_volume); - if (!expandSphere.apply(positionAttribute, indexAttribute, - drawVertexCount, primitiveRestartEnabled, primitiveRestartIndex)) + if (!expandSphere.apply(positionAttribute, indexAttribute, drawVertexCount, + primitiveRestartEnabled, primitiveRestartIndex)) return false; return true; @@ -134,40 +135,40 @@ private: { } float xMin, xMax, yMin, yMax, zMin, zMax; - QVector3D xMinPt, xMaxPt, yMinPt, yMaxPt, zMinPt, zMaxPt; + Vector3D xMinPt, xMaxPt, yMinPt, yMaxPt, zMinPt, zMaxPt; void visit(uint ndx, float x, float y, float z) override { if (ndx) { if (x < xMin) { xMin = x; - xMinPt = QVector3D(x, y, z); + xMinPt = Vector3D(x, y, z); } if (x > xMax) { xMax = x; - xMaxPt = QVector3D(x, y, z); + xMaxPt = Vector3D(x, y, z); } if (y < yMin) { yMin = y; - yMinPt = QVector3D(x, y, z); + yMinPt = Vector3D(x, y, z); } if (y > yMax) { yMax = y; - yMaxPt = QVector3D(x, y, z); + yMaxPt = Vector3D(x, y, z); } if (z < zMin) { zMin = z; - zMinPt = QVector3D(x, y, z); + zMinPt = Vector3D(x, y, z); } if (z > zMax) { zMax = z; - zMaxPt = QVector3D(x, y, z); + zMaxPt = Vector3D(x, y, z); } } else { xMin = xMax = x; yMin = yMax = y; zMin = zMax = z; - xMinPt = xMaxPt = yMinPt = yMaxPt = zMinPt = zMaxPt = QVector3D(x, y, z); + xMinPt = xMaxPt = yMinPt = yMaxPt = zMinPt = zMaxPt = Vector3D(x, y, z); } } }; @@ -183,7 +184,7 @@ private: void visit(uint ndx, float x, float y, float z) override { Q_UNUSED(ndx); - m_volume.expandToContain(QVector3D(x, y, z)); + m_volume.expandToContain(Vector3D(x, y, z)); } }; }; @@ -197,7 +198,7 @@ void calculateLocalBoundingVolume(NodeManagers *manager, Entity *node) return; GeometryRenderer *gRenderer = node->renderComponent<GeometryRenderer>(); - if (gRenderer) { + if (gRenderer && gRenderer->primitiveType() != QGeometryRenderer::Patches) { Geometry *geom = manager->lookupResource<Geometry, GeometryManager>(gRenderer->geometryId()); if (geom) { @@ -265,18 +266,16 @@ void calculateLocalBoundingVolume(NodeManagers *manager, Entity *node) // in a job executed after this one // We need to recompute the bounding volume // If anything in the GeometryRenderer has changed - if (buf->isDirty() || - node->isBoundingVolumeDirty() || - positionAttribute->isDirty() || - geom->isDirty() || - gRenderer->isDirty() || - (indexAttribute && indexAttribute->isDirty()) || - (indexBuf && indexBuf->isDirty())) - { + if (buf->isDirty() + || node->isBoundingVolumeDirty() + || positionAttribute->isDirty() + || geom->isDirty() + || gRenderer->isDirty() + || (indexAttribute && indexAttribute->isDirty()) + || (indexBuf && indexBuf->isDirty())) { BoundingVolumeCalculator reader(manager); - if (reader.apply(positionAttribute, indexAttribute, - drawVertexCount, gRenderer->primitiveRestartEnabled(), gRenderer->restartIndexValue())) - { + if (reader.apply(positionAttribute, indexAttribute, drawVertexCount, + gRenderer->primitiveRestartEnabled(), gRenderer->restartIndexValue())) { node->localBoundingVolume()->setCenter(reader.result().center()); node->localBoundingVolume()->setRadius(reader.result().radius()); node->unsetBoundingVolumeDirty(); diff --git a/src/render/jobs/frustumcullingjob.cpp b/src/render/jobs/frustumcullingjob.cpp index 85c6b5cad..1a03b691d 100644 --- a/src/render/jobs/frustumcullingjob.cpp +++ b/src/render/jobs/frustumcullingjob.cpp @@ -86,17 +86,17 @@ void FrustumCullingJob::cullScene(Entity *e, const Plane *planes) const Sphere *s = e->worldBoundingVolumeWithChildren(); // Unrolled loop - if (QVector3D::dotProduct(s->center(), planes[0].normal) + planes[0].d < -s->radius()) + if (Vector3D::dotProduct(s->center(), planes[0].normal) + planes[0].d < -s->radius()) return; - if (QVector3D::dotProduct(s->center(), planes[1].normal) + planes[1].d < -s->radius()) + if (Vector3D::dotProduct(s->center(), planes[1].normal) + planes[1].d < -s->radius()) return; - if (QVector3D::dotProduct(s->center(), planes[2].normal) + planes[2].d < -s->radius()) + if (Vector3D::dotProduct(s->center(), planes[2].normal) + planes[2].d < -s->radius()) return; - if (QVector3D::dotProduct(s->center(), planes[3].normal) + planes[3].d < -s->radius()) + if (Vector3D::dotProduct(s->center(), planes[3].normal) + planes[3].d < -s->radius()) return; - if (QVector3D::dotProduct(s->center(), planes[4].normal) + planes[4].d < -s->radius()) + if (Vector3D::dotProduct(s->center(), planes[4].normal) + planes[4].d < -s->radius()) return; - if (QVector3D::dotProduct(s->center(), planes[5].normal) + planes[5].d < -s->radius()) + if (Vector3D::dotProduct(s->center(), planes[5].normal) + planes[5].d < -s->radius()) return; m_visibleEntities.push_back(e); diff --git a/src/render/jobs/frustumcullingjob_p.h b/src/render/jobs/frustumcullingjob_p.h index 8b0bc7150..f81e4c5b9 100644 --- a/src/render/jobs/frustumcullingjob_p.h +++ b/src/render/jobs/frustumcullingjob_p.h @@ -41,7 +41,8 @@ #define QT3DRENDER_RENDER_FRUSTUMCULLINGJOB_P_H #include <Qt3DCore/qaspectjob.h> -#include <QMatrix4x4> +#include <Qt3DCore/private/matrix4x4_p.h> +#include <Qt3DRender/private/aligned_malloc_p.h> // // W A R N I N G @@ -69,11 +70,13 @@ class FrustumCullingJob : public Qt3DCore::QAspectJob public: FrustumCullingJob(); + QT3D_ALIGNED_MALLOC_AND_FREE() + inline void setRoot(Entity *root) Q_DECL_NOTHROW { m_root = root; } inline void setActive(bool active) Q_DECL_NOTHROW { m_active = active; } inline bool isActive() const Q_DECL_NOTHROW { return m_active; } - inline void setViewProjection(const QMatrix4x4 &viewProjection) Q_DECL_NOTHROW { m_viewProjection = viewProjection; } - inline QMatrix4x4 viewProjection() const Q_DECL_NOTHROW { return m_viewProjection; } + inline void setViewProjection(const Matrix4x4 &viewProjection) Q_DECL_NOTHROW { m_viewProjection = viewProjection; } + inline Matrix4x4 viewProjection() const Q_DECL_NOTHROW { return m_viewProjection; } QVector<Entity *> visibleEntities() const Q_DECL_NOTHROW { return m_visibleEntities; } @@ -81,7 +84,7 @@ public: private: void cullScene(Entity *e, const Plane *planes); - QMatrix4x4 m_viewProjection; + Matrix4x4 m_viewProjection; Entity *m_root; QVector<Entity *> m_visibleEntities; bool m_active; diff --git a/src/render/jobs/job_common_p.h b/src/render/jobs/job_common_p.h index 0e570ca19..7fd88a697 100644 --- a/src/render/jobs/job_common_p.h +++ b/src/render/jobs/job_common_p.h @@ -100,12 +100,17 @@ namespace JobTypes { UpdateMeshTriangleList, FilterCompatibleTechniques, UpdateLevelOfDetail, - SyncTextureLoading, + SyncSkeletonLoading, LoadSkeleton, UpdateSkinningPalette, ProximityFiltering, SyncFilterEntityByLayer, - SyncMaterialGatherer + SyncMaterialGatherer, + ReadRenderQueueSizeBarrier, + BeginDrawingBarrier, + UpdateGLResourcesBarrier, + PrepareCommandSubmissionBarrier, + EndDrawingBarrier }; } // JobTypes diff --git a/src/render/jobs/loadtexturedatajob.cpp b/src/render/jobs/loadtexturedatajob.cpp index 55232d74f..790e41998 100644 --- a/src/render/jobs/loadtexturedatajob.cpp +++ b/src/render/jobs/loadtexturedatajob.cpp @@ -49,16 +49,7 @@ QT_BEGIN_NAMESPACE namespace Qt3DRender { namespace Render { -LoadTextureDataJob::LoadTextureDataJob(const QTextureGeneratorPtr &texGen) - : m_texGen(texGen) - , m_imgDataGen(nullptr) -{ - SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadTextureData, 0); -} - -LoadTextureDataJob::LoadTextureDataJob(const QTextureImageDataGeneratorPtr &imgDataGen) - : m_texGen(nullptr) - , m_imgDataGen(imgDataGen) +LoadTextureDataJob::LoadTextureDataJob() { SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadTextureData, 0); } @@ -69,13 +60,20 @@ LoadTextureDataJob::~LoadTextureDataJob() void LoadTextureDataJob::run() { - if (m_texGen) { - QTextureDataPtr texData = (*m_texGen)(); - m_manager->textureDataManager()->assignData(m_texGen, texData); + // NOTE: This must run after Renderer::updateGLResources(), + // because that is where pendingGenerators is populated. + // We are therefore not able to create one job for each texture + // before we add the ability for running jobs (like this) to + // spawn new jobs. + const QVector<QTextureImageDataGeneratorPtr> pendingImgGen = m_manager->textureImageDataManager()->pendingGenerators(); + for (const QTextureImageDataGeneratorPtr &imgGen : pendingImgGen) { + QTextureImageDataPtr imgData = (*imgGen)(); + m_manager->textureImageDataManager()->assignData(imgGen, imgData); } - if (m_imgDataGen) { - QTextureImageDataPtr imgData = (*m_imgDataGen)(); - m_manager->textureImageDataManager()->assignData(m_imgDataGen, imgData); + const QVector<QTextureGeneratorPtr> pendingTexGen = m_manager->textureDataManager()->pendingGenerators(); + for (const QTextureGeneratorPtr &texGen : pendingTexGen) { + QTextureDataPtr texData = (*texGen)(); + m_manager->textureDataManager()->assignData(texGen, texData); } } diff --git a/src/render/jobs/loadtexturedatajob_p.h b/src/render/jobs/loadtexturedatajob_p.h index 607068712..7272bbc1d 100644 --- a/src/render/jobs/loadtexturedatajob_p.h +++ b/src/render/jobs/loadtexturedatajob_p.h @@ -67,8 +67,7 @@ class NodeManagers; class LoadTextureDataJob : public Qt3DCore::QAspectJob { public: - LoadTextureDataJob(const QTextureGeneratorPtr &texGen); - LoadTextureDataJob(const QTextureImageDataGeneratorPtr &imgDataGen); + LoadTextureDataJob(); ~LoadTextureDataJob(); inline void setNodeManagers(NodeManagers *manager) { m_manager = manager; } @@ -77,9 +76,6 @@ protected: void run() final; private: - QTextureGeneratorPtr m_texGen; - QTextureImageDataGeneratorPtr m_imgDataGen; - NodeManagers *m_manager; }; diff --git a/src/render/jobs/pickboundingvolumejob.cpp b/src/render/jobs/pickboundingvolumejob.cpp index 1805f6d43..5884a8f67 100644 --- a/src/render/jobs/pickboundingvolumejob.cpp +++ b/src/render/jobs/pickboundingvolumejob.cpp @@ -54,6 +54,10 @@ #include <Qt3DRender/private/qpickevent_p.h> #include <Qt3DRender/private/pickboundingvolumeutils_p.h> +#include <QSurface> +#include <QWindow> +#include <QOffscreenSurface> + QT_BEGIN_NAMESPACE namespace Qt3DRender { @@ -111,7 +115,12 @@ PickBoundingVolumeJob::PickBoundingVolumeJob() SET_JOB_RUN_STAT_TYPE(this, JobTypes::PickBoundingVolume, 0); } -void PickBoundingVolumeJob::setMouseEvents(const QList<QMouseEvent> &pendingEvents) +void PickBoundingVolumeJob::setRoot(Entity *root) +{ + m_node = root; +} + +void PickBoundingVolumeJob::setMouseEvents(const QList<QPair<QObject*, QMouseEvent>> &pendingEvents) { m_pendingMouseEvents = pendingEvents; } @@ -159,8 +168,8 @@ bool PickBoundingVolumeJob::runHelper() bool hasMoveEvent = false; bool hasOtherEvent = false; // Quickly look which types of events we've got - for (const QMouseEvent &event : mouseEvents) { - const bool isMove = (event.type() == QEvent::MouseMove); + for (const auto &event : mouseEvents) { + const bool isMove = (event.second.type() == QEvent::MouseMove); hasMoveEvent |= isMove; hasOtherEvent |= !isMove; } @@ -188,10 +197,10 @@ bool PickBoundingVolumeJob::runHelper() PickingUtils::ViewportCameraAreaGatherer vcaGatherer; // TO DO: We could cache this and only gather when we know the FrameGraph tree has changed - const QVector<PickingUtils::ViewportCameraAreaTriplet> vcaTriplets = vcaGatherer.gather(m_frameGraphRoot); + const QVector<PickingUtils::ViewportCameraAreaDetails> vcaDetails = vcaGatherer.gather(m_frameGraphRoot); // If we have no viewport / camera or area, return early - if (vcaTriplets.empty()) + if (vcaDetails.empty()) return false; // TO DO: @@ -210,19 +219,21 @@ bool PickBoundingVolumeJob::runHelper() const float pickWorldSpaceTolerance = m_renderSettings->pickWorldSpaceTolerance(); // For each mouse event - for (const QMouseEvent &event : mouseEvents) { + for (const auto &event : mouseEvents) { m_hoveredPickersToClear = m_hoveredPickers; QPickEvent::Buttons eventButton = QPickEvent::NoButton; int eventButtons = 0; int eventModifiers = QPickEvent::NoModifier; - setEventButtonAndModifiers(event, eventButton, eventButtons, eventModifiers); + setEventButtonAndModifiers(event.second, eventButton, eventButtons, eventModifiers); - // For each triplet of Viewport / Camera and Area - for (const PickingUtils::ViewportCameraAreaTriplet &vca : vcaTriplets) { + // For each Viewport / Camera and Area entry + for (const PickingUtils::ViewportCameraAreaDetails &vca : vcaDetails) { PickingUtils::HitList sphereHits; - QRay3D ray = rayForViewportAndCamera(vca.area, event.pos(), vca.viewport, vca.cameraId); + QRay3D ray = rayForViewportAndCamera(vca, event.first, event.second.pos()); + if (!ray.isValid()) + continue; PickingUtils::HierarchicalEntityPicker entityPicker(ray); if (entityPicker.collectHits(m_manager, m_node)) { @@ -259,7 +270,7 @@ bool PickBoundingVolumeJob::runHelper() } // Dispatch events based on hit results - dispatchPickEvents(event, sphereHits, eventButton, eventButtons, eventModifiers, allHitsRequested); + dispatchPickEvents(event.second, sphereHits, eventButton, eventButtons, eventModifiers, allHitsRequested); } } @@ -309,39 +320,48 @@ void PickBoundingVolumeJob::dispatchPickEvents(const QMouseEvent &event, } // Send the corresponding event - QVector3D localIntersection = hit.m_intersection; + Vector3D localIntersection = hit.m_intersection; if (entity && entity->worldTransform()) localIntersection = entity->worldTransform()->inverted() * hit.m_intersection; QPickEventPtr pickEvent; switch (hit.m_type) { case QCollisionQueryResult::Hit::Triangle: - pickEvent = QPickTriangleEventPtr::create(event.localPos(), hit.m_intersection, - localIntersection, hit.m_distance, - hit.m_primitiveIndex, - hit.m_vertexIndex[0], - hit.m_vertexIndex[1], - hit.m_vertexIndex[2], - eventButton, eventButtons, - eventModifiers, hit.m_uvw); + pickEvent.reset(new QPickTriangleEvent(event.localPos(), + convertToQVector3D(hit.m_intersection), + convertToQVector3D(localIntersection), + hit.m_distance, + hit.m_primitiveIndex, + hit.m_vertexIndex[0], + hit.m_vertexIndex[1], + hit.m_vertexIndex[2], + eventButton, eventButtons, + eventModifiers, + convertToQVector3D(hit.m_uvw))); break; case QCollisionQueryResult::Hit::Edge: - pickEvent = QPickLineEventPtr::create(event.localPos(), hit.m_intersection, - localIntersection, hit.m_distance, - hit.m_primitiveIndex, - hit.m_vertexIndex[0], hit.m_vertexIndex[1], - eventButton, eventButtons, eventModifiers); + pickEvent.reset(new QPickLineEvent(event.localPos(), + convertToQVector3D(hit.m_intersection), + convertToQVector3D(localIntersection), + hit.m_distance, + hit.m_primitiveIndex, + hit.m_vertexIndex[0], hit.m_vertexIndex[1], + eventButton, eventButtons, eventModifiers)); break; case QCollisionQueryResult::Hit::Point: - pickEvent = QPickPointEventPtr::create(event.localPos(), hit.m_intersection, - localIntersection, hit.m_distance, - hit.m_vertexIndex[0], - eventButton, eventButtons, eventModifiers); + pickEvent.reset(new QPickPointEvent(event.localPos(), + convertToQVector3D(hit.m_intersection), + convertToQVector3D(localIntersection), + hit.m_distance, + hit.m_vertexIndex[0], + eventButton, eventButtons, eventModifiers)); break; case QCollisionQueryResult::Hit::Entity: - pickEvent = QPickEventPtr::create(event.localPos(), hit.m_intersection, - localIntersection, hit.m_distance, - eventButton, eventButtons, eventModifiers); + pickEvent.reset(new QPickEvent(event.localPos(), + convertToQVector3D(hit.m_intersection), + convertToQVector3D(localIntersection), + hit.m_distance, + eventButton, eventButtons, eventModifiers)); break; default: Q_UNREACHABLE(); diff --git a/src/render/jobs/pickboundingvolumejob_p.h b/src/render/jobs/pickboundingvolumejob_p.h index 407cc37a5..2c38c400b 100644 --- a/src/render/jobs/pickboundingvolumejob_p.h +++ b/src/render/jobs/pickboundingvolumejob_p.h @@ -52,6 +52,12 @@ // #include "abstractpickingjob_p.h" +#include <Qt3DCore/qaspectjob.h> +#include <Qt3DRender/private/qray3d_p.h> +#include <Qt3DRender/private/handle_types_p.h> +#include <Qt3DRender/private/qboundingvolumeprovider_p.h> +#include <Qt3DRender/private/qcollisionqueryresult_p.h> +#include <Qt3DRender/private/pickboundingvolumeutils_p.h> #include <Qt3DRender/qpickevent.h> #include <QMouseEvent> #include <QKeyEvent> @@ -71,7 +77,8 @@ class Q_AUTOTEST_EXPORT PickBoundingVolumeJob : public AbstractPickingJob public: PickBoundingVolumeJob(); - void setMouseEvents(const QList<QMouseEvent> &pendingEvents); + void setRoot(Entity *root); + void setMouseEvents(const QList<QPair<QObject*, QMouseEvent>> &pendingEvents); void setKeyEvents(const QList<QKeyEvent> &pendingEvents); void markPickersDirty(); bool pickersDirty() const { return m_pickersDirty; } @@ -90,15 +97,15 @@ protected: bool allHitsRequested); private: - QList<QMouseEvent> m_pendingMouseEvents; + void clearPreviouslyHoveredPickers(); + + QList<QPair<QObject*, QMouseEvent>> m_pendingMouseEvents; QList<QKeyEvent> m_pendingKeyEvents; bool m_pickersDirty; bool m_oneHoverAtLeast; HObjectPicker m_currentPicker; QVector<HObjectPicker> m_hoveredPickers; QVector<HObjectPicker> m_hoveredPickersToClear; - - void clearPreviouslyHoveredPickers(); }; typedef QSharedPointer<PickBoundingVolumeJob> PickBoundingVolumeJobPtr; diff --git a/src/render/jobs/pickboundingvolumeutils.cpp b/src/render/jobs/pickboundingvolumeutils.cpp index ba88e5691..21255819f 100644 --- a/src/render/jobs/pickboundingvolumeutils.cpp +++ b/src/render/jobs/pickboundingvolumeutils.cpp @@ -73,9 +73,9 @@ void ViewportCameraAreaGatherer::visit(FrameGraphNode *node) m_leaves.push_back(node); } -ViewportCameraAreaTriplet ViewportCameraAreaGatherer::gatherUpViewportCameraAreas(Render::FrameGraphNode *node) const +ViewportCameraAreaDetails ViewportCameraAreaGatherer::gatherUpViewportCameraAreas(Render::FrameGraphNode *node) const { - ViewportCameraAreaTriplet vca; + ViewportCameraAreaDetails vca; vca.viewport = QRectF(0.0f, 0.0f, 1.0f, 1.0f); while (node) { @@ -87,9 +87,12 @@ ViewportCameraAreaTriplet ViewportCameraAreaGatherer::gatherUpViewportCameraArea case FrameGraphNode::Viewport: vca.viewport = computeViewport(vca.viewport, static_cast<const ViewportNode *>(node)); break; - case FrameGraphNode::Surface: - vca.area = static_cast<const RenderSurfaceSelector *>(node)->renderTargetSize(); + case FrameGraphNode::Surface: { + auto selector = static_cast<const RenderSurfaceSelector *>(node); + vca.area = selector->renderTargetSize(); + vca.surface = selector->surface(); break; + } default: break; } @@ -99,29 +102,32 @@ ViewportCameraAreaTriplet ViewportCameraAreaGatherer::gatherUpViewportCameraArea return vca; } -QVector<ViewportCameraAreaTriplet> ViewportCameraAreaGatherer::gather(FrameGraphNode *root) +QVector<ViewportCameraAreaDetails> ViewportCameraAreaGatherer::gather(FrameGraphNode *root) { // Retrieve all leaves visit(root); - QVector<ViewportCameraAreaTriplet> vcaTriplets; + QVector<ViewportCameraAreaDetails> vcaTriplets; vcaTriplets.reserve(m_leaves.count()); // Find all viewport/camera pairs by traversing from leaf to root for (Render::FrameGraphNode *leaf : qAsConst(m_leaves)) { - ViewportCameraAreaTriplet vcaTriplet = gatherUpViewportCameraAreas(leaf); - if (!m_targetCamera.isNull() && vcaTriplet.cameraId != m_targetCamera) + ViewportCameraAreaDetails vcaDetails = gatherUpViewportCameraAreas(leaf); + if (!m_targetCamera.isNull() && vcaDetails.cameraId != m_targetCamera) continue; - if (!vcaTriplet.cameraId.isNull() && isUnique(vcaTriplets, vcaTriplet)) - vcaTriplets.push_back(vcaTriplet); + if (!vcaDetails.cameraId.isNull() && isUnique(vcaTriplets, vcaDetails)) + vcaTriplets.push_back(vcaDetails); } return vcaTriplets; } -bool ViewportCameraAreaGatherer::isUnique(const QVector<ViewportCameraAreaTriplet> &vcaTriplets, - const ViewportCameraAreaTriplet &vca) const +bool ViewportCameraAreaGatherer::isUnique(const QVector<ViewportCameraAreaDetails> &vcaList, + const ViewportCameraAreaDetails &vca) const { - for (const ViewportCameraAreaTriplet &triplet : vcaTriplets) { - if (vca.cameraId == triplet.cameraId && vca.viewport == triplet.viewport && vca.area == triplet.area) + for (const ViewportCameraAreaDetails &listItem : vcaList) { + if (vca.cameraId == listItem.cameraId && + vca.viewport == listItem.viewport && + vca.surface == listItem.surface && + vca.area == listItem.area) return false; } return true; @@ -155,7 +161,6 @@ QVector<Entity *> EntityGatherer::entities() const return m_entities; } - class TriangleCollisionVisitor : public TrianglesVisitor { public: @@ -175,20 +180,20 @@ private: bool m_frontFaceRequested; bool m_backFaceRequested; - void visit(uint andx, const QVector3D &a, - uint bndx, const QVector3D &b, - uint cndx, const QVector3D &c) override; - bool intersectsSegmentTriangle(uint andx, const QVector3D &a, - uint bndx, const QVector3D &b, - uint cndx, const QVector3D &c); + void visit(uint andx, const Vector3D &a, + uint bndx, const Vector3D &b, + uint cndx, const Vector3D &c) override; + bool intersectsSegmentTriangle(uint andx, const Vector3D &a, + uint bndx, const Vector3D &b, + uint cndx, const Vector3D &c); }; -void TriangleCollisionVisitor::visit(uint andx, const QVector3D &a, uint bndx, const QVector3D &b, uint cndx, const QVector3D &c) +void TriangleCollisionVisitor::visit(uint andx, const Vector3D &a, uint bndx, const Vector3D &b, uint cndx, const Vector3D &c) { - const QMatrix4x4 &mat = *m_root->worldTransform(); - const QVector3D tA = mat * a; - const QVector3D tB = mat * b; - const QVector3D tC = mat * c; + const Matrix4x4 &mat = *m_root->worldTransform(); + const Vector3D tA = mat * a; + const Vector3D tB = mat * b; + const Vector3D tC = mat * c; bool intersected = m_frontFaceRequested && intersectsSegmentTriangle(cndx, tC, bndx, tB, andx, tA); // front facing @@ -199,10 +204,11 @@ void TriangleCollisionVisitor::visit(uint andx, const QVector3D &a, uint bndx, c m_triangleIndex++; } -bool TriangleCollisionVisitor::intersectsSegmentTriangle(uint andx, const QVector3D &a, uint bndx, const QVector3D &b, uint cndx, const QVector3D &c) + +bool TriangleCollisionVisitor::intersectsSegmentTriangle(uint andx, const Vector3D &a, uint bndx, const Vector3D &b, uint cndx, const Vector3D &c) { float t = 0.0f; - QVector3D uvw; + Vector3D uvw; bool intersected = Render::intersectsSegmentTriangle(m_ray, a, b, c, uvw, t); if (intersected) { QCollisionQueryResult::Hit queryResult; @@ -238,30 +244,30 @@ private: uint m_segmentIndex; float m_pickWorldSpaceTolerance; - void visit(uint andx, const QVector3D &a, - uint bndx, const QVector3D &b) override; - bool intersectsSegmentSegment(uint andx, const QVector3D &a, - uint bndx, const QVector3D &b); - bool rayToLineSegment(const QVector3D& lineStart,const QVector3D& lineEnd, - float &distance, QVector3D &intersection) const; + void visit(uint andx, const Vector3D &a, + uint bndx, const Vector3D &b) override; + bool intersectsSegmentSegment(uint andx, const Vector3D &a, + uint bndx, const Vector3D &b); + bool rayToLineSegment(const Vector3D& lineStart,const Vector3D& lineEnd, + float &distance, Vector3D &intersection) const; }; -void LineCollisionVisitor::visit(uint andx, const QVector3D &a, uint bndx, const QVector3D &b) +void LineCollisionVisitor::visit(uint andx, const Vector3D &a, uint bndx, const Vector3D &b) { - const QMatrix4x4 &mat = *m_root->worldTransform(); - const QVector3D tA = mat * a; - const QVector3D tB = mat * b; + const Matrix4x4 &mat = *m_root->worldTransform(); + const Vector3D tA = mat * a; + const Vector3D tB = mat * b; intersectsSegmentSegment(andx, tA, bndx, tB); m_segmentIndex++; } -bool LineCollisionVisitor::intersectsSegmentSegment(uint andx, const QVector3D &a, - uint bndx, const QVector3D &b) +bool LineCollisionVisitor::intersectsSegmentSegment(uint andx, const Vector3D &a, + uint bndx, const Vector3D &b) { float distance = 0.f; - QVector3D intersection; + Vector3D intersection; bool res = rayToLineSegment(a, b, distance, intersection); if (res) { QCollisionQueryResult::Hit queryResult; @@ -278,19 +284,19 @@ bool LineCollisionVisitor::intersectsSegmentSegment(uint andx, const QVector3D & return false; } -bool LineCollisionVisitor::rayToLineSegment(const QVector3D& lineStart,const QVector3D& lineEnd, - float &distance, QVector3D &intersection) const +bool LineCollisionVisitor::rayToLineSegment(const Vector3D& lineStart,const Vector3D& lineEnd, + float &distance, Vector3D &intersection) const { const float epsilon = 0.00000001f; - const QVector3D u = m_ray.direction() * m_ray.distance(); - const QVector3D v = lineEnd - lineStart; - const QVector3D w = m_ray.origin() - lineStart; - const float a = QVector3D::dotProduct(u, u); - const float b = QVector3D::dotProduct(u, v); - const float c = QVector3D::dotProduct(v, v); - const float d = QVector3D::dotProduct(u, w); - const float e = QVector3D::dotProduct(v, w); + const Vector3D u = m_ray.direction() * m_ray.distance(); + const Vector3D v = lineEnd - lineStart; + const Vector3D w = m_ray.origin() - lineStart; + const float a = Vector3D::dotProduct(u, u); + const float b = Vector3D::dotProduct(u, v); + const float c = Vector3D::dotProduct(v, v); + const float d = Vector3D::dotProduct(u, w); + const float e = Vector3D::dotProduct(v, w); const float D = a * c - b * b; float sc, sN, sD = D; float tc, tN, tD = D; @@ -331,7 +337,7 @@ bool LineCollisionVisitor::rayToLineSegment(const QVector3D& lineStart,const QVe sc = (qAbs(sN) < epsilon ? 0.0f : sN / sD); tc = (qAbs(tN) < epsilon ? 0.0f : tN / tD); - const QVector3D dP = w + (sc * u) - (tc * v); + const Vector3D dP = w + (sc * u) - (tc * v); const float f = dP.length(); if (f < m_pickWorldSpaceTolerance) { distance = sc * u.length(); @@ -359,23 +365,23 @@ private: uint m_pointIndex; float m_pickWorldSpaceTolerance; - void visit(uint ndx, const QVector3D &p) override; + void visit(uint ndx, const Vector3D &p) override; - double pointToRayDistance(const QVector3D &a, QVector3D &p) + double pointToRayDistance(const Vector3D &a, Vector3D &p) { - const QVector3D v = a - m_ray.origin(); - const double t = QVector3D::dotProduct(v, m_ray.direction()); + const Vector3D v = a - m_ray.origin(); + const double t = Vector3D::dotProduct(v, m_ray.direction()); p = m_ray.origin() + t * m_ray.direction(); return (p - a).length(); } }; -void PointCollisionVisitor::visit(uint ndx, const QVector3D &p) +void PointCollisionVisitor::visit(uint ndx, const Vector3D &p) { - const QMatrix4x4 &mat = *m_root->worldTransform(); - const QVector3D tP = mat * p; - QVector3D intersection; + const Matrix4x4 &mat = *m_root->worldTransform(); + const Vector3D tP = mat * p; + Vector3D intersection; float d = pointToRayDistance(tP, intersection); if (d < m_pickWorldSpaceTolerance) { @@ -464,10 +470,32 @@ void AbstractCollisionGathererFunctor::sortHits(HitList &results) std::sort(results.begin(), results.end(), compareHitsDistance); } +namespace { + +// Workaround to avoid passing *this into the blockMappedReduce calls for the +// mapFunctor which would cause an SSE alignment error on Windows Also note +// that a lambda doesn't work since we need the typedef result_type defined to +// work with QtConcurrent +struct MapFunctorHolder +{ + MapFunctorHolder(const AbstractCollisionGathererFunctor *gatherer) + : m_gatherer(gatherer) + {} + + // This define is required to work with QtConcurrent + typedef HitList result_type; + HitList operator ()(const Entity *e) const { return m_gatherer->operator ()(e); } + + const AbstractCollisionGathererFunctor *m_gatherer; +}; + +} // anonymous + HitList EntityCollisionGathererFunctor::computeHits(const QVector<Entity *> &entities, bool allHitsRequested) { const auto reducerOp = allHitsRequested ? PickingUtils::reduceToAllHits : PickingUtils::reduceToFirstHit; - return QtConcurrent::blockingMappedReduced<HitList>(entities, *this, reducerOp); + const MapFunctorHolder holder(this); + return QtConcurrent::blockingMappedReduced<HitList>(entities, holder, reducerOp); } HitList EntityCollisionGathererFunctor::pick(const Entity *entity) const @@ -485,7 +513,8 @@ HitList EntityCollisionGathererFunctor::pick(const Entity *entity) const HitList TriangleCollisionGathererFunctor::computeHits(const QVector<Entity *> &entities, bool allHitsRequested) { const auto reducerOp = allHitsRequested ? PickingUtils::reduceToAllHits : PickingUtils::reduceToFirstHit; - return QtConcurrent::blockingMappedReduced<HitList>(entities, *this, reducerOp); + const MapFunctorHolder holder(this); + return QtConcurrent::blockingMappedReduced<HitList>(entities, holder, reducerOp); } HitList TriangleCollisionGathererFunctor::pick(const Entity *entity) const @@ -510,7 +539,8 @@ HitList TriangleCollisionGathererFunctor::pick(const Entity *entity) const HitList LineCollisionGathererFunctor::computeHits(const QVector<Entity *> &entities, bool allHitsRequested) { const auto reducerOp = allHitsRequested ? PickingUtils::reduceToAllHits : PickingUtils::reduceToFirstHit; - return QtConcurrent::blockingMappedReduced<HitList>(entities, *this, reducerOp); + const MapFunctorHolder holder(this); + return QtConcurrent::blockingMappedReduced<HitList>(entities, holder, reducerOp); } HitList LineCollisionGathererFunctor::pick(const Entity *entity) const @@ -534,7 +564,8 @@ HitList LineCollisionGathererFunctor::pick(const Entity *entity) const HitList PointCollisionGathererFunctor::computeHits(const QVector<Entity *> &entities, bool allHitsRequested) { const auto reducerOp = allHitsRequested ? PickingUtils::reduceToAllHits : PickingUtils::reduceToFirstHit; - return QtConcurrent::blockingMappedReduced<HitList>(entities, *this, reducerOp); + const MapFunctorHolder holder(this); + return QtConcurrent::blockingMappedReduced<HitList>(entities, holder, reducerOp); } HitList PointCollisionGathererFunctor::pick(const Entity *entity) const diff --git a/src/render/jobs/pickboundingvolumeutils_p.h b/src/render/jobs/pickboundingvolumeutils_p.h index 47ab6c3bd..780c16cc8 100644 --- a/src/render/jobs/pickboundingvolumeutils_p.h +++ b/src/render/jobs/pickboundingvolumeutils_p.h @@ -59,6 +59,8 @@ QT_BEGIN_NAMESPACE +class QSurface; + namespace Qt3DRender { namespace RayCasting { class QAbstractCollisionQueryService; @@ -73,27 +75,28 @@ class NodeManagers; namespace PickingUtils { -struct Q_AUTOTEST_EXPORT ViewportCameraAreaTriplet +struct Q_AUTOTEST_EXPORT ViewportCameraAreaDetails { Qt3DCore::QNodeId cameraId; QRectF viewport; QSize area; + QSurface *surface = nullptr; }; -QT3D_DECLARE_TYPEINFO_3(Qt3DRender, Render, PickingUtils, ViewportCameraAreaTriplet, Q_PRIMITIVE_TYPE) +QT3D_DECLARE_TYPEINFO_3(Qt3DRender, Render, PickingUtils, ViewportCameraAreaDetails, Q_PRIMITIVE_TYPE) class Q_AUTOTEST_EXPORT ViewportCameraAreaGatherer { public: ViewportCameraAreaGatherer(const Qt3DCore::QNodeId &nodeId = Qt3DCore::QNodeId()) : m_targetCamera(nodeId) { } - QVector<ViewportCameraAreaTriplet> gather(FrameGraphNode *root); + QVector<ViewportCameraAreaDetails> gather(FrameGraphNode *root); private: Qt3DCore::QNodeId m_targetCamera; QVector<FrameGraphNode *> m_leaves; void visit(FrameGraphNode *node); - ViewportCameraAreaTriplet gatherUpViewportCameraAreas(Render::FrameGraphNode *node) const; - bool isUnique(const QVector<ViewportCameraAreaTriplet> &vcaTriplets, const ViewportCameraAreaTriplet &vca) const; + ViewportCameraAreaDetails gatherUpViewportCameraAreas(Render::FrameGraphNode *node) const; + bool isUnique(const QVector<ViewportCameraAreaDetails> &vcaList, const ViewportCameraAreaDetails &vca) const; }; class Q_AUTOTEST_EXPORT EntityGatherer diff --git a/src/render/jobs/raycastingjob.cpp b/src/render/jobs/raycastingjob.cpp index c9fe5cac0..0fbaed219 100644 --- a/src/render/jobs/raycastingjob.cpp +++ b/src/render/jobs/raycastingjob.cpp @@ -148,19 +148,24 @@ bool RayCastingJob::runHelper() const EntityCasterGatherer::EntityCasterList &entities = gatherer.result(); PickingUtils::ViewportCameraAreaGatherer vcaGatherer; - const QVector<PickingUtils::ViewportCameraAreaTriplet> vcaTriplets = vcaGatherer.gather(m_frameGraphRoot); + const QVector<PickingUtils::ViewportCameraAreaDetails> vcaDetails = vcaGatherer.gather(m_frameGraphRoot); for (const EntityCasterGatherer::EntityCasterList::value_type &pair: entities) { QVector<QRay3D> rays; switch (pair.second->type()) { case QAbstractRayCasterPrivate::WorldSpaceRayCaster: - rays << QRay3D(pair.second->origin(), pair.second->direction(), pair.second->length()); + rays << QRay3D(Vector3D(pair.second->origin()), + Vector3D(pair.second->direction()), + pair.second->length()); rays.back().transform(*pair.first->worldTransform()); break; case QAbstractRayCasterPrivate::ScreenScapeRayCaster: - for (const PickingUtils::ViewportCameraAreaTriplet &vca : vcaTriplets) - rays << rayForViewportAndCamera(vca.area, pair.second->position(), vca.viewport, vca.cameraId); + for (const PickingUtils::ViewportCameraAreaDetails &vca : vcaDetails) { + // TODO: Fix this properly by not passing null for the eventSource + rays << rayForViewportAndCamera(vca, nullptr, pair.second->position()); + //rays << rayForViewportAndCamera(vca.area, pair.second->position(), vca.viewport, vca.cameraId); + } break; default: Q_UNREACHABLE(); @@ -216,7 +221,7 @@ void RayCastingJob::dispatchHits(RayCaster *rayCaster, const PickingUtils::HitLi QAbstractRayCaster::Hits hits; for (const PickingUtils::HitList::value_type &sphereHit: sphereHits) { Entity *entity = m_manager->renderNodesManager()->lookupResource(sphereHit.m_entityId); - QVector3D localIntersection = sphereHit.m_intersection; + Vector3D localIntersection = sphereHit.m_intersection; if (entity && entity->worldTransform()) localIntersection = entity->worldTransform()->inverted() * localIntersection; @@ -240,8 +245,8 @@ void RayCastingJob::dispatchHits(RayCaster *rayCaster, const PickingUtils::HitLi hitType, sphereHit.m_entityId, sphereHit.m_distance, - localIntersection, - sphereHit.m_intersection, + convertToQVector3D(localIntersection), + convertToQVector3D(sphereHit.m_intersection), sphereHit.m_primitiveIndex, sphereHit.m_vertexIndex[0], sphereHit.m_vertexIndex[1], diff --git a/src/render/jobs/renderviewjobutils_p.h b/src/render/jobs/renderviewjobutils_p.h index 15f3bb71c..468a95bfd 100644 --- a/src/render/jobs/renderviewjobutils_p.h +++ b/src/render/jobs/renderviewjobutils_p.h @@ -58,6 +58,7 @@ #include <QMatrix4x4> #include <Qt3DRender/private/uniform_p.h> #include <Qt3DRender/private/handle_types_p.h> +#include <Qt3DRender/private/aligned_malloc_p.h> QT_BEGIN_NAMESPACE @@ -160,6 +161,8 @@ struct Q_AUTOTEST_EXPORT UniformBlockValueBuilder UniformBlockValueBuilder(); ~UniformBlockValueBuilder(); + QT3D_ALIGNED_MALLOC_AND_FREE() + void buildActiveUniformNameValueMapHelper(ShaderData *currentShaderData, const QString &blockName, const QString &qmlPropertyName, @@ -173,7 +176,7 @@ struct Q_AUTOTEST_EXPORT UniformBlockValueBuilder UniformBlockValueBuilderHash activeUniformNamesToValue; ShaderDataManager *shaderDataManager; TextureManager *textureManager; - QMatrix4x4 viewMatrix; + Matrix4x4 viewMatrix; }; } // namespace Render diff --git a/src/render/jobs/updatelevelofdetailjob.cpp b/src/render/jobs/updatelevelofdetailjob.cpp index 8b604229a..141d65c22 100644 --- a/src/render/jobs/updatelevelofdetailjob.cpp +++ b/src/render/jobs/updatelevelofdetailjob.cpp @@ -140,20 +140,20 @@ void UpdateLevelOfDetailJob::updateEntityLod(Entity *entity) void UpdateLevelOfDetailJob::updateEntityLodByDistance(Entity *entity, LevelOfDetail *lod) { - QMatrix4x4 viewMatrix; - QMatrix4x4 projectionMatrix; + Matrix4x4 viewMatrix; + Matrix4x4 projectionMatrix; if (!Render::CameraLens::viewMatrixForCamera(m_manager->renderNodesManager(), lod->camera(), viewMatrix, projectionMatrix)) return; const QVector<qreal> thresholds = lod->thresholds(); - QVector3D center = lod->center(); + Vector3D center(lod->center()); if (lod->hasBoundingVolumeOverride() || entity->worldBoundingVolume() == nullptr) { center = *entity->worldTransform() * center; } else { center = entity->worldBoundingVolume()->center(); } - const QVector3D tcenter = viewMatrix * center; + const Vector3D tcenter = viewMatrix * center; const float dist = tcenter.length(); const int n = thresholds.size(); for (int i=0; i<n; ++i) { @@ -169,20 +169,20 @@ void UpdateLevelOfDetailJob::updateEntityLodByDistance(Entity *entity, LevelOfDe void UpdateLevelOfDetailJob::updateEntityLodByScreenArea(Entity *entity, LevelOfDetail *lod) { - QMatrix4x4 viewMatrix; - QMatrix4x4 projectionMatrix; + Matrix4x4 viewMatrix; + Matrix4x4 projectionMatrix; if (!Render::CameraLens::viewMatrixForCamera(m_manager->renderNodesManager(), lod->camera(), viewMatrix, projectionMatrix)) return; PickingUtils::ViewportCameraAreaGatherer vcaGatherer(lod->camera()); - const QVector<PickingUtils::ViewportCameraAreaTriplet> vcaTriplets = vcaGatherer.gather(m_frameGraphRoot); + const QVector<PickingUtils::ViewportCameraAreaDetails> vcaTriplets = vcaGatherer.gather(m_frameGraphRoot); if (vcaTriplets.isEmpty()) return; - const PickingUtils::ViewportCameraAreaTriplet &vca = vcaTriplets.front(); + const PickingUtils::ViewportCameraAreaDetails &vca = vcaTriplets.front(); const QVector<qreal> thresholds = lod->thresholds(); - Sphere bv(lod->center(), lod->radius()); + Sphere bv(Vector3D(lod->center()), lod->radius()); if (!lod->hasBoundingVolumeOverride() && entity->worldBoundingVolume() != nullptr) { bv = *(entity->worldBoundingVolume()); } else { diff --git a/src/render/jobs/updatelevelofdetailjob_p.h b/src/render/jobs/updatelevelofdetailjob_p.h index 02967458b..4c80a3205 100644 --- a/src/render/jobs/updatelevelofdetailjob_p.h +++ b/src/render/jobs/updatelevelofdetailjob_p.h @@ -84,6 +84,7 @@ private: void updateEntityLod(Entity *entity); void updateEntityLodByDistance(Entity *entity, LevelOfDetail *lod); void updateEntityLodByScreenArea(Entity *entity, LevelOfDetail *lod); + QRect windowViewport(const QSize &area, const QRectF &relativeViewport) const; NodeManagers *m_manager; diff --git a/src/render/jobs/updateworldtransformjob.cpp b/src/render/jobs/updateworldtransformjob.cpp index 8b11cd309..c56ed8507 100644 --- a/src/render/jobs/updateworldtransformjob.cpp +++ b/src/render/jobs/updateworldtransformjob.cpp @@ -54,9 +54,9 @@ namespace Render { namespace { -void updateWorldTransformAndBounds(Qt3DRender::Render::Entity *node, const QMatrix4x4 &parentTransform) +void updateWorldTransformAndBounds(Qt3DRender::Render::Entity *node, const Matrix4x4 &parentTransform) { - QMatrix4x4 worldTransform(parentTransform); + Matrix4x4 worldTransform(parentTransform); Transform *nodeTransform = node->renderComponent<Transform>(); if (nodeTransform != nullptr && nodeTransform->isEnabled()) @@ -94,7 +94,7 @@ void UpdateWorldTransformJob::run() qCDebug(Jobs) << "Entering" << Q_FUNC_INFO << QThread::currentThread(); - QMatrix4x4 parentTransform; + Matrix4x4 parentTransform; Entity *parent = m_node->parent(); if (parent != nullptr) parentTransform = *(parent->worldTransform()); diff --git a/src/render/materialsystem/qparameter.cpp b/src/render/materialsystem/qparameter.cpp index b9bfa44e7..2b2dd29d5 100644 --- a/src/render/materialsystem/qparameter.cpp +++ b/src/render/materialsystem/qparameter.cpp @@ -179,13 +179,30 @@ QParameterPrivate::QParameterPrivate() { } +namespace { + +/*! \internal */ +inline QVariant toBackendValue(const QVariant &v) +{ + if (auto nodeValue = v.value<Qt3DCore::QNode*>()) + return QVariant::fromValue(nodeValue->id()); + return v; +} + +} // anonymous + void QParameterPrivate::setValue(const QVariant &v) { - Qt3DCore::QNode *nodeValue = v.value<Qt3DCore::QNode *>(); - if (nodeValue != nullptr) - m_backendValue = QVariant::fromValue(nodeValue->id()); - else - m_backendValue = v; + if (v.type() == QVariant::List) { + QSequentialIterable iterable = v.value<QSequentialIterable>(); + QVariantList variants; + variants.reserve(iterable.size()); + for (const auto &v : iterable) + variants.append(toBackendValue(v)); + m_backendValue = variants; + } else { + m_backendValue = toBackendValue(v); + } m_value = v; } diff --git a/src/render/materialsystem/shadercache.cpp b/src/render/materialsystem/shadercache.cpp index 4ddf26799..ce29622ad 100644 --- a/src/render/materialsystem/shadercache.cpp +++ b/src/render/materialsystem/shadercache.cpp @@ -62,18 +62,28 @@ ShaderCache::~ShaderCache() * * \return A pointer to the shader program if it is cached, nullptr otherwise */ -QOpenGLShaderProgram *ShaderCache::getShaderProgramAndAddRef(ProgramDNA dna, Qt3DCore::QNodeId shaderPeerId) +QOpenGLShaderProgram *ShaderCache::getShaderProgramAndAddRef(ProgramDNA dna, Qt3DCore::QNodeId shaderPeerId, bool *wasPresent) { - auto shaderProgram = m_programHash.value(dna, nullptr); - if (shaderProgram) { + auto shaderProgram = m_programHash.constFind(dna); + + // Some callers may wish to differentiate between a result of null due to + // not having anything in the cache and a result of null due to the cache + // containing a program the shaders of which failed to compile. + if (wasPresent) + *wasPresent = shaderProgram != m_programHash.constEnd(); + + if (shaderProgram != m_programHash.constEnd()) { // Ensure we store the fact that shaderPeerId references this shader QMutexLocker lock(&m_refsMutex); QVector<Qt3DCore::QNodeId> &programRefs = m_programRefs[dna]; auto it = std::lower_bound(programRefs.begin(), programRefs.end(), shaderPeerId); if (*it != shaderPeerId) programRefs.insert(it, shaderPeerId); + + return *shaderProgram; } - return shaderProgram; + + return nullptr; } /*! diff --git a/src/render/materialsystem/shadercache_p.h b/src/render/materialsystem/shadercache_p.h index 24a55876e..bda629ee5 100644 --- a/src/render/materialsystem/shadercache_p.h +++ b/src/render/materialsystem/shadercache_p.h @@ -71,7 +71,7 @@ class QT3DRENDERSHARED_PRIVATE_EXPORT ShaderCache public: ~ShaderCache(); - QOpenGLShaderProgram *getShaderProgramAndAddRef(ProgramDNA dna, Qt3DCore::QNodeId shaderPeerId); + QOpenGLShaderProgram *getShaderProgramAndAddRef(ProgramDNA dna, Qt3DCore::QNodeId shaderPeerId, bool *wasPresent = nullptr); void insert(ProgramDNA dna, Qt3DCore::QNodeId shaderPeerId, QOpenGLShaderProgram *program); void removeRef(ProgramDNA dna, Qt3DCore::QNodeId shaderPeerId); void purge(); diff --git a/src/render/materialsystem/shaderdata.cpp b/src/render/materialsystem/shaderdata.cpp index fec1e66ac..de423c3c2 100644 --- a/src/render/materialsystem/shaderdata.cpp +++ b/src/render/materialsystem/shaderdata.cpp @@ -171,7 +171,7 @@ void ShaderData::cleanup(NodeManagers *managers) m_updatedShaderData.clear(); } -QVariant ShaderData::getTransformedProperty(const QString &name, const QMatrix4x4 &viewMatrix) +QVariant ShaderData::getTransformedProperty(const QString &name, const Matrix4x4 &viewMatrix) { // Note protecting m_worldMatrix at this point as we assume all world updates // have been performed when reaching this point @@ -180,11 +180,11 @@ QVariant ShaderData::getTransformedProperty(const QString &name, const QMatrix4x const TransformType transformType = it.value(); switch (transformType) { case ModelToEye: - return QVariant::fromValue(viewMatrix * m_worldMatrix * m_originalProperties.value(name).value<QVector3D>()); + return QVariant::fromValue(viewMatrix * m_worldMatrix * Vector3D(m_originalProperties.value(name).value<QVector3D>())); case ModelToWorld: - return QVariant::fromValue(m_worldMatrix * m_originalProperties.value(it.key()).value<QVector3D>()); + return QVariant::fromValue(m_worldMatrix * Vector3D(m_originalProperties.value(it.key()).value<QVector3D>())); case ModelToWorldDirection: - return QVariant::fromValue((m_worldMatrix * QVector4D(m_originalProperties.value(it.key()).value<QVector3D>(), 0.0f)).toVector3D()); + return QVariant::fromValue(Vector3D(m_worldMatrix * Vector4D(m_originalProperties.value(it.key()).value<QVector3D>(), 0.0f))); case NoTransform: break; } @@ -193,7 +193,7 @@ QVariant ShaderData::getTransformedProperty(const QString &name, const QMatrix4x } // Called by FramePreparationJob or by RenderView when dealing with lights -void ShaderData::updateWorldTransform(const QMatrix4x4 &worldMatrix) +void ShaderData::updateWorldTransform(const Matrix4x4 &worldMatrix) { QMutexLocker lock(&m_mutex); if (m_worldMatrix != worldMatrix) { diff --git a/src/render/materialsystem/shaderdata_p.h b/src/render/materialsystem/shaderdata_p.h index 168335f63..f9c3ecc79 100644 --- a/src/render/materialsystem/shaderdata_p.h +++ b/src/render/materialsystem/shaderdata_p.h @@ -55,7 +55,7 @@ #include <Qt3DRender/private/shadervariables_p.h> #include <Qt3DRender/qshaderdata.h> #include <QMutex> -#include <QMatrix4x4> +#include <Qt3DCore/private/matrix4x4_p.h> QT_BEGIN_NAMESPACE @@ -83,13 +83,13 @@ public: QHash<QString, QVariant> properties() const { return m_originalProperties; } // Called by FramePreparationJob - void updateWorldTransform(const QMatrix4x4 &worldMatrix); + void updateWorldTransform(const Matrix4x4 &worldMatrix); // Call by RenderViewJob void markDirty(); TransformType propertyTransformType(const QString &name) const; - QVariant getTransformedProperty(const QString &name, const QMatrix4x4 &viewMatrix); + QVariant getTransformedProperty(const QString &name, const Matrix4x4 &viewMatrix); // Called by FrameCleanupJob static void cleanup(NodeManagers *managers); @@ -114,8 +114,8 @@ protected: QMutex m_mutex; static QVector<Qt3DCore::QNodeId> m_updatedShaderData; - QMatrix4x4 m_worldMatrix; - QMatrix4x4 m_viewMatrix; + Matrix4x4 m_worldMatrix; + Matrix4x4 m_viewMatrix; NodeManagers *m_managers; void clearUpdatedProperties(); diff --git a/src/render/picking/pickeventfilter.cpp b/src/render/picking/pickeventfilter.cpp index 297911e45..b10383c72 100644 --- a/src/render/picking/pickeventfilter.cpp +++ b/src/render/picking/pickeventfilter.cpp @@ -62,10 +62,10 @@ PickEventFilter::~PickEventFilter() Called from a worker thread in the thread pool so be sure to mutex protect the data. */ -QList<QMouseEvent> PickEventFilter::pendingMouseEvents() +QList<QPair<QObject *, QMouseEvent> > PickEventFilter::pendingMouseEvents() { QMutexLocker locker(&m_mutex); - QList<QMouseEvent> pendingEvents(m_pendingMouseEvents); + QList<QPair<QObject*, QMouseEvent>> pendingEvents(m_pendingMouseEvents); m_pendingMouseEvents.clear(); return pendingEvents; } @@ -90,14 +90,14 @@ bool PickEventFilter::eventFilter(QObject *obj, QEvent *e) case QEvent::MouseButtonRelease: case QEvent::MouseMove: { QMutexLocker locker(&m_mutex); - m_pendingMouseEvents.push_back(QMouseEvent(*static_cast<QMouseEvent *>(e))); + m_pendingMouseEvents.push_back({obj, QMouseEvent(*static_cast<QMouseEvent *>(e))}); } break; case QEvent::HoverMove: { QMutexLocker locker(&m_mutex); QHoverEvent *he = static_cast<QHoverEvent *>(e); - m_pendingMouseEvents.push_back(QMouseEvent(QEvent::MouseMove, + m_pendingMouseEvents.push_back({obj, QMouseEvent(QEvent::MouseMove, he->pos(), Qt::NoButton, Qt::NoButton, - he->modifiers())); + he->modifiers())}); } break; case QEvent::KeyPress: case QEvent::KeyRelease: { diff --git a/src/render/picking/pickeventfilter_p.h b/src/render/picking/pickeventfilter_p.h index c4ede4681..dfd8c1b99 100644 --- a/src/render/picking/pickeventfilter_p.h +++ b/src/render/picking/pickeventfilter_p.h @@ -69,14 +69,14 @@ public: explicit PickEventFilter(QObject *parent = nullptr); ~PickEventFilter(); - QList<QMouseEvent> pendingMouseEvents(); + QList<QPair<QObject*, QMouseEvent>> pendingMouseEvents(); QList<QKeyEvent> pendingKeyEvents(); protected: bool eventFilter(QObject *obj, QEvent *e) final; private: - QList<QMouseEvent> m_pendingMouseEvents; + QList<QPair<QObject*, QMouseEvent>> m_pendingMouseEvents; QList<QKeyEvent> m_pendingKeyEvents; QMutex m_mutex; }; diff --git a/src/render/raycasting/boundingsphere_p.h b/src/render/raycasting/boundingsphere_p.h index 63bd8a562..bcffbaa19 100644 --- a/src/render/raycasting/boundingsphere_p.h +++ b/src/render/raycasting/boundingsphere_p.h @@ -53,6 +53,7 @@ #include <Qt3DRender/qt3drender_global.h> #include <Qt3DRender/private/qboundingvolume_p.h> +#include <Qt3DCore/private/vector3d_p.h> QT_BEGIN_NAMESPACE @@ -65,7 +66,7 @@ public: BoundingSphere(); ~BoundingSphere(); - virtual QVector3D center() const = 0; + virtual Vector3D center() const = 0; virtual float radius() const = 0; }; diff --git a/src/render/raycasting/qabstractcollisionqueryservice.cpp b/src/render/raycasting/qabstractcollisionqueryservice.cpp index 993ad840e..5148df911 100644 --- a/src/render/raycasting/qabstractcollisionqueryservice.cpp +++ b/src/render/raycasting/qabstractcollisionqueryservice.cpp @@ -62,8 +62,8 @@ void QAbstractCollisionQueryService::setResultHandle(QCollisionQueryResult &resu } void QAbstractCollisionQueryService::addEntityHit(QCollisionQueryResult &result, Qt3DCore::QNodeId entity, - const QVector3D& intersection, float distance, - const QVector3D& uvw) + const Vector3D& intersection, float distance, + const Vector3D& uvw) { result.d_func()->addEntityHit(entity, intersection, distance, uvw); } diff --git a/src/render/raycasting/qabstractcollisionqueryservice_p.h b/src/render/raycasting/qabstractcollisionqueryservice_p.h index 1c1261937..fa35792d0 100644 --- a/src/render/raycasting/qabstractcollisionqueryservice_p.h +++ b/src/render/raycasting/qabstractcollisionqueryservice_p.h @@ -97,8 +97,8 @@ protected: QAbstractCollisionQueryService(QAbstractCollisionQueryServicePrivate &dd); void setResultHandle(QCollisionQueryResult &result, const QQueryHandle &handle); - void addEntityHit(QCollisionQueryResult &result, Qt3DCore::QNodeId entity, const QVector3D &intersection, - float distance, const QVector3D &uvw); + void addEntityHit(QCollisionQueryResult &result, Qt3DCore::QNodeId entity, const Vector3D &intersection, + float distance, const Vector3D &uvw); private: Q_DECLARE_PRIVATE(QAbstractCollisionQueryService) diff --git a/src/render/raycasting/qboundingvolume_p.h b/src/render/raycasting/qboundingvolume_p.h index 8267c2b18..b63463f23 100644 --- a/src/render/raycasting/qboundingvolume_p.h +++ b/src/render/raycasting/qboundingvolume_p.h @@ -53,6 +53,7 @@ #include <Qt3DRender/qt3drender_global.h> #include <Qt3DCore/qnodeid.h> +#include <Qt3DCore/private/vector3d_p.h> QT_BEGIN_NAMESPACE namespace Qt3DRender { @@ -72,8 +73,8 @@ public: }; virtual Qt3DCore::QNodeId id() const = 0; - virtual bool intersects(const QRay3D &ray, QVector3D *q = nullptr, - QVector3D *uvw = nullptr) const = 0; + virtual bool intersects(const QRay3D &ray, Vector3D *q = nullptr, + Vector3D *uvw = nullptr) const = 0; virtual Type type() const = 0; }; diff --git a/src/render/raycasting/qcollisionqueryresult.cpp b/src/render/raycasting/qcollisionqueryresult.cpp index 62975200c..9d1e484b6 100644 --- a/src/render/raycasting/qcollisionqueryresult.cpp +++ b/src/render/raycasting/qcollisionqueryresult.cpp @@ -56,8 +56,8 @@ QCollisionQueryResultPrivate::QCollisionQueryResultPrivate(const QCollisionQuery { } -void QCollisionQueryResultPrivate::addEntityHit(Qt3DCore::QNodeId entity, const QVector3D& intersection, - float distance, const QVector3D& uvw) +void QCollisionQueryResultPrivate::addEntityHit(Qt3DCore::QNodeId entity, const Vector3D& intersection, + float distance, const Vector3D& uvw) { m_hits.append(QCollisionQueryResult::Hit(entity, intersection, distance, uvw)); } diff --git a/src/render/raycasting/qcollisionqueryresult_p.h b/src/render/raycasting/qcollisionqueryresult_p.h index 1a430e019..24371d30e 100644 --- a/src/render/raycasting/qcollisionqueryresult_p.h +++ b/src/render/raycasting/qcollisionqueryresult_p.h @@ -53,8 +53,8 @@ #include <Qt3DRender/qt3drender_global.h> #include <Qt3DCore/qnodeid.h> +#include <Qt3DCore/private/vector3d_p.h> #include <QVector> -#include <QVector3D> #include <QSharedData> QT_BEGIN_NAMESPACE @@ -84,7 +84,7 @@ public: m_vertexIndex[0] = m_vertexIndex[1] = m_vertexIndex[2] = 0; } - Hit(Qt3DCore::QNodeId entity, const QVector3D &intersection, float distance, const QVector3D &uvw) + Hit(Qt3DCore::QNodeId entity, const Vector3D &intersection, float distance, const Vector3D &uvw) : m_entityId(entity) , m_intersection(intersection) , m_distance(distance) @@ -94,11 +94,11 @@ public: Qt3DCore::QNodeId m_entityId; HitType m_type; - QVector3D m_intersection; + Vector3D m_intersection; float m_distance; uint m_primitiveIndex; uint m_vertexIndex[3]; - QVector3D m_uvw; + Vector3D m_uvw; }; QCollisionQueryResult(); @@ -146,8 +146,8 @@ public: explicit QCollisionQueryResultPrivate(const QCollisionQueryResultPrivate ©); void setHandle(const QQueryHandle &handle); - void addEntityHit(Qt3DCore::QNodeId entity, const QVector3D& intersection, float distance, - const QVector3D& uvw); + void addEntityHit(Qt3DCore::QNodeId entity, const Vector3D& intersection, float distance, + const Vector3D& uvw); QQueryHandle m_handle; QVector<QCollisionQueryResult::Hit> m_hits; diff --git a/src/render/raycasting/qray3d.cpp b/src/render/raycasting/qray3d.cpp index 3f136deb8..40d16bc73 100644 --- a/src/render/raycasting/qray3d.cpp +++ b/src/render/raycasting/qray3d.cpp @@ -93,7 +93,7 @@ QRay3D::QRay3D() QRay3D thruAB(pointA, pointB - pointA); \endcode */ -QRay3D::QRay3D(const QVector3D &origin, const QVector3D &direction, float distance) +QRay3D::QRay3D(const Vector3D &origin, const Vector3D &direction, float distance) : m_origin(origin) , m_direction(direction) , m_distance(distance) @@ -110,7 +110,7 @@ QRay3D::~QRay3D() \sa setOrigin(), direction() */ -QVector3D QRay3D::origin() const +Vector3D QRay3D::origin() const { return m_origin; } @@ -122,7 +122,7 @@ QVector3D QRay3D::origin() const \sa origin(), setDirection() */ -void QRay3D::setOrigin(const QVector3D &value) +void QRay3D::setOrigin(const Vector3D &value) { m_origin = value; } @@ -134,7 +134,7 @@ void QRay3D::setOrigin(const QVector3D &value) \sa setDirection(), origin() */ -QVector3D QRay3D::direction() const +Vector3D QRay3D::direction() const { return m_direction; } @@ -146,7 +146,7 @@ QVector3D QRay3D::direction() const \sa direction(), setOrigin() */ -void QRay3D::setDirection(const QVector3D &value) +void QRay3D::setDirection(const Vector3D &value) { if (value.isNull()) return; @@ -164,12 +164,12 @@ void QRay3D::setDistance(float distance) m_distance = distance; } -QVector3D QRay3D::point(float t) const +Vector3D QRay3D::point(float t) const { return m_origin + t * m_direction; } -QRay3D &QRay3D::transform(const QMatrix4x4 &matrix) +QRay3D &QRay3D::transform(const Matrix4x4 &matrix) { m_origin = matrix * m_origin; m_direction = matrix.mapVector(m_direction); @@ -177,7 +177,7 @@ QRay3D &QRay3D::transform(const QMatrix4x4 &matrix) return *this; } -QRay3D QRay3D::transformed(const QMatrix4x4 &matrix) const +QRay3D QRay3D::transformed(const Matrix4x4 &matrix) const { return QRay3D(matrix * m_origin, matrix.mapVector(m_direction)); } @@ -195,12 +195,12 @@ bool QRay3D::operator!=(const QRay3D &other) const /*! Returns true if \a point lies on this ray; false otherwise. */ -bool QRay3D::contains(const QVector3D &point) const +bool QRay3D::contains(const Vector3D &point) const { - QVector3D ppVec(point - m_origin); + Vector3D ppVec(point - m_origin); if (ppVec.isNull()) // point coincides with origin return true; - const float dot = QVector3D::dotProduct(ppVec, m_direction); + const float dot = Vector3D ::dotProduct(ppVec, m_direction); if (qFuzzyIsNull(dot)) return false; return qFuzzyCompare(dot*dot, ppVec.lengthSquared() * m_direction.lengthSquared()); @@ -213,7 +213,7 @@ bool QRay3D::contains(const QVector3D &point) const */ bool QRay3D::contains(const QRay3D &ray) const { - const float dot = QVector3D::dotProduct(m_direction, ray.direction()); + const float dot = Vector3D ::dotProduct(m_direction, ray.direction()); if (!qFuzzyCompare(dot*dot, m_direction.lengthSquared() * ray.direction().lengthSquared())) return false; return contains(ray.origin()); @@ -247,11 +247,11 @@ bool QRay3D::contains(const QRay3D &ray) const \sa point(), project() */ -float QRay3D::projectedDistance(const QVector3D &point) const +float QRay3D::projectedDistance(const Vector3D &point) const { Q_ASSERT(!m_direction.isNull()); - return QVector3D::dotProduct(point - m_origin, m_direction) / + return Vector3D ::dotProduct(point - m_origin, m_direction) / m_direction.lengthSquared(); } @@ -264,10 +264,10 @@ float QRay3D::projectedDistance(const QVector3D &point) const \sa projectedDistance() */ -QVector3D QRay3D::project(const QVector3D &vector) const +Vector3D QRay3D::project(const Vector3D &vector) const { - QVector3D norm = m_direction.normalized(); - return QVector3D::dotProduct(vector, norm) * norm; + Vector3D norm = m_direction.normalized(); + return Vector3D ::dotProduct(vector, norm) * norm; } /*! @@ -277,7 +277,7 @@ QVector3D QRay3D::project(const QVector3D &vector) const \sa point() */ -float QRay3D::distance(const QVector3D &point) const +float QRay3D::distance(const Vector3D &point) const { float t = projectedDistance(point); return (point - (m_origin + t * m_direction)).length(); @@ -350,8 +350,8 @@ QDebug operator<<(QDebug dbg, const QRay3D &ray) */ QDataStream &operator<<(QDataStream &stream, const QRay3D &ray) { - stream << ray.origin(); - stream << ray.direction(); + stream << convertToQVector3D(ray.origin()); + stream << convertToQVector3D(ray.direction()); return stream; } @@ -364,9 +364,10 @@ QDataStream &operator<<(QDataStream &stream, const QRay3D &ray) QDataStream &operator>>(QDataStream &stream, QRay3D &ray) { QVector3D origin, direction; + stream >> origin; stream >> direction; - ray = QRay3D(origin, direction); + ray = QRay3D(Vector3D(origin), Vector3D(direction)); return stream; } diff --git a/src/render/raycasting/qray3d_p.h b/src/render/raycasting/qray3d_p.h index 7c1156b76..8b7852cc3 100644 --- a/src/render/raycasting/qray3d_p.h +++ b/src/render/raycasting/qray3d_p.h @@ -53,8 +53,8 @@ // #include <Qt3DRender/qt3drender_global.h> -#include <QtGui/qvector3d.h> -#include <QtGui/qmatrix4x4.h> +#include <Qt3DCore/private/matrix4x4_p.h> +#include <Qt3DCore/private/vector3d_p.h> QT_BEGIN_NAMESPACE @@ -65,37 +65,39 @@ class QT3DRENDERSHARED_EXPORT QRay3D { public: QRay3D(); - explicit QRay3D(const QVector3D &origin, const QVector3D &direction = QVector3D(0.0f, 0.0f, 1.0f), float distance = 1.0f); + explicit QRay3D(const Vector3D &origin, const Vector3D &direction = Vector3D(0.0f, 0.0f, 1.0f), float distance = 1.0f); ~QRay3D(); - QVector3D origin() const; - void setOrigin(const QVector3D &value); + Vector3D origin() const; + void setOrigin(const Vector3D &value); - QVector3D direction() const; - void setDirection(const QVector3D &value); + Vector3D direction() const; + void setDirection(const Vector3D &value); float distance() const; void setDistance(float distance); - bool contains(const QVector3D &point) const; + bool contains(const Vector3D &point) const; bool contains(const QRay3D &ray) const; - QVector3D point(float t) const; - float projectedDistance(const QVector3D &point) const; + Vector3D point(float t) const; + float projectedDistance(const Vector3D &point) const; - QVector3D project(const QVector3D &vector) const; + Vector3D project(const Vector3D &vector) const; - float distance(const QVector3D &point) const; + float distance(const Vector3D &point) const; - QRay3D &transform(const QMatrix4x4 &matrix); - QRay3D transformed(const QMatrix4x4 &matrix) const; + QRay3D &transform(const Matrix4x4 &matrix); + QRay3D transformed(const Matrix4x4 &matrix) const; bool operator==(const QRay3D &other) const; bool operator!=(const QRay3D &other) const; + bool isValid() const { return !m_direction.isNull() && !qFuzzyIsNull(m_distance); } + private: - QVector3D m_origin; - QVector3D m_direction; + Vector3D m_origin; + Vector3D m_direction; float m_distance; }; QT3D_DECLARE_TYPEINFO_2(Qt3DRender, RayCasting, QRay3D, Q_MOVABLE_TYPE) diff --git a/src/render/raycasting/qraycastingservice.cpp b/src/render/raycasting/qraycastingservice.cpp index e0c7b6199..8debeac6a 100644 --- a/src/render/raycasting/qraycastingservice.cpp +++ b/src/render/raycasting/qraycastingservice.cpp @@ -67,8 +67,8 @@ struct Hit bool intersects; float distance; Qt3DCore::QNodeId id; - QVector3D intersection; - QVector3D uvw; + Vector3D intersection; + Vector3D uvw; }; bool compareHitsDistance(const Hit &a, const Hit &b) diff --git a/src/render/render.pro b/src/render/render.pro index 29110abea..3929cb121 100644 --- a/src/render/render.pro +++ b/src/render/render.pro @@ -28,10 +28,21 @@ gcov { QMAKE_LFLAGS += -fprofile-arcs -ftest-coverage } +qtConfig(qt3d-simd-avx2) { + CONFIG += simd + QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_AVX2 +} + +qtConfig(qt3d-simd-sse2):!qtConfig(qt3d-simd-avx2) { + CONFIG += simd + QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_SSE2 +} + HEADERS += \ renderlogging_p.h \ qt3drender_global.h \ - qt3drender_global_p.h + qt3drender_global_p.h \ + aligned_malloc_p.h SOURCES += \ renderlogging.cpp diff --git a/src/render/services/vsyncframeadvanceservice.cpp b/src/render/services/vsyncframeadvanceservice.cpp index 8749a54ab..c8437e20d 100644 --- a/src/render/services/vsyncframeadvanceservice.cpp +++ b/src/render/services/vsyncframeadvanceservice.cpp @@ -89,7 +89,7 @@ qint64 VSyncFrameAdvanceService::waitForNextFrame() if (d->m_drivenByRenderThread) d->m_semaphore.acquire(1); else - d->m_semaphore.acquire(d->m_semaphore.available() + 1); + d->m_semaphore.acquire(d->m_semaphore.available()); const quint64 currentTime = d->m_elapsed.nsecsElapsed(); qCDebug(VSyncAdvanceService) << "Elapsed nsecs since last call " << currentTime - d->m_elapsedTimeSincePreviousFrame; diff --git a/tests/auto/core/common/common.pri b/tests/auto/core/common/common.pri index 3a85df875..9b761b8e0 100644 --- a/tests/auto/core/common/common.pri +++ b/tests/auto/core/common/common.pri @@ -15,3 +15,13 @@ qtConfig(private_tests) { } QT += core-private 3dcore 3dcore-private + +qtConfig(qt3d-simd-avx2) { + CONFIG += simd + QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_AVX2 +} + +qtConfig(qt3d-simd-sse2):!qtConfig(qt3d-simd-avx2) { + CONFIG += simd + QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_SSE2 +} diff --git a/tests/auto/core/matrix4x4_avx2/matrix4x4_avx2.pro b/tests/auto/core/matrix4x4_avx2/matrix4x4_avx2.pro index 4a97ab2a9..4db8a1975 100644 --- a/tests/auto/core/matrix4x4_avx2/matrix4x4_avx2.pro +++ b/tests/auto/core/matrix4x4_avx2/matrix4x4_avx2.pro @@ -1,6 +1,6 @@ TARGET = tst_matrix4x4_avx2 CONFIG += testcase -QT += testlib 3dcore 3dcore-private +QT += testlib 3dcore 3dcore-private 3drender-private QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_AVX2 diff --git a/tests/auto/core/matrix4x4_avx2/tst_matrix4x4_avx2.cpp b/tests/auto/core/matrix4x4_avx2/tst_matrix4x4_avx2.cpp index 41b0c535c..144df6711 100644 --- a/tests/auto/core/matrix4x4_avx2/tst_matrix4x4_avx2.cpp +++ b/tests/auto/core/matrix4x4_avx2/tst_matrix4x4_avx2.cpp @@ -28,12 +28,15 @@ #include <QtTest/QtTest> #include <Qt3DCore/private/matrix4x4_avx2_p.h> +#include <Qt3DRender/private/aligned_malloc_p.h> using namespace Qt3DCore; class tst_Matrix4x4_AVX2: public QObject { Q_OBJECT +public: + QT3D_ALIGNED_MALLOC_AND_FREE() private Q_SLOTS: diff --git a/tests/auto/core/nodes/tst_nodes.cpp b/tests/auto/core/nodes/tst_nodes.cpp index 2e73e6c34..baf7010b0 100644 --- a/tests/auto/core/nodes/tst_nodes.cpp +++ b/tests/auto/core/nodes/tst_nodes.cpp @@ -1041,15 +1041,22 @@ void tst_Nodes::appendingParentlessComponentToEntity() // return early in such a case. // Check that we received ComponentAdded - for (const auto event: { entitySpy.events.takeFirst().change().dynamicCast<Qt3DCore::QComponentAddedChange>(), - componentSpy.events.takeLast().change().dynamicCast<Qt3DCore::QComponentAddedChange>() }) { + const auto event = entitySpy.events.takeFirst().change().dynamicCast<Qt3DCore::QComponentAddedChange>(); QCOMPARE(event->type(), Qt3DCore::ComponentAdded); QCOMPARE(event->subjectId(), entity->id()); QCOMPARE(event->entityId(), entity->id()); QCOMPARE(event->componentId(), comp->id()); QCOMPARE(event->componentMetaObject(), comp->metaObject()); } + { + const auto event = componentSpy.events.takeFirst().change().dynamicCast<Qt3DCore::QComponentAddedChange>(); + QCOMPARE(event->type(), Qt3DCore::ComponentAdded); + QCOMPARE(event->subjectId(), comp->id()); + QCOMPARE(event->entityId(), entity->id()); + QCOMPARE(event->componentId(), comp->id()); + QCOMPARE(event->componentMetaObject(), comp->metaObject()); + } } } @@ -1080,15 +1087,22 @@ void tst_Nodes::appendingComponentToEntity() QVERIFY(comp->parentNode() == entity.data()); QCOMPARE(entitySpy.events.size(), 1); QVERIFY(entitySpy.events.first().wasLocked()); - for (const auto event: { entitySpy.events.takeFirst().change().dynamicCast<Qt3DCore::QComponentAddedChange>(), - componentSpy.events.takeFirst().change().dynamicCast<Qt3DCore::QComponentAddedChange>() }) { + const auto event = entitySpy.events.takeFirst().change().dynamicCast<Qt3DCore::QComponentAddedChange>(); QCOMPARE(event->type(), Qt3DCore::ComponentAdded); QCOMPARE(event->subjectId(), entity->id()); QCOMPARE(event->entityId(), entity->id()); QCOMPARE(event->componentId(), comp->id()); QCOMPARE(event->componentMetaObject(), comp->metaObject()); } + { + const auto event = componentSpy.events.takeFirst().change().dynamicCast<Qt3DCore::QComponentAddedChange>(); + QCOMPARE(event->type(), Qt3DCore::ComponentAdded); + QCOMPARE(event->subjectId(), comp->id()); + QCOMPARE(event->entityId(), entity->id()); + QCOMPARE(event->componentId(), comp->id()); + QCOMPARE(event->componentMetaObject(), comp->metaObject()); + } } } @@ -1123,14 +1137,22 @@ void tst_Nodes::removingComponentFromEntity() QCOMPARE(entitySpy.events.size(), 1); QVERIFY(entitySpy.events.first().wasLocked()); QCOMPARE(componentSpy.events.size(), 1); - for (const auto event: { entitySpy.events.takeFirst().change().dynamicCast<Qt3DCore::QComponentRemovedChange>(), - componentSpy.events.takeFirst().change().dynamicCast<Qt3DCore::QComponentRemovedChange>() }) { + { + const auto event = entitySpy.events.takeFirst().change().dynamicCast<Qt3DCore::QComponentRemovedChange>(); QCOMPARE(event->type(), Qt3DCore::ComponentRemoved); QCOMPARE(event->subjectId(), entity->id()); QCOMPARE(event->entityId(), entity->id()); QCOMPARE(event->componentId(), comp->id()); QCOMPARE(event->componentMetaObject(), comp->metaObject()); } + { + const auto event = componentSpy.events.takeFirst().change().dynamicCast<Qt3DCore::QComponentRemovedChange>(); + QCOMPARE(event->type(), Qt3DCore::ComponentRemoved); + QCOMPARE(event->subjectId(), comp->id()); + QCOMPARE(event->entityId(), entity->id()); + QCOMPARE(event->componentId(), comp->id()); + QCOMPARE(event->componentMetaObject(), comp->metaObject()); + } } } diff --git a/tests/auto/core/vector3d_sse/tst_vector3d_sse.cpp b/tests/auto/core/vector3d_sse/tst_vector3d_sse.cpp index be9fbc347..7ea79a5f5 100644 --- a/tests/auto/core/vector3d_sse/tst_vector3d_sse.cpp +++ b/tests/auto/core/vector3d_sse/tst_vector3d_sse.cpp @@ -668,6 +668,14 @@ private Q_SLOTS: // THEN QVERIFY(v0 == v1); } + { + // GIVEN + Vector3D_SSE v0(6.0f, 6.0f, 6.0f); + Vector3D_SSE v1(6.0f, 6.0f, 6.0f); + + // THEN + QVERIFY(v0 == v1); + } } void checkInequality() @@ -787,11 +795,6 @@ private Q_SLOTS: } } - void checkNormalized() - { - - } - void checkIsNull() { { diff --git a/tests/auto/core/vector4d_sse/tst_vector4d_sse.cpp b/tests/auto/core/vector4d_sse/tst_vector4d_sse.cpp index e7b58c8cf..ed9722ffb 100644 --- a/tests/auto/core/vector4d_sse/tst_vector4d_sse.cpp +++ b/tests/auto/core/vector4d_sse/tst_vector4d_sse.cpp @@ -823,6 +823,98 @@ private Q_SLOTS: QCOMPARE(v0.w(), v1.w()); } } + + void checkLengthSquared() + { + { + // GIVEN + Vector4D_SSE v0(10.0f, 10.0f, 10.0f, 10.0f); + + // THEN + QCOMPARE(v0.lengthSquared(), 400.0f); + } + { + // GIVEN + Vector4D_SSE v0(3.0f, 1.0f, 2.0f, 4.0f); + + // THEN + QCOMPARE(v0.lengthSquared(), 30.0f); + } + } + + void checkLength() + { + { + // GIVEN + Vector4D_SSE v0(3.0f, 0.0f, 0.0f, 0.0f); + + // THEN + QCOMPARE(v0.length(), 3.0f); + } + { + // GIVEN + Vector4D_SSE v0(0.0f, 10.0f, 0.0f, 0.0f); + + // THEN + QCOMPARE(v0.length(), 10.0f); + } + { + // GIVEN + Vector4D_SSE v0(0.0f, 0.0f, 9.0f, 0.0f); + + // THEN + QCOMPARE(v0.length(), 9.0f); + } + { + // GIVEN + Vector4D_SSE v0(0.0f, 0.0f, 0.0f, 8.0f); + + // THEN + QCOMPARE(v0.length(), 8.0f); + } + } + + void checkNormalize() + { + { + // GIVEN + Vector4D_SSE v0(10.0f, 0.0f, 0.0f, 0.0f); + + // WHEN + v0.normalize(); + + // THEN + QCOMPARE(v0, Vector4D_SSE(1.0f, 0.0f, 0.0f, 0.0f)); + } + { + // GIVEN + Vector4D_SSE v0(0.0f, 0.0f, 3.0f, 0.0f); + + // WHEN + v0.normalize(); + + // THEN + QCOMPARE(v0, Vector4D_SSE(0.0, 0.0f, 1.0f, 0.0f)); + } + } + + void checkIsNull() + { + { + // GIVEN + Vector4D_SSE v0; + + // THEN + QVERIFY(v0.isNull()); + } + { + // GIVEN + Vector4D_SSE v0(1.0f, 1.0f, 1.0f, 1.0f); + + // THEN + QVERIFY(!v0.isNull()); + } + } }; QTEST_APPLESS_MAIN(tst_Vector4D_SSE) diff --git a/tests/auto/render/boundingsphere/tst_boundingsphere.cpp b/tests/auto/render/boundingsphere/tst_boundingsphere.cpp index ce55db432..992e643d2 100644 --- a/tests/auto/render/boundingsphere/tst_boundingsphere.cpp +++ b/tests/auto/render/boundingsphere/tst_boundingsphere.cpp @@ -330,7 +330,98 @@ private Q_SLOTS: calcBVolume.setRoot(test->sceneRoot()); calcBVolume.run(); - QVector3D center = entityBackend->localBoundingVolume()->center(); + Vector3D center = entityBackend->localBoundingVolume()->center(); + float radius = entityBackend->localBoundingVolume()->radius(); + qDebug() << radius << center; + + // truncate and compare integers only + QVERIFY(int(radius) == int(expectedRadius)); + QVERIFY(int(center.x()) == int(expectedCenter.x())); + QVERIFY(int(center.y()) == int(expectedCenter.y())); + QVERIFY(int(center.z()) == int(expectedCenter.z())); + } + + void checkCustomPackedGeometry() + { + int drawVertexCount = 6; + QVector3D expectedCenter(-0.488892f, 0.0192147f, -75.4804f); + float expectedRadius = 25.5442f; + + // two triangles with different Z + QByteArray vdata; + vdata.resize(6 * 3 * sizeof(float)); + float *vp = reinterpret_cast<float *>(vdata.data()); + *vp++ = -1.0f; + *vp++ = 1.0f; + *vp++ = -100.0f; + *vp++ = 0.0f; + *vp++ = 0.0f; + *vp++ = -100.0f; + *vp++ = 1.0f; + *vp++ = 1.0f; + *vp++ = -100.0f; + + *vp++ = -1.0f; + *vp++ = -1.0f; + *vp++ = -50.0f; + *vp++ = 0.0f; + *vp++ = 0.0f; + *vp++ = -50.0f; + *vp++ = 1.0f; + *vp++ = -1.0f; + *vp++ = -50.0f; + + QScopedPointer<Qt3DCore::QEntity> entity(new Qt3DCore::QEntity); + QScopedPointer<Qt3DRender::TestAspect> test(new Qt3DRender::TestAspect(entity.data())); + Qt3DRender::QBuffer *vbuffer = new Qt3DRender::QBuffer; + + vbuffer->setData(vdata); + Qt3DRender::Render::Buffer *vbufferBackend = test->nodeManagers()->bufferManager()->getOrCreateResource(vbuffer->id()); + vbufferBackend->setRenderer(test->renderer()); + vbufferBackend->setManager(test->nodeManagers()->bufferManager()); + simulateInitialization(vbuffer, vbufferBackend); + + Qt3DRender::QGeometry *g = new Qt3DRender::QGeometry; + g->addAttribute(new Qt3DRender::QAttribute); + + const QVector<Qt3DRender::QAttribute *> attrs = g->attributes(); + Qt3DRender::QAttribute *attr = attrs[0]; + attr->setBuffer(vbuffer); + attr->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); + attr->setVertexBaseType(Qt3DRender::QAttribute::Float); + attr->setVertexSize(3); + attr->setCount(6); + attr->setByteOffset(0); + attr->setByteStride(0); + + Qt3DRender::QGeometryRenderer *gr = new Qt3DRender::QGeometryRenderer; + gr->setVertexCount(drawVertexCount); + gr->setGeometry(g); + entity->addComponent(gr); + + Qt3DRender::Render::Attribute *attr0Backend = test->nodeManagers()->attributeManager()->getOrCreateResource(attrs[0]->id()); + attr0Backend->setRenderer(test->renderer()); + simulateInitialization(attrs[0], attr0Backend); + + Qt3DRender::Render::Geometry *gBackend = test->nodeManagers()->geometryManager()->getOrCreateResource(g->id()); + gBackend->setRenderer(test->renderer()); + simulateInitialization(g, gBackend); + + Qt3DRender::Render::GeometryRenderer *grBackend = test->nodeManagers()->geometryRendererManager()->getOrCreateResource(gr->id()); + grBackend->setRenderer(test->renderer()); + grBackend->setManager(test->nodeManagers()->geometryRendererManager()); + simulateInitialization(gr, grBackend); + + Qt3DRender::Render::Entity *entityBackend = test->nodeManagers()->renderNodesManager()->getOrCreateResource(entity->id()); + entityBackend->setRenderer(test->renderer()); + simulateInitialization(entity.data(), entityBackend); + + Qt3DRender::Render::CalculateBoundingVolumeJob calcBVolume; + calcBVolume.setManagers(test->nodeManagers()); + calcBVolume.setRoot(test->sceneRoot()); + calcBVolume.run(); + + Vector3D center = entityBackend->localBoundingVolume()->center(); float radius = entityBackend->localBoundingVolume()->radius(); qDebug() << radius << center; diff --git a/tests/auto/render/commons/testrenderer.h b/tests/auto/render/commons/testrenderer.h index b3f602dc2..9624f129a 100644 --- a/tests/auto/render/commons/testrenderer.h +++ b/tests/auto/render/commons/testrenderer.h @@ -52,7 +52,7 @@ public: void shutdown() override {} void releaseGraphicsResources() override {} void render() override {} - void doRender(bool scene3dBlocking = false) override { Q_UNUSED(scene3dBlocking); } + void doRender() override {} void cleanGraphicsResources() override {} bool isRunning() const override { return true; } bool shouldRender() override { return true; } @@ -60,7 +60,7 @@ public: QVector<Qt3DCore::QAspectJobPtr> renderBinJobs() override { return QVector<Qt3DCore::QAspectJobPtr>(); } Qt3DCore::QAspectJobPtr pickBoundingVolumeJob() override { return Qt3DCore::QAspectJobPtr(); } Qt3DCore::QAspectJobPtr rayCastingJob() override { return Qt3DCore::QAspectJobPtr(); } - Qt3DCore::QAspectJobPtr syncTextureLoadingJob() override { return Qt3DCore::QAspectJobPtr(); } + Qt3DCore::QAspectJobPtr syncSkeletonLoadingJob() override { return Qt3DCore::QAspectJobPtr(); } Qt3DCore::QAspectJobPtr expandBoundingVolumeJob() override { return Qt3DCore::QAspectJobPtr(); } void setSceneRoot(Qt3DCore::QBackendNodeFactory *factory, Qt3DRender::Render::Entity *root) override { Q_UNUSED(factory); Q_UNUSED(root); } Qt3DRender::Render::Entity *sceneRoot() const override { return nullptr; } @@ -81,6 +81,12 @@ public: void setOffscreenSurfaceHelper(Qt3DRender::Render::OffscreenSurfaceHelper *helper) override; QSurfaceFormat format() override; + void lockSurfaceAndRender() override {} + bool releaseRendererAndRequestPromiseToRender() override { return true; } + bool waitForRenderJobs() override { return true; } + bool tryWaitForRenderJobs(int timeout) override { Q_UNUSED(timeout); return true; } + void abortRenderJobs() override {} + protected: Qt3DRender::Render::AbstractRenderer::BackendNodeDirtySet m_changes; Qt3DRender::Render::NodeManagers *m_managers; diff --git a/tests/auto/render/coordinatereader/tst_coordinatereader.cpp b/tests/auto/render/coordinatereader/tst_coordinatereader.cpp index 7dfe3ceba..afb18fe55 100644 --- a/tests/auto/render/coordinatereader/tst_coordinatereader.cpp +++ b/tests/auto/render/coordinatereader/tst_coordinatereader.cpp @@ -67,7 +67,7 @@ public: { return m_bufferInfo; } - bool verifyCoordinate(uint index, QVector4D value) + bool verifyCoordinate(uint index, Vector4D value) { return qFuzzyCompare(getCoordinate(index), value); } @@ -270,12 +270,12 @@ private Q_SLOTS: // THEN QCOMPARE(ret, true); - QVERIFY(reader.verifyCoordinate(0, QVector4D(0, 0, 1, 1))); - QVERIFY(reader.verifyCoordinate(1, QVector4D(1, 0, 0, 1))); - QVERIFY(reader.verifyCoordinate(2, QVector4D(0, 1, 0, 1))); - QVERIFY(reader.verifyCoordinate(3, QVector4D(0, 0, 1, 1))); - QVERIFY(reader.verifyCoordinate(4, QVector4D(1, 0, 0, 1))); - QVERIFY(reader.verifyCoordinate(5, QVector4D(0, 1, 0, 1))); + QVERIFY(reader.verifyCoordinate(0, Vector4D(0, 0, 1, 1))); + QVERIFY(reader.verifyCoordinate(1, Vector4D(1, 0, 0, 1))); + QVERIFY(reader.verifyCoordinate(2, Vector4D(0, 1, 0, 1))); + QVERIFY(reader.verifyCoordinate(3, Vector4D(0, 0, 1, 1))); + QVERIFY(reader.verifyCoordinate(4, Vector4D(1, 0, 0, 1))); + QVERIFY(reader.verifyCoordinate(5, Vector4D(0, 1, 0, 1))); } void testReadCoordinateVec4() @@ -364,12 +364,12 @@ private Q_SLOTS: // THEN QCOMPARE(ret, true); - QVERIFY(reader.verifyCoordinate(0, QVector4D(0, 0, 1, 1))); - QVERIFY(reader.verifyCoordinate(1, QVector4D(1, 0, 0, 1))); - QVERIFY(reader.verifyCoordinate(2, QVector4D(0, 1, 0, 0))); - QVERIFY(reader.verifyCoordinate(3, QVector4D(0, 0, 1, 0))); - QVERIFY(reader.verifyCoordinate(4, QVector4D(1, 0, 0, 0))); - QVERIFY(reader.verifyCoordinate(5, QVector4D(0, 1, 0, 1))); + QVERIFY(reader.verifyCoordinate(0, Vector4D(0, 0, 1, 1))); + QVERIFY(reader.verifyCoordinate(1, Vector4D(1, 0, 0, 1))); + QVERIFY(reader.verifyCoordinate(2, Vector4D(0, 1, 0, 0))); + QVERIFY(reader.verifyCoordinate(3, Vector4D(0, 0, 1, 0))); + QVERIFY(reader.verifyCoordinate(4, Vector4D(1, 0, 0, 0))); + QVERIFY(reader.verifyCoordinate(5, Vector4D(0, 1, 0, 1))); } void testReadCoordinateFromAttribute() @@ -468,9 +468,9 @@ private Q_SLOTS: // THEN QCOMPARE(ret, true); - QVERIFY(reader.verifyCoordinate(0, QVector4D(0, 0, 1, 1))); - QVERIFY(reader.verifyCoordinate(1, QVector4D(0, 1, 0, 1))); - QVERIFY(reader.verifyCoordinate(2, QVector4D(1, 0, 0, 1))); + QVERIFY(reader.verifyCoordinate(0, Vector4D(0, 0, 1, 1))); + QVERIFY(reader.verifyCoordinate(1, Vector4D(0, 1, 0, 1))); + QVERIFY(reader.verifyCoordinate(2, Vector4D(1, 0, 0, 1))); // WHEN ret = reader.setGeometry(backendRenderer, @@ -479,9 +479,9 @@ private Q_SLOTS: // THEN QCOMPARE(ret, true); - QVERIFY(reader.verifyCoordinate(0, QVector4D(1, 0, 0, 1))); - QVERIFY(reader.verifyCoordinate(1, QVector4D(0, 0, 1, 1))); - QVERIFY(reader.verifyCoordinate(2, QVector4D(0, 1, 0, 1))); + QVERIFY(reader.verifyCoordinate(0, Vector4D(1, 0, 0, 1))); + QVERIFY(reader.verifyCoordinate(1, Vector4D(0, 0, 1, 1))); + QVERIFY(reader.verifyCoordinate(2, Vector4D(0, 1, 0, 1))); } }; diff --git a/tests/auto/render/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp b/tests/auto/render/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp index 4d4a08a34..803d57fa9 100644 --- a/tests/auto/render/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp +++ b/tests/auto/render/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp @@ -93,7 +93,8 @@ public: { renderer()->setOpenGLContext(&m_glContext); d_func()->m_renderer->initialize(); - renderer()->graphicsContext()->beginDrawing(m_window.data()); + renderer()->graphicsContext()->makeCurrent(m_window.data()); + renderer()->graphicsContext()->beginDrawing(); } Render::Renderer *renderer() const diff --git a/tests/auto/render/geometryrenderer/tst_geometryrenderer.cpp b/tests/auto/render/geometryrenderer/tst_geometryrenderer.cpp index d07ec9914..e61fdf6e5 100644 --- a/tests/auto/render/geometryrenderer/tst_geometryrenderer.cpp +++ b/tests/auto/render/geometryrenderer/tst_geometryrenderer.cpp @@ -30,6 +30,7 @@ #include <qbackendnodetester.h> #include <Qt3DRender/private/geometryrenderer_p.h> #include <Qt3DRender/private/geometryrenderermanager_p.h> +#include <Qt3DRender/private/nodemanagers_p.h> #include <Qt3DRender/qgeometry.h> #include <Qt3DRender/qgeometryfactory.h> #include <Qt3DCore/qpropertyupdatedchange.h> @@ -186,6 +187,8 @@ private Q_SLOTS: // GIVEN Qt3DRender::Render::GeometryRenderer renderGeometryRenderer; TestRenderer renderer; + Qt3DRender::Render::NodeManagers nodeManagers; + renderGeometryRenderer.setRenderer(&renderer); QVERIFY(!renderGeometryRenderer.isDirty()); diff --git a/tests/auto/render/pickboundingvolumejob/pickboundingvolumejob.qrc b/tests/auto/render/pickboundingvolumejob/pickboundingvolumejob.qrc index c2b0c7fff..feef480e2 100644 --- a/tests/auto/render/pickboundingvolumejob/pickboundingvolumejob.qrc +++ b/tests/auto/render/pickboundingvolumejob/pickboundingvolumejob.qrc @@ -8,5 +8,7 @@ <file>testscene_pickersdisabled.qml</file> <file>testscene_dragenabledoverlapping.qml</file> <file>testscene_parententity.qml</file> + <file>testscene_viewports.qml</file> + <file>testscene_cameraposition.qml</file> </qresource> </RCC> diff --git a/tests/auto/render/pickboundingvolumejob/testscene_cameraposition.qml b/tests/auto/render/pickboundingvolumejob/testscene_cameraposition.qml new file mode 100644 index 000000000..87e7a8aac --- /dev/null +++ b/tests/auto/render/pickboundingvolumejob/testscene_cameraposition.qml @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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.Extras 2.0 +import QtQuick.Window 2.0 + +Entity { + id: sceneRoot + + Window { + id: win + width: 600 + height: 600 + visible: true + } + + Camera { + id: camera + projectionType: CameraLens.PerspectiveProjection + fieldOfView: 45 + nearPlane : 0.1 + farPlane : 1000.0 + position: Qt.vector3d( 0.0, 0.0, -40.0 ) + upVector: Qt.vector3d( 0.0, 1.0, 0.0 ) + viewCenter: Qt.vector3d( 5.0, 3.0, 1.0 ) + } + + components: [ + RenderSettings { + Viewport { + normalizedRect: Qt.rect(0.0, 0.0, 1.0, 1.0) + + RenderSurfaceSelector { + + surface: win + + ClearBuffers { + buffers : ClearBuffers.ColorDepthBuffer + NoDraw {} + } + + CameraSelector { + camera: camera + } + } + } + } + ] + + CuboidMesh { id: cubeMesh } + PhongMaterial { id: material } + + Entity { + property ObjectPicker picker: ObjectPicker { + objectName: "Picker" + } + + property Transform transform: Transform { + translation: camera.viewCenter + scale: 2.0 + } + + components: [cubeMesh, material, picker, transform] + } + +} diff --git a/tests/auto/render/pickboundingvolumejob/testscene_viewports.qml b/tests/auto/render/pickboundingvolumejob/testscene_viewports.qml new file mode 100644 index 000000000..daafc0edd --- /dev/null +++ b/tests/auto/render/pickboundingvolumejob/testscene_viewports.qml @@ -0,0 +1,158 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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.Extras 2.0 +import QtQuick.Window 2.0 + +Entity { + id: sceneRoot + + Window { + id: _view + width: 600 + height: 600 + visible: true + } + + Camera { + id: camera + projectionType: CameraLens.PerspectiveProjection + fieldOfView: 45 + aspectRatio: _view.width / 2 / _view.height + nearPlane : 0.1 + farPlane : 1000.0 + position: Qt.vector3d( 0.0, 0.0, -10.0 ) + upVector: Qt.vector3d( 0.0, 1.0, 0.0 ) + viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 ) + } + + Camera { + id: camera2 + projectionType: CameraLens.PerspectiveProjection + fieldOfView: 45 + aspectRatio: _view.width / _view.height + nearPlane : 0.1 + farPlane : 1000.0 + position: Qt.vector3d( 0.0, 0.0, -20.0 ) + upVector: Qt.vector3d( 0.0, 1.0, 0.0 ) + viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 ) + } + + FirstPersonCameraController { + camera: camera + } + + DirectionalLight { + worldDirection: camera.viewVector.times(-1) + } + + // Draw 2 viewports + // one with the content, the other with content + debug volumes + components: [ + RenderSettings { + Viewport { + normalizedRect: Qt.rect(0.0, 0.0, 1.0, 1.0) + + RenderSurfaceSelector { + surface: _view + + Viewport { + normalizedRect: Qt.rect(0.0, 0.0, 0.5, 1.0) + ClearBuffers { + buffers : ClearBuffers.ColorDepthBuffer + clearColor: "white" + CameraSelector { + camera: camera + } + } + } + + Viewport { + normalizedRect: Qt.rect(0.5, 0.0, 0.5, 1.0) + CameraSelector { + camera: camera2 + } + } + } + } + } + ] + + CuboidMesh { id: cubeMesh } + + Entity { + readonly property ObjectPicker objectPicker: ObjectPicker { + onClicked: console.log("o1") + } + readonly property Transform transform: Transform { + scale: 3 + translation: Qt.vector3d(3, 0, 0) + } + readonly property PhongMaterial material: PhongMaterial { diffuse: "red" } + + components: [cubeMesh, transform, material, objectPicker ] + } + + Entity { + readonly property ObjectPicker objectPicker: ObjectPicker { + objectName: "Picker2" + onClicked: console.log("o2") + } + readonly property Transform transform: Transform { + scale: 3 + translation: Qt.vector3d(-3, 0, 0) + } + readonly property PhongMaterial material: PhongMaterial { diffuse: "green" } + + components: [cubeMesh, transform, material, objectPicker ] + } +} diff --git a/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp b/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp index a14bccefc..b86df05a4 100644 --- a/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp +++ b/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp @@ -234,7 +234,7 @@ private Q_SLOTS: // WHEN Qt3DRender::Render::PickingUtils::ViewportCameraAreaGatherer gatherer; - QVector<Qt3DRender::Render::PickingUtils::ViewportCameraAreaTriplet> results = gatherer.gather(test->frameGraphRoot()); + QVector<Qt3DRender::Render::PickingUtils::ViewportCameraAreaDetails> results = gatherer.gather(test->frameGraphRoot()); // THEN QCOMPARE(results.size(), 1); @@ -329,8 +329,8 @@ private Q_SLOTS: QVERIFY(pickBVJob.currentPicker().isNull()); // WHEN - QList<QMouseEvent> events; - events.push_back(QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); + QList<QPair<QObject *,QMouseEvent>> events; + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); bool earlyReturn = !pickBVJob.runHelper(); @@ -343,7 +343,7 @@ private Q_SLOTS: // WHEN events.clear(); - events.push_back(QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(207.0f, 303.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(207.0f, 303.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); @@ -353,7 +353,7 @@ private Q_SLOTS: // WHEN events.clear(); - events.push_back(QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(390.0f, 300.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(390.0f, 300.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); @@ -366,7 +366,7 @@ private Q_SLOTS: // WHEN events.clear(); - events.push_back(QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(390.0f, 300.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(390.0f, 300.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); @@ -425,8 +425,9 @@ private Q_SLOTS: QVERIFY(earlyReturn); // WHEN - QList<QMouseEvent> events; - events.push_back(QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(400.0f, 440.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); + QList<QPair<QObject *, QMouseEvent>> events; + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(400.0f, 440.0f), + Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); @@ -474,8 +475,9 @@ private Q_SLOTS: Qt3DRender::Render::PickBoundingVolumeJob pickBVJob; initializePickBoundingVolumeJob(&pickBVJob, test.data()); - QList<QMouseEvent> events; - events.push_back(QMouseEvent(QMouseEvent::MouseMove, QPointF(207.0f, 303.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); + QList<QPair<QObject *, QMouseEvent>> events; + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(207.0f, 303.0f), + Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); // THEN @@ -530,9 +532,9 @@ private Q_SLOTS: Qt3DRender::Render::PickBoundingVolumeJob pickBVJob; initializePickBoundingVolumeJob(&pickBVJob, test.data()); - QList<QMouseEvent> events; - events.push_back(QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f), - Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); + QList<QPair<QObject *, QMouseEvent>> events; + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f), + Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); bool earlyReturn = !pickBVJob.runHelper(); @@ -580,8 +582,9 @@ private Q_SLOTS: Qt3DRender::Render::PickBoundingVolumeJob pickBVJob; initializePickBoundingVolumeJob(&pickBVJob, test.data()); - QList<QMouseEvent> events; - events.push_back(QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); + QList<QPair<QObject *, QMouseEvent>> events; + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f), + Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); bool earlyReturn = !pickBVJob.runHelper(); @@ -591,7 +594,8 @@ private Q_SLOTS: // WHEN events.clear(); - events.push_back(QMouseEvent(QMouseEvent::MouseMove, QPointF(207.0f, 303.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(207.0f, 303.0f), + Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); @@ -639,8 +643,9 @@ private Q_SLOTS: Qt3DRender::Render::PickBoundingVolumeJob pickBVJob; initializePickBoundingVolumeJob(&pickBVJob, test.data()); - QList<QMouseEvent> events; - events.push_back(QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); + QList<QPair<QObject *, QMouseEvent>> events; + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f), + Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); bool earlyReturn = !pickBVJob.runHelper(); @@ -650,7 +655,8 @@ private Q_SLOTS: // WHEN events.clear(); - events.push_back(QMouseEvent(QMouseEvent::MouseMove, QPointF(207.0f, 303.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(207.0f, 303.0f), + Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); @@ -698,8 +704,9 @@ private Q_SLOTS: Qt3DRender::Render::PickBoundingVolumeJob pickBVJob; initializePickBoundingVolumeJob(&pickBVJob, test.data()); - QList<QMouseEvent> events; - events.push_back(QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); + QList<QPair<QObject *, QMouseEvent>> events; + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f), + Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); const bool earlyReturn = !pickBVJob.runHelper(); @@ -764,8 +771,9 @@ private Q_SLOTS: Qt3DRender::Render::PickBoundingVolumeJob pickBVJob; initializePickBoundingVolumeJob(&pickBVJob, test.data()); - QList<QMouseEvent> events; - events.push_back(QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); + QList<QPair<QObject *, QMouseEvent>> events; + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f), + Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); bool earlyReturn = !pickBVJob.runHelper(); @@ -785,7 +793,8 @@ private Q_SLOTS: // WHEN -> Move on same object events.clear(); - events.push_back(QMouseEvent(QMouseEvent::MouseMove, QPointF(207.0f, 303.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(207.0f, 303.0f), + Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); @@ -805,7 +814,8 @@ private Q_SLOTS: // WHEN -> Release on object events.clear(); - events.push_back(QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(207.0f, 303.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(207.0f, 303.0f), + Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); @@ -832,8 +842,10 @@ private Q_SLOTS: // WHEN -> Release outside of object events.clear(); - events.push_back(QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); - events.push_back(QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(0.0f, 0.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f), + Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(0.0f, 0.0f), + Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); @@ -900,8 +912,9 @@ private Q_SLOTS: Qt3DRender::Render::PickBoundingVolumeJob pickBVJob; initializePickBoundingVolumeJob(&pickBVJob, test.data()); - QList<QMouseEvent> events; - events.push_back(QMouseEvent(QMouseEvent::HoverMove, QPointF(207.0f, 303.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); + QList<QPair<QObject *, QMouseEvent>> events; + events.push_back({nullptr, QMouseEvent(QMouseEvent::HoverMove, QPointF(207.0f, 303.0f), + Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); bool earlyReturn = !pickBVJob.runHelper(); @@ -916,7 +929,8 @@ private Q_SLOTS: // WHEN -> HoverMove Out events.clear(); - events.push_back(QMouseEvent(QEvent::HoverMove, QPointF(20.0f, 40.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); + events.push_back({nullptr, QMouseEvent(QEvent::HoverMove, QPointF(20.0f, 40.0f), + Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); @@ -931,8 +945,10 @@ private Q_SLOTS: // WHEN -> HoverMove In + Pressed other events.clear(); - events.push_back(QMouseEvent(QEvent::HoverMove, QPointF(207.0f, 303.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); - events.push_back(QMouseEvent(QEvent::MouseButtonPress, QPointF(0.0f, 0.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); + events.push_back({nullptr, QMouseEvent(QEvent::HoverMove, QPointF(207.0f, 303.0f), + Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); + events.push_back({nullptr, QMouseEvent(QEvent::MouseButtonPress, QPointF(0.0f, 0.0f), + Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); @@ -1001,8 +1017,9 @@ private Q_SLOTS: Qt3DRender::Render::PickBoundingVolumeJob pickBVJob; initializePickBoundingVolumeJob(&pickBVJob, test.data()); - QList<QMouseEvent> events; - events.push_back(QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(400.0f, 300.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); + QList<QPair<QObject *, QMouseEvent>> events; + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(400.0f, 300.0f), + Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); bool earlyReturn = !pickBVJob.runHelper(); @@ -1017,7 +1034,8 @@ private Q_SLOTS: // WHEN -> Move on same object events.clear(); - events.push_back(QMouseEvent(QMouseEvent::MouseMove, QPointF(400.0f, 300.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(400.0f, 300.0f), + Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); @@ -1032,7 +1050,8 @@ private Q_SLOTS: // WHEN -> Release on object events.clear(); - events.push_back(QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(400.0f, 300.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(400.0f, 300.0f), + Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); @@ -1049,8 +1068,10 @@ private Q_SLOTS: // WHEN -> Release outside of object events.clear(); - events.push_back(QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(400.0f, 300.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); - events.push_back(QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(0.0f, 0.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(400.0f, 300.0f), + Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(0.0f, 0.0f), + Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); @@ -1126,8 +1147,9 @@ private Q_SLOTS: Qt3DRender::Render::PickBoundingVolumeJob pickBVJob; initializePickBoundingVolumeJob(&pickBVJob, test.data()); - QList<QMouseEvent> events; - events.push_back(QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(320.0f, 303.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); + QList<QPair<QObject *, QMouseEvent>> events; + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(320.0f, 303.0f), + Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); bool earlyReturn = !pickBVJob.runHelper(); @@ -1141,7 +1163,8 @@ private Q_SLOTS: // WHEN -> Move on next object, show stay on previous picker unless all picks are requested events.clear(); - events.push_back(QMouseEvent(QMouseEvent::MouseMove, QPointF(280.0f, 303.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(280.0f, 303.0f), + Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); earlyReturn = !pickBVJob.runHelper(); @@ -1200,8 +1223,9 @@ private Q_SLOTS: Qt3DRender::Render::PickBoundingVolumeJob pickBVJob; initializePickBoundingVolumeJob(&pickBVJob, test.data()); - QList<QMouseEvent> events; - events.push_back(QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(400.0f, 300.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); + QList<QPair<QObject *, QMouseEvent>> events; + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(400.0f, 300.0f), + Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); pickBVJob.setMouseEvents(events); bool earlyReturn = !pickBVJob.runHelper(); @@ -1212,6 +1236,155 @@ private Q_SLOTS: Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); QCOMPARE(change->propertyName(), "pressed"); } + + void checkPickerAndViewports() + { + // GIVEN + QmlSceneReader sceneReader(QUrl("qrc:/testscene_viewports.qml")); + QScopedPointer<Qt3DCore::QNode> root(qobject_cast<Qt3DCore::QNode *>(sceneReader.root())); + QVERIFY(root); + + QList<Qt3DRender::QRenderSettings *> renderSettings = root->findChildren<Qt3DRender::QRenderSettings *>(); + QCOMPARE(renderSettings.size(), 1); + Qt3DRender::QPickingSettings *settings = renderSettings.first()->pickingSettings(); + + settings->setPickMethod(Qt3DRender::QPickingSettings::TrianglePicking); + settings->setPickResultMode(Qt3DRender::QPickingSettings::NearestPick); + settings->setFaceOrientationPickingMode(Qt3DRender::QPickingSettings::FrontFace); + + QScopedPointer<Qt3DRender::TestAspect> test(new Qt3DRender::TestAspect(root.data())); + TestArbiter arbiter; + + // Runs Required jobs + runRequiredJobs(test.data()); + + // THEN + // object partially obscured by another viewport, make sure only visible portion is pickable + QList<Qt3DRender::QObjectPicker *> pickers = root->findChildren<Qt3DRender::QObjectPicker *>(); + QCOMPARE(pickers.size(), 2); + + Qt3DRender::QObjectPicker *picker = pickers.last(); + QCOMPARE(picker->objectName(), QLatin1String("Picker2")); + + Qt3DRender::Render::ObjectPicker *backendPicker = test->nodeManagers()->objectPickerManager()->lookupResource(picker->id()); + QVERIFY(backendPicker); + Qt3DCore::QBackendNodePrivate::get(backendPicker)->setArbiter(&arbiter); + + // WHEN -> Pressed on object in vp1 + Qt3DRender::Render::PickBoundingVolumeJob pickBVJob; + initializePickBoundingVolumeJob(&pickBVJob, test.data()); + + QList<QPair<QObject *, QMouseEvent>> events; + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(280.0f, 300.0f), + Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); + pickBVJob.setMouseEvents(events); + bool earlyReturn = !pickBVJob.runHelper(); + + // THEN -> Pressed + QVERIFY(!earlyReturn); + QVERIFY(backendPicker->isPressed()); + QCOMPARE(arbiter.events.count(), 1); + Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "pressed"); + + // WHEN reset -> Presset on object in vp2 + backendPicker->cleanup(); + backendPicker->setEnabled(true); + events.clear(); + arbiter.events.clear(); + + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(320.0f, 300.0f), + Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); + pickBVJob.setMouseEvents(events); + earlyReturn = !pickBVJob.runHelper(); + + // THEN -> Nothing happened + QVERIFY(!earlyReturn); + QVERIFY(!backendPicker->isPressed()); + QCOMPARE(arbiter.events.count(), 0); + } + + void checkMultipleRayDirections_data() + { + QTest::addColumn<QVector3D>("cameraOrigin"); + QTest::addColumn<QVector3D>("cameraUpVector"); + + int k = 0; + const int n = 10; + for (int j=0; j<n; j++) { + QMatrix4x4 m; + m.rotate(360.f / (float)n * (float)j, 0.f, 0.f, 1.f); + for (int i=0; i<n; i++) { + const double angle = M_PI * 2. / (double)n * i; + const double x = std::sin(angle) * 10.; + const double z = std::cos(angle) * 10.; + QVector3D pos(x, 0, z); + QVector3D up(0, 1, 0); + QTest::newRow(QString::number(k++).toLatin1().data()) << m * pos << m * up; + } + } + } + + void checkMultipleRayDirections() + { + // GIVEN + QmlSceneReader sceneReader(QUrl("qrc:/testscene_cameraposition.qml")); + QScopedPointer<Qt3DCore::QNode> root(qobject_cast<Qt3DCore::QNode *>(sceneReader.root())); + QVERIFY(root); + + QList<Qt3DRender::QRenderSettings *> renderSettings = root->findChildren<Qt3DRender::QRenderSettings *>(); + QCOMPARE(renderSettings.size(), 1); + Qt3DRender::QPickingSettings *settings = renderSettings.first()->pickingSettings(); + + settings->setPickMethod(Qt3DRender::QPickingSettings::TrianglePicking); + + QScopedPointer<Qt3DRender::TestAspect> test(new Qt3DRender::TestAspect(root.data())); + TestArbiter arbiter; + + QList<Qt3DRender::QCamera *> cameras = root->findChildren<Qt3DRender::QCamera *>(); + QCOMPARE(cameras.size(), 1); + Qt3DRender::QCamera *camera = cameras.first(); + + QFETCH(QVector3D, cameraUpVector); + camera->setUpVector(cameraUpVector); + + QFETCH(QVector3D, cameraOrigin); + camera->setPosition(cameraOrigin); + + // Runs Required jobs + runRequiredJobs(test.data()); + + // THEN + QList<Qt3DRender::QObjectPicker *> pickers = root->findChildren<Qt3DRender::QObjectPicker *>(); + QCOMPARE(pickers.size(), 1); + + Qt3DRender::QObjectPicker *picker = pickers.front(); + + Qt3DRender::Render::ObjectPicker *backendPicker = test->nodeManagers()->objectPickerManager()->lookupResource(picker->id()); + QVERIFY(backendPicker); + Qt3DCore::QBackendNodePrivate::get(backendPicker)->setArbiter(&arbiter); + + // WHEN -> Pressed on object + Qt3DRender::Render::PickBoundingVolumeJob pickBVJob; + initializePickBoundingVolumeJob(&pickBVJob, test.data()); + + QList<QPair<QObject *, QMouseEvent>> events; + events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(303.0f, 303.0f), + Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)}); + pickBVJob.setMouseEvents(events); + bool earlyReturn = !pickBVJob.runHelper(); + + // THEN -> Pressed + QVERIFY(!earlyReturn); + QVERIFY(backendPicker->isPressed()); + Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "pressed"); + Qt3DRender::QPickEventPtr pickEvent = change->value().value<Qt3DRender::QPickEventPtr>(); + QVERIFY(pickEvent); + + arbiter.events.clear(); + } + }; QTEST_MAIN(tst_PickBoundingVolumeJob) diff --git a/tests/auto/render/qcamera/tst_qcamera.cpp b/tests/auto/render/qcamera/tst_qcamera.cpp index 82a6d8b89..b630c447a 100644 --- a/tests/auto/render/qcamera/tst_qcamera.cpp +++ b/tests/auto/render/qcamera/tst_qcamera.cpp @@ -165,7 +165,7 @@ private Q_SLOTS: Qt3DRender::Render::Entity *cameraEntity = test->nodeManagers()->lookupResource<Qt3DRender::Render::Entity, Qt3DRender::Render::EntityManager>(camera->id()); // THEN - QVERIFY(qFuzzyCompare(*cameraEntity->worldTransform(), parentTransform->matrix())); + QVERIFY(qFuzzyCompare(convertToQMatrix4x4(*cameraEntity->worldTransform()), convertToQMatrix4x4(parentTransform->matrix()))); } void checkTransformWithParentAndLookAt() @@ -193,7 +193,7 @@ private Q_SLOTS: 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(); + const QMatrix4x4 worldTransform = convertToQMatrix4x4(*cameraEntity->worldTransform()); fuzzyCompareMatrix(worldTransform, m); } @@ -234,7 +234,7 @@ private Q_SLOTS: 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); + fuzzyCompareMatrix(convertToQMatrix4x4(*childEntity->worldTransform()), m); } }; diff --git a/tests/auto/render/qray3d/tst_qray3d.cpp b/tests/auto/render/qray3d/tst_qray3d.cpp index e6ab02af0..e9d4d3033 100644 --- a/tests/auto/render/qray3d/tst_qray3d.cpp +++ b/tests/auto/render/qray3d/tst_qray3d.cpp @@ -70,7 +70,7 @@ static inline bool fuzzyCompare(float p1, float p2) return (qAbs(p1 - p2) <= (qIsNull(fac) ? 0.00001f : 0.00001f * fac)); } -static inline bool fuzzyCompare(const QVector3D &lhs, const QVector3D &rhs) +static inline bool fuzzyCompare(const Vector3D &lhs, const Vector3D &rhs) { if (fuzzyCompare(lhs.x(), rhs.x()) && fuzzyCompare(lhs.y(), rhs.y()) && @@ -85,59 +85,59 @@ static inline bool fuzzyCompare(const QVector3D &lhs, const QVector3D &rhs) void tst_QRay3D::create_data() { - QTest::addColumn<QVector3D>("point"); - QTest::addColumn<QVector3D>("direction"); + QTest::addColumn<Vector3D>("point"); + QTest::addColumn<Vector3D>("direction"); // normalized direction vectors QTest::newRow("line on x-axis from origin") - << QVector3D() - << QVector3D(1.0f, 0.0f, 0.0f); + << Vector3D() + << Vector3D(1.0f, 0.0f, 0.0f); QTest::newRow("line parallel -z-axis from 3,3,3") - << QVector3D(3.0f, 3.0f, 3.0f) - << QVector3D(0.0f, 0.0f, -1.0f); + << Vector3D(3.0f, 3.0f, 3.0f) + << Vector3D(0.0f, 0.0f, -1.0f); QTest::newRow("vertical line (parallel to y-axis)") - << QVector3D(0.5f, 0.0f, 0.5f) - << QVector3D(0.0f, 1.0f, 0.0f); + << Vector3D(0.5f, 0.0f, 0.5f) + << Vector3D(0.0f, 1.0f, 0.0f); QTest::newRow("equidistant from all 3 axes") - << QVector3D(0.5f, 0.0f, 0.5f) - << QVector3D(0.57735026919f, 0.57735026919f, 0.57735026919f); + << Vector3D(0.5f, 0.0f, 0.5f) + << Vector3D(0.57735026919f, 0.57735026919f, 0.57735026919f); // non-normalized direction vectors QTest::newRow("line on x-axis from origin - B") - << QVector3D() - << QVector3D(2.0f, 0.0f, 0.0f); + << Vector3D() + << Vector3D(2.0f, 0.0f, 0.0f); QTest::newRow("line parallel -z-axis from 3,3,3 - B") - << QVector3D(3.0f, 3.0f, 3.0f) - << QVector3D(0.0f, 0.0f, -0.7f); + << Vector3D(3.0f, 3.0f, 3.0f) + << Vector3D(0.0f, 0.0f, -0.7f); QTest::newRow("vertical line (parallel to y-axis) - B") - << QVector3D(0.5f, 0.0f, 0.5f) - << QVector3D(0.0f, 5.3f, 0.0f); + << Vector3D(0.5f, 0.0f, 0.5f) + << Vector3D(0.0f, 5.3f, 0.0f); QTest::newRow("equidistant from all 3 axes - B") - << QVector3D(0.5f, 0.0f, 0.5f) - << QVector3D(1.0f, 1.0f, 1.0f); + << Vector3D(0.5f, 0.0f, 0.5f) + << Vector3D(1.0f, 1.0f, 1.0f); QTest::newRow("negative direction") - << QVector3D(-3.0f, -3.0f, -3.0f) - << QVector3D(-1.2f, -1.8f, -2.4f); + << Vector3D(-3.0f, -3.0f, -3.0f) + << Vector3D(-1.2f, -1.8f, -2.4f); } void tst_QRay3D::create() { - QFETCH(QVector3D, point); - QFETCH(QVector3D, direction); + QFETCH(Vector3D, point); + QFETCH(Vector3D, direction); Qt3DRender::RayCasting::QRay3D ray(point, direction); QVERIFY(fuzzyCompare(ray.direction(), direction)); QVERIFY(fuzzyCompare(ray.origin(), point)); Qt3DRender::RayCasting::QRay3D ray2; - QCOMPARE(ray2.origin(), QVector3D(0, 0, 0)); - QCOMPARE(ray2.direction(), QVector3D(0, 0, 1)); + QCOMPARE(ray2.origin(), Vector3D(0, 0, 0)); + QCOMPARE(ray2.direction(), Vector3D(0, 0, 1)); ray2.setOrigin(point); ray2.setDirection(direction); QVERIFY(fuzzyCompare(ray.direction(), direction)); @@ -146,97 +146,97 @@ void tst_QRay3D::create() void tst_QRay3D::projection_data() { - QTest::addColumn<QVector3D>("point"); - QTest::addColumn<QVector3D>("direction"); - QTest::addColumn<QVector3D>("vector"); - QTest::addColumn<QVector3D>("expected"); + QTest::addColumn<Vector3D>("point"); + QTest::addColumn<Vector3D>("direction"); + QTest::addColumn<Vector3D>("vector"); + QTest::addColumn<Vector3D>("expected"); QTest::newRow("line on x-axis from origin") - << QVector3D() - << QVector3D(2.0f, 0.0f, 0.0f) - << QVector3D(0.6f, 0.0f, 0.0f) - << QVector3D(0.6f, 0.0f, 0.0f); + << Vector3D() + << Vector3D(2.0f, 0.0f, 0.0f) + << Vector3D(0.6f, 0.0f, 0.0f) + << Vector3D(0.6f, 0.0f, 0.0f); QTest::newRow("line parallel -z-axis from 3,3,3") - << QVector3D(3.0f, 3.0f, 3.0f) - << QVector3D(0.0f, 0.0f, -0.7f) - << QVector3D(3.0f, 3.0f, 2.4f) - << QVector3D(0.0f, 0.0f, 2.4f); + << Vector3D(3.0f, 3.0f, 3.0f) + << Vector3D(0.0f, 0.0f, -0.7f) + << Vector3D(3.0f, 3.0f, 2.4f) + << Vector3D(0.0f, 0.0f, 2.4f); QTest::newRow("vertical line (parallel to y-axis)") - << QVector3D(0.5f, 0.0f, 0.5f) - << QVector3D(0.0f, 5.3f, 0.0f) - << QVector3D(0.5f, 0.6f, 0.5f) - << QVector3D(0.0f, 0.6f, 0.0f); + << Vector3D(0.5f, 0.0f, 0.5f) + << Vector3D(0.0f, 5.3f, 0.0f) + << Vector3D(0.5f, 0.6f, 0.5f) + << Vector3D(0.0f, 0.6f, 0.0f); QTest::newRow("equidistant from all 3 axes, project y-axis (with some z & x)") - << QVector3D(0.5f, 0.0f, 0.5f) - << QVector3D(1.0f, 1.0f, 1.0f) - << QVector3D(0.5f, 5.0f, 0.5f) - << QVector3D(2.0f, 2.0f, 2.0f); + << Vector3D(0.5f, 0.0f, 0.5f) + << Vector3D(1.0f, 1.0f, 1.0f) + << Vector3D(0.5f, 5.0f, 0.5f) + << Vector3D(2.0f, 2.0f, 2.0f); QTest::newRow("negative direction line, project +ve y-axis (with some z & x)") - << QVector3D(-3.0f, -3.0f, -3.0f) - << QVector3D(-1.2f, -1.8f, -2.4f) - << QVector3D(0.5f, 5.0f, 0.5f) - << QVector3D(1.241379261016846f, 1.862068772315979f, 2.48275852203369f); + << Vector3D(-3.0f, -3.0f, -3.0f) + << Vector3D(-1.2f, -1.8f, -2.4f) + << Vector3D(0.5f, 5.0f, 0.5f) + << Vector3D(1.241379261016846f, 1.862068772315979f, 2.48275852203369f); } void tst_QRay3D::projection() { - QFETCH(QVector3D, point); - QFETCH(QVector3D, direction); - QFETCH(QVector3D, vector); - QFETCH(QVector3D, expected); + QFETCH(Vector3D, point); + QFETCH(Vector3D, direction); + QFETCH(Vector3D, vector); + QFETCH(Vector3D, expected); Qt3DRender::RayCasting::QRay3D line(point, direction); - QVector3D result = line.project(vector); + Vector3D result = line.project(vector); QVERIFY(fuzzyCompare(result, expected)); } void tst_QRay3D::point_data() { - QTest::addColumn<QVector3D>("point"); - QTest::addColumn<QVector3D>("direction"); - QTest::addColumn<QVector3D>("point_on_line_pos_0_6"); - QTest::addColumn<QVector3D>("point_on_line_neg_7_2"); + QTest::addColumn<Vector3D>("point"); + QTest::addColumn<Vector3D>("direction"); + QTest::addColumn<Vector3D>("point_on_line_pos_0_6"); + QTest::addColumn<Vector3D>("point_on_line_neg_7_2"); QTest::newRow("line on x-axis from origin") - << QVector3D() - << QVector3D(2.0f, 0.0f, 0.0f) - << QVector3D(1.2f, 0.0f, 0.0f) - << QVector3D(-14.4f, 0.0f, 0.0f); + << Vector3D() + << Vector3D(2.0f, 0.0f, 0.0f) + << Vector3D(1.2f, 0.0f, 0.0f) + << Vector3D(-14.4f, 0.0f, 0.0f); QTest::newRow("line parallel -z-axis from 3,3,3") - << QVector3D(3.0f, 3.0f, 3.0f) - << QVector3D(0.0f, 0.0f, -0.7f) - << QVector3D(3.0f, 3.0f, 2.58f) - << QVector3D(3.0f, 3.0f, 8.04f); + << Vector3D(3.0f, 3.0f, 3.0f) + << Vector3D(0.0f, 0.0f, -0.7f) + << Vector3D(3.0f, 3.0f, 2.58f) + << Vector3D(3.0f, 3.0f, 8.04f); QTest::newRow("vertical line (parallel to y-axis)") - << QVector3D(0.5f, 0.0f, 0.5f) - << QVector3D(0.0f, 5.3f, 0.0f) - << QVector3D(0.5f, 3.18f, 0.5f) - << QVector3D(0.5f, -38.16f, 0.5f); + << Vector3D(0.5f, 0.0f, 0.5f) + << Vector3D(0.0f, 5.3f, 0.0f) + << Vector3D(0.5f, 3.18f, 0.5f) + << Vector3D(0.5f, -38.16f, 0.5f); QTest::newRow("equidistant from all 3 axes") - << QVector3D(0.5f, 0.0f, 0.5f) - << QVector3D(1.0f, 1.0f, 1.0f) - << QVector3D(1.1f, 0.6f, 1.1f) - << QVector3D(-6.7f, -7.2f, -6.7f); + << Vector3D(0.5f, 0.0f, 0.5f) + << Vector3D(1.0f, 1.0f, 1.0f) + << Vector3D(1.1f, 0.6f, 1.1f) + << Vector3D(-6.7f, -7.2f, -6.7f); QTest::newRow("negative direction") - << QVector3D(-3.0f, -3.0f, -3.0f) - << QVector3D(-1.2f, -1.8f, -2.4f) - << QVector3D(-3.72f, -4.08f, -4.44f) - << QVector3D(5.64f, 9.96f, 14.28f); + << Vector3D(-3.0f, -3.0f, -3.0f) + << Vector3D(-1.2f, -1.8f, -2.4f) + << Vector3D(-3.72f, -4.08f, -4.44f) + << Vector3D(5.64f, 9.96f, 14.28f); } void tst_QRay3D::point() { - QFETCH(QVector3D, point); - QFETCH(QVector3D, direction); - QFETCH(QVector3D, point_on_line_pos_0_6); - QFETCH(QVector3D, point_on_line_neg_7_2); + QFETCH(Vector3D, point); + QFETCH(Vector3D, direction); + QFETCH(Vector3D, point_on_line_pos_0_6); + QFETCH(Vector3D, point_on_line_neg_7_2); Qt3DRender::RayCasting::QRay3D line(point, direction); QVERIFY(fuzzyCompare(line.point(0.6f), point_on_line_pos_0_6)); QVERIFY(fuzzyCompare(line.point(-7.2f), point_on_line_neg_7_2)); @@ -246,39 +246,39 @@ void tst_QRay3D::point() void tst_QRay3D::contains_point_data() { - QTest::addColumn<QVector3D>("origin"); - QTest::addColumn<QVector3D>("direction"); - QTest::addColumn<QVector3D>("point"); + QTest::addColumn<Vector3D>("origin"); + QTest::addColumn<Vector3D>("direction"); + QTest::addColumn<Vector3D>("point"); QTest::addColumn<bool>("contains"); QTest::newRow("bogus this line with null direction") - << QVector3D(1.0, 3.0, 3.0) - << QVector3D(0.0, 0.0, 0.0) - << QVector3D(1.0, 2.0, 4.0) + << Vector3D(1.0, 3.0, 3.0) + << Vector3D(0.0, 0.0, 0.0) + << Vector3D(1.0, 2.0, 4.0) << false; QTest::newRow("point at the origin") - << QVector3D(0.0, 0.0, 0.0) - << QVector3D(1.0, 3.0, 3.0) - << QVector3D(0.0, 0.0, 0.0) + << Vector3D(0.0, 0.0, 0.0) + << Vector3D(1.0, 3.0, 3.0) + << Vector3D(0.0, 0.0, 0.0) << true; QTest::newRow("close to the origin") - << QVector3D(1.0, 1.0, 1.0) - << QVector3D(1.0, 3.0, 3.0) - << QVector3D(1.0005f, 1.0005f, 1.0) + << Vector3D(1.0, 1.0, 1.0) + << Vector3D(1.0, 3.0, 3.0) + << Vector3D(1.0005f, 1.0005f, 1.0) << false; QTest::newRow("45 line line in plane x=1") - << QVector3D(1.0, 3.0, 3.0) - << QVector3D(0.0, -1.0, -1.0) - << QVector3D(1.0, 4.0, 4.0) + << Vector3D(1.0, 3.0, 3.0) + << Vector3D(0.0, -1.0, -1.0) + << Vector3D(1.0, 4.0, 4.0) << true; { // This is to prove that the constructed approach give the // same results - QVector3D p(1.0, 3.0, 3.0); - QVector3D v(0.0, -1.0, -1.0); + Vector3D p(1.0, 3.0, 3.0); + Vector3D v(0.0, -1.0, -1.0); QTest::newRow("constructed 45 line line in plane x=1") << p @@ -288,20 +288,20 @@ void tst_QRay3D::contains_point_data() } QTest::newRow("intersection with negative s in plane z=-1") - << QVector3D(1.0f, 2.0f, -1.0f) - << QVector3D(1.0f, 1.0f, 0.0f) - << QVector3D(2.0f, 1.0f, 0.0f) + << Vector3D(1.0f, 2.0f, -1.0f) + << Vector3D(1.0f, 1.0f, 0.0f) + << Vector3D(2.0f, 1.0f, 0.0f) << false; QTest::newRow("45 angled line") - << QVector3D(3.0f, 0.0f, -1.0f) - << QVector3D(1.0f, -1.0f, 1.0f) - << QVector3D(6.0f, -3.0f, 2.0f) + << Vector3D(3.0f, 0.0f, -1.0f) + << Vector3D(1.0f, -1.0f, 1.0f) + << Vector3D(6.0f, -3.0f, 2.0f) << true; { - QVector3D p(-10.0, 3.0, 3.0); - QVector3D v(0.0, 20.0, -1.0); + Vector3D p(-10.0, 3.0, 3.0); + Vector3D v(0.0, 20.0, -1.0); QTest::newRow("constructed vector close to axis") << p << v @@ -310,8 +310,8 @@ void tst_QRay3D::contains_point_data() } { - QVector3D p(1.0, 3.0, 3.0); - QVector3D v(40.0, 500.0, -1.0); + Vector3D p(1.0, 3.0, 3.0); + Vector3D v(40.0, 500.0, -1.0); QTest::newRow("constructed larger values close to axis") << p << v @@ -322,9 +322,9 @@ void tst_QRay3D::contains_point_data() void tst_QRay3D::contains_point() { - QFETCH(QVector3D, origin); - QFETCH(QVector3D, direction); - QFETCH(QVector3D, point); + QFETCH(Vector3D, origin); + QFETCH(Vector3D, direction); + QFETCH(Vector3D, point); QFETCH(bool, contains); Qt3DRender::RayCasting::QRay3D line(origin, direction); @@ -338,9 +338,9 @@ void tst_QRay3D::contains_ray_data() void tst_QRay3D::contains_ray() { - QFETCH(QVector3D, origin); - QFETCH(QVector3D, direction); - QFETCH(QVector3D, point); + QFETCH(Vector3D, origin); + QFETCH(Vector3D, direction); + QFETCH(Vector3D, point); QFETCH(bool, contains); Qt3DRender::RayCasting::QRay3D line(origin, direction); @@ -355,7 +355,7 @@ void tst_QRay3D::contains_ray() QVERIFY(line2.contains(line)); // Different direction. - Qt3DRender::RayCasting::QRay3D line4(point, QVector3D(direction.y(), direction.x(), direction.z())); + Qt3DRender::RayCasting::QRay3D line4(point, Vector3D(direction.y(), direction.x(), direction.z())); QVERIFY(!line.contains(line4)); QVERIFY(!line4.contains(line)); } else { @@ -367,41 +367,41 @@ void tst_QRay3D::contains_ray() void tst_QRay3D::distance_data() { - QTest::addColumn<QVector3D>("origin"); - QTest::addColumn<QVector3D>("direction"); - QTest::addColumn<QVector3D>("point"); + QTest::addColumn<Vector3D>("origin"); + QTest::addColumn<Vector3D>("direction"); + QTest::addColumn<Vector3D>("point"); QTest::addColumn<float>("distance"); QTest::newRow("axis-x") - << QVector3D(6.0f, 0.0f, 0.0f) - << QVector3D(1.0f, 0.0f, 0.0f) - << QVector3D(0.0f, 0.0f, 0.0f) + << Vector3D(6.0f, 0.0f, 0.0f) + << Vector3D(1.0f, 0.0f, 0.0f) + << Vector3D(0.0f, 0.0f, 0.0f) << 0.0f; QTest::newRow("axis-x to 1") - << QVector3D(6.0f, 0.0f, 0.0f) - << QVector3D(1.0f, 0.0f, 0.0f) - << QVector3D(0.0f, 1.0f, 0.0f) + << Vector3D(6.0f, 0.0f, 0.0f) + << Vector3D(1.0f, 0.0f, 0.0f) + << Vector3D(0.0f, 1.0f, 0.0f) << 1.0f; QTest::newRow("neg-axis-y") - << QVector3D(0.0f, 6.0f, 0.0f) - << QVector3D(0.0f, -1.5f, 0.0f) - << QVector3D(0.0f, 100.0f, 0.0f) + << Vector3D(0.0f, 6.0f, 0.0f) + << Vector3D(0.0f, -1.5f, 0.0f) + << Vector3D(0.0f, 100.0f, 0.0f) << 0.0f; QTest::newRow("neg-axis-y to 2") - << QVector3D(0.0f, 6.0f, 0.0f) - << QVector3D(0.0f, -1.5f, 0.0f) - << QVector3D(2.0f, 0.0f, 0.0f) + << Vector3D(0.0f, 6.0f, 0.0f) + << Vector3D(0.0f, -1.5f, 0.0f) + << Vector3D(2.0f, 0.0f, 0.0f) << 2.0f; } void tst_QRay3D::distance() { - QFETCH(QVector3D, origin); - QFETCH(QVector3D, direction); - QFETCH(QVector3D, point); + QFETCH(Vector3D, origin); + QFETCH(Vector3D, direction); + QFETCH(Vector3D, point); QFETCH(float, distance); Qt3DRender::RayCasting::QRay3D line(origin, direction); @@ -410,9 +410,9 @@ void tst_QRay3D::distance() void tst_QRay3D::compare() { - Qt3DRender::RayCasting::QRay3D ray1(QVector3D(10, 20, 30), QVector3D(-3, -4, -5)); - Qt3DRender::RayCasting::QRay3D ray2(QVector3D(10, 20, 30), QVector3D(1.5f, 2.0f, 2.5f)); - Qt3DRender::RayCasting::QRay3D ray3(QVector3D(0, 20, 30), QVector3D(-3, -4, -5)); + Qt3DRender::RayCasting::QRay3D ray1(Vector3D(10, 20, 30), Vector3D(-3, -4, -5)); + Qt3DRender::RayCasting::QRay3D ray2(Vector3D(10, 20, 30), Vector3D(1.5f, 2.0f, 2.5f)); + Qt3DRender::RayCasting::QRay3D ray3(Vector3D(0, 20, 30), Vector3D(-3, -4, -5)); QVERIFY(ray1 == ray1); QVERIFY(!(ray1 != ray1)); QVERIFY(qFuzzyCompare(ray1, ray1)); @@ -427,7 +427,7 @@ void tst_QRay3D::compare() void tst_QRay3D::dataStream() { #ifndef QT_NO_DATASTREAM - Qt3DRender::RayCasting::QRay3D ray(QVector3D(1.0f, 2.0f, 3.0f), QVector3D(4.0f, 5.0f, 6.0f)); + Qt3DRender::RayCasting::QRay3D ray(Vector3D(1.0f, 2.0f, 3.0f), Vector3D(4.0f, 5.0f, 6.0f)); QByteArray data; { @@ -452,13 +452,17 @@ void tst_QRay3D::transform_data() void tst_QRay3D::transform() { - QFETCH(QVector3D, point); - QFETCH(QVector3D, direction); + QFETCH(Vector3D, point); + QFETCH(Vector3D, direction); - QMatrix4x4 m; - m.translate(-1.0f, 2.5f, 5.0f); - m.rotate(45.0f, 1.0f, 1.0f, 1.0f); - m.scale(23.5f); + Matrix4x4 m; + { + QMatrix4x4 c; + c.translate(-1.0f, 2.5f, 5.0f); + c.rotate(45.0f, 1.0f, 1.0f, 1.0f); + c.scale(23.5f); + m = Matrix4x4(c); + } Qt3DRender::RayCasting::QRay3D ray1(point, direction); Qt3DRender::RayCasting::QRay3D ray2(ray1); @@ -495,19 +499,19 @@ void tst_QRay3D::properties() qRegisterMetaType<Qt3DRender::RayCasting::QRay3D>(); - obj.setRay(Qt3DRender::RayCasting::QRay3D(QVector3D(1, 2, 3), QVector3D(4, 5, 6))); + obj.setRay(Qt3DRender::RayCasting::QRay3D(Vector3D(1, 2, 3), Vector3D(4, 5, 6))); Qt3DRender::RayCasting::QRay3D r = qvariant_cast<Qt3DRender::RayCasting::QRay3D>(obj.property("ray")); - QCOMPARE(r.origin(), QVector3D(1, 2, 3)); - QCOMPARE(r.direction(), QVector3D(4, 5, 6)); + QCOMPARE(r.origin(), Vector3D(1, 2, 3)); + QCOMPARE(r.direction(), Vector3D(4, 5, 6)); obj.setProperty("ray", qVariantFromValue - (Qt3DRender::RayCasting::QRay3D(QVector3D(-1, -2, -3), QVector3D(-4, -5, -6)))); + (Qt3DRender::RayCasting::QRay3D(Vector3D(-1, -2, -3), Vector3D(-4, -5, -6)))); r = qvariant_cast<Qt3DRender::RayCasting::QRay3D>(obj.property("ray")); - QCOMPARE(r.origin(), QVector3D(-1, -2, -3)); - QCOMPARE(r.direction(), QVector3D(-4, -5, -6)); + QCOMPARE(r.origin(), Vector3D(-1, -2, -3)); + QCOMPARE(r.direction(), Vector3D(-4, -5, -6)); } void tst_QRay3D::metaTypes() @@ -523,14 +527,14 @@ void tst_QRay3D::shouldNotAllowNullDirection() // GIVEN Qt3DRender::RayCasting::QRay3D ray; - QCOMPARE(ray.origin(), QVector3D(0, 0, 0)); - QCOMPARE(ray.direction(), QVector3D(0, 0, 1)); + QCOMPARE(ray.origin(), Vector3D(0, 0, 0)); + QCOMPARE(ray.direction(), Vector3D(0, 0, 1)); // WHEN - ray.setDirection(QVector3D(0, 0, 0)); + ray.setDirection(Vector3D(0, 0, 0)); // THEN - QCOMPARE(ray.direction(), QVector3D(0, 0, 1)); + QCOMPARE(ray.direction(), Vector3D(0, 0, 1)); } QTEST_APPLESS_MAIN(tst_QRay3D) diff --git a/tests/auto/render/raycasting/tst_raycasting.cpp b/tests/auto/render/raycasting/tst_raycasting.cpp index 0f3d04962..d14bcddcb 100644 --- a/tests/auto/render/raycasting/tst_raycasting.cpp +++ b/tests/auto/render/raycasting/tst_raycasting.cpp @@ -72,15 +72,15 @@ void tst_RayCasting::shouldIntersect_data() QTest::addColumn<Sphere>("sphere"); QTest::addColumn<bool>("shouldIntersect"); - QRay3D ray(QVector3D(1, 1, 1), QVector3D(0, 0, 1)); + QRay3D ray(Vector3D(1, 1, 1), Vector3D(0, 0, 1)); - Sphere sphere1(QVector3D(1, 1, 1), 2); - Sphere sphere2(QVector3D(0, 0, 0), 3); - Sphere sphere3(QVector3D(0, 1, 3), 1); - Sphere sphere4(QVector3D(4, 4, 5), 1); - Sphere sphere5(QVector3D(2, 2, 11), 5); - Sphere sphere6(QVector3D(2, 2, 13), 1); - Sphere sphere7(QVector3D(2, 2, 15), 5); + Sphere sphere1(Vector3D(1, 1, 1), 2); + Sphere sphere2(Vector3D(0, 0, 0), 3); + Sphere sphere3(Vector3D(0, 1, 3), 1); + Sphere sphere4(Vector3D(4, 4, 5), 1); + Sphere sphere5(Vector3D(2, 2, 11), 5); + Sphere sphere6(Vector3D(2, 2, 13), 1); + Sphere sphere7(Vector3D(2, 2, 15), 5); QTest::newRow("Ray starts inside sphere") << ray << sphere1 << true; QTest::newRow("Ray starts inside sphere") << ray << sphere2 << true; @@ -97,7 +97,7 @@ void tst_RayCasting::shouldIntersect() QFETCH(Sphere, sphere); QFETCH(bool, shouldIntersect); - QVector3D intersectionPoint; + Vector3D intersectionPoint; QCOMPARE(sphere.intersects(ray, &intersectionPoint), shouldIntersect); } @@ -206,16 +206,16 @@ void tst_RayCasting::shouldReturnHits_data() QTest::addColumn<QVector<QNodeId> >("hits"); QTest::addColumn<QAbstractCollisionQueryService::QueryMode >("queryMode"); - QRay3D ray(QVector3D(1, 1, 1), QVector3D(0, 0, 1)); + QRay3D ray(Vector3D(1, 1, 1), Vector3D(0, 0, 1)); this->boundingVolumes.clear(); - this->boundingVolumes.append(QVector<Sphere>() << Sphere(QVector3D(1, 1, 1), 3, QNodeId::createId()) - << Sphere(QVector3D(0, 0, 0), 3, QNodeId::createId()) - << Sphere(QVector3D(0, 1, 3), 1, QNodeId::createId()) - << Sphere(QVector3D(4, 4, 5), 1, QNodeId::createId()) - << Sphere(QVector3D(2, 2, 11), 5, QNodeId::createId()) - << Sphere(QVector3D(2, 2, 13), 1, QNodeId::createId()) - << Sphere(QVector3D(2, 2, 15), 5, QNodeId::createId())); + this->boundingVolumes.append(QVector<Sphere>() << Sphere(Vector3D(1, 1, 1), 3, QNodeId::createId()) + << Sphere(Vector3D(0, 0, 0), 3, QNodeId::createId()) + << Sphere(Vector3D(0, 1, 3), 1, QNodeId::createId()) + << Sphere(Vector3D(4, 4, 5), 1, QNodeId::createId()) + << Sphere(Vector3D(2, 2, 11), 5, QNodeId::createId()) + << Sphere(Vector3D(2, 2, 13), 1, QNodeId::createId()) + << Sphere(Vector3D(2, 2, 15), 5, QNodeId::createId())); QTest::newRow("All hits, One sphere intersect") << ray << (QVector<QBoundingVolume *> () << volumeAt(0) << volumeAt(3)) @@ -276,11 +276,11 @@ void tst_RayCasting::shouldReturnHits() void tst_RayCasting::shouldUseProvidedBoudingVolumes() { // GIVEN - QRay3D ray(QVector3D(1, 1, 1), QVector3D(0, 0, 1)); + QRay3D ray(Vector3D(1, 1, 1), Vector3D(0, 0, 1)); - Sphere sphere1(QVector3D(1, 1, 1), 3); - Sphere sphere3(QVector3D(0, 1, 3), 1); - Sphere sphere4(QVector3D(4, 4, 5), 1); + Sphere sphere1(Vector3D(1, 1, 1), 3); + Sphere sphere3(Vector3D(0, 1, 3), 1); + Sphere sphere4(Vector3D(4, 4, 5), 1); MyBoudingVolumesProvider provider(QVector<QBoundingVolume *>() << &sphere1 << &sphere4 << &sphere3); QVector<QNodeId> hits(QVector<QNodeId>() << sphere1.id() << sphere3.id()); @@ -325,10 +325,10 @@ void tst_RayCasting::mousePicking() // Window center on near plane QRay3D ray = Qt3DRender::Render::AbstractPickingJob::intersectionRay(viewport.center().toPoint(), - camera.viewMatrix(), - camera.projectionMatrix(), - viewport.toRect()); - Qt3DRender::Render::Sphere s(QVector3D(0.0f, 0.5f, 0.0f), 1.0f); + Matrix4x4(camera.viewMatrix()), + Matrix4x4(camera.projectionMatrix()), + viewport.toRect()); + Qt3DRender::Render::Sphere s(Vector3D(0.0f, 0.5f, 0.0f), 1.0f); // WHEN bool intersects = s.intersects(ray, nullptr); @@ -338,9 +338,9 @@ void tst_RayCasting::mousePicking() // WHEN ray = Qt3DRender::Render::AbstractPickingJob::intersectionRay(viewport.topLeft().toPoint(), - camera.viewMatrix(), - camera.projectionMatrix(), - viewport.toRect()); + Matrix4x4(camera.viewMatrix()), + Matrix4x4(camera.projectionMatrix()), + viewport.toRect()); intersects = s.intersects(ray, nullptr); // THEN @@ -348,9 +348,9 @@ void tst_RayCasting::mousePicking() // WHEN ray = Qt3DRender::Render::AbstractPickingJob::intersectionRay(viewport.topRight().toPoint(), - camera.viewMatrix(), - camera.projectionMatrix(), - viewport.toRect()); + Matrix4x4(camera.viewMatrix()), + Matrix4x4(camera.projectionMatrix()), + viewport.toRect()); intersects = s.intersects(ray, nullptr); // THEN @@ -358,9 +358,9 @@ void tst_RayCasting::mousePicking() // WHEN ray = Qt3DRender::Render::AbstractPickingJob::intersectionRay(viewport.bottomLeft().toPoint(), - camera.viewMatrix(), - camera.projectionMatrix(), - viewport.toRect()); + Matrix4x4(camera.viewMatrix()), + Matrix4x4(camera.projectionMatrix()), + viewport.toRect()); intersects = s.intersects(ray, nullptr); // THEN @@ -368,9 +368,9 @@ void tst_RayCasting::mousePicking() // WHEN ray = Qt3DRender::Render::AbstractPickingJob::intersectionRay(viewport.bottomRight().toPoint(), - camera.viewMatrix(), - camera.projectionMatrix(), - viewport.toRect()); + Matrix4x4(camera.viewMatrix()), + Matrix4x4(camera.projectionMatrix()), + viewport.toRect()); intersects = s.intersects(ray, nullptr); // THEN diff --git a/tests/auto/render/render.pro b/tests/auto/render/render.pro index 2fcebaa3c..ef147ba7f 100644 --- a/tests/auto/render/render.pro +++ b/tests/auto/render/render.pro @@ -24,14 +24,12 @@ qtConfig(private_tests) { attribute \ geometry \ geometryrenderer \ - raycasting \ qcameraselector \ qclearbuffers \ qframegraphnode \ qlayerfilter \ qabstractlight \ qenvironmentlight \ - qray3d \ qrenderpassfilter \ qrenderstate \ qrendertargetselector \ @@ -45,8 +43,6 @@ qtConfig(private_tests) { objectpicker \ # qboundingvolumedebug \ # boundingvolumedebug \ - trianglesextractor \ - triangleboundingvolume \ ddstextures \ shadercache \ layerfiltering \ @@ -113,9 +109,20 @@ qtConfig(private_tests) { qraycaster \ raycaster \ raycastingjob \ - qcamera + qcamera \ + renderbarrierjob QT_FOR_CONFIG = 3dcore-private + # TO DO: These could be restored to be executed in all cases + # when aligned-malloc.pri becomes part of the test framework + !qtConfig(qt3d-simd-avx2): { + SUBDIRS += \ + qray3d \ + raycasting \ + trianglesextractor \ + triangleboundingvolume \ + } + qtConfig(qt3d-extras) { SUBDIRS += \ qmaterial \ diff --git a/tests/auto/render/renderbarrierjob/renderbarrierjob.pro b/tests/auto/render/renderbarrierjob/renderbarrierjob.pro new file mode 100644 index 000000000..5a988144f --- /dev/null +++ b/tests/auto/render/renderbarrierjob/renderbarrierjob.pro @@ -0,0 +1,9 @@ +TEMPLATE = app + +TARGET = tst_renderbarrierjob + +QT += 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_renderbarrierjob.cpp diff --git a/tests/auto/render/renderbarrierjob/tst_renderbarrierjob.cpp b/tests/auto/render/renderbarrierjob/tst_renderbarrierjob.cpp new file mode 100644 index 000000000..e3b49edd4 --- /dev/null +++ b/tests/auto/render/renderbarrierjob/tst_renderbarrierjob.cpp @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** 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/QtTest> +#include <QMutex> +#include <QWaitCondition> +#include <QThread> +#include <Qt3DRender/private/renderbarrierjob_p.h> +#include <Qt3DRender/private/job_common_p.h> + +class TestRenderThread : public QThread +{ +public: + TestRenderThread(Qt3DRender::Render::RenderBarrierJobPtr barrier) + : m_barrier(barrier) + {} + + void run() override + { + m_started.store(1); + m_writeSemaphore.release(); + m_readSemaphore.acquire(); + + m_barrier->allowToProceed(); + m_released.store(1); + m_writeSemaphore.release(); + m_readSemaphore.acquire(); + + m_barrier->waitForDependencies(); + m_completed.store(1); + } + + Qt3DRender::Render::RenderBarrierJobPtr m_barrier; + QSemaphore m_writeSemaphore; + QSemaphore m_readSemaphore; + + QAtomicInt m_started; + QAtomicInt m_released; + QAtomicInt m_completed; +}; + +class tst_RenderBarrierJob : public QObject +{ + Q_OBJECT +public : + tst_RenderBarrierJob() {} + ~tst_RenderBarrierJob() {} + +private Q_SLOTS: + void shouldControlRenderThread() + { + // GIVEN a barrier (of any type) + auto barrier = Qt3DRender::Render::RenderBarrierJobPtr::create(Qt3DRender::Render::JobTypes::BeginDrawingBarrier); + TestRenderThread testThread(barrier); + + // THEN + QVERIFY(testThread.m_started.load() == 0); + QVERIFY(testThread.m_released.load() == 0); + QVERIFY(testThread.m_completed.load() == 0); + + // WHEN + testThread.start(); + testThread.m_writeSemaphore.acquire(); + + // THEN thread should have started + QVERIFY(testThread.m_started.load() == 1); + QVERIFY(testThread.m_released.load() == 0); + QVERIFY(testThread.m_completed.load() == 0); + testThread.m_readSemaphore.release(); + + // WHEN + testThread.m_writeSemaphore.acquire(); + + // THEN job should be released + QVERIFY(testThread.m_started.load() == 1); + QVERIFY(testThread.m_released.load() == 1); + QVERIFY(testThread.m_completed.load() == 0); + testThread.m_readSemaphore.release(); + + // WHEN job runs and we wait for thread + barrier->run(); + testThread.wait(); + + // THEN thread should be finished + QVERIFY(testThread.m_started.load() == 1); + QVERIFY(testThread.m_released.load() == 1); + QVERIFY(testThread.m_completed.load() == 1); + } +}; + +QTEST_MAIN(tst_RenderBarrierJob) + +#include "tst_renderbarrierjob.moc" diff --git a/tests/auto/render/renderer/tst_renderer.cpp b/tests/auto/render/renderer/tst_renderer.cpp index cfccf8b78..b941a2ac4 100644 --- a/tests/auto/render/renderer/tst_renderer.cpp +++ b/tests/auto/render/renderer/tst_renderer.cpp @@ -34,6 +34,9 @@ #include <Qt3DRender/private/viewportnode_p.h> #include <Qt3DRender/private/renderview_p.h> #include <Qt3DRender/private/renderviewbuilder_p.h> +#include <Qt3DRender/private/offscreensurfacehelper_p.h> +#include <Qt3DRender/private/loadtexturedatajob_p.h> +#include <Qt3DRender/private/renderbarrierjob_p.h> class tst_Renderer : public QObject { @@ -63,47 +66,62 @@ private Q_SLOTS: // NOTE: FilterCompatibleTechniqueJob and ShaderGathererJob cannot run because the context // is not initialized in this test - const int singleRenderViewJobCount = 11 + 1 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount(); + const int renderBarrierJobCount = 5; + // Barriers: readRenderQueueSize + // beginDrawing + // updateGLResources + // prepareCommandSubmission + // endDrawing + + const int renderViewJobCount = 13 + 1 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount(); // RenderViewBuilder renderViewJob, // renderableEntityFilterJob, // lightGatherJob, // computableEntityFilterJob, // syncRenderViewInitializationJob, - // syncFrustumCullingJob, // filterEntityByLayerJob, + // syncFilterEntityByLayerJob, + // syncFrustumCullingJob, // filterProximityJob, // setClearDrawBufferIndexJob, // frustumCullingJob, // syncRenderCommandBuldingJob, - // syncRenderViewCommandBuilderJob) - // n * (RenderViewCommandBuildJobs + MaterialGathererJobs + // syncRenderViewCommandBuilderJob + // n * RenderViewCommandBuildJobs + + const int flagIndependentRendererJobCount = 6; + // Flag independent: updateLevelOfDetailJob + // cleanupJob + // sendRenderCaptureJob + // sendBufferCaptureJob + // VAOGatherer + // updateSkinningPaletteJob + + const int flagIndependetRenderViewJobCount = renderViewJobCount - 2; + // Cached: filterEntityByLayerJob, + // syncFilterEntityByLayerJob, + // WHEN (nothing dirty, no buffers) QVector<Qt3DCore::QAspectJobPtr> jobs = renderer.renderBinJobs(); - // THEN (level + // THEN QCOMPARE(jobs.size(), - 1 + // updateLevelOfDetailJob - 1 + // cleanupJob - 1 + // sendRenderCaptureJob - 1 + // sendBufferCaptureJob - 1 + // VAOGatherer - 1 + // updateSkinningPaletteJob - singleRenderViewJobCount); // Only valid for the first call to renderBinJobs(), since subsequent calls won't have the renderqueue reset - + flagIndependetRenderViewJobCount + + renderBarrierJobCount + + flagIndependentRendererJobCount); // WHEN renderer.markDirty(Qt3DRender::Render::AbstractRenderer::EntityEnabledDirty, nullptr); jobs = renderer.renderBinJobs(); - // THEN (level + // THEN QCOMPARE(jobs.size(), - 1 + // updateLevelOfDetailJob - 1 + // cleanupJob - 1 + // sendRenderCaptureJob - 1 + // sendBufferCaptureJob - 1 + // VAOGatherer - 1 + // updateSkinningPaletteJob + flagIndependetRenderViewJobCount + + renderBarrierJobCount + + flagIndependentRendererJobCount + + 1 + // filterEntityByLayerJob + 1 + // syncFilterEntityByLayerJob 1); // EntityEnabledDirty renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); @@ -112,17 +130,14 @@ private Q_SLOTS: renderer.markDirty(Qt3DRender::Render::AbstractRenderer::TransformDirty, nullptr); jobs = renderer.renderBinJobs(); - // THEN (level + // THEN QCOMPARE(jobs.size(), - 1 + // updateLevelOfDetailJob - 1 + // cleanupJob - 1 + // sendRenderCaptureJob - 1 + // sendBufferCaptureJob - 1 + // VAOGatherer + flagIndependetRenderViewJobCount + + renderBarrierJobCount + + flagIndependentRendererJobCount + 1 + // WorldTransformJob 1 + // UpdateWorldBoundingVolume 1 + // UpdateShaderDataTransform - 1 + // updateSkinningPaletteJob 1); // ExpandBoundingVolumeJob renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); @@ -131,16 +146,13 @@ private Q_SLOTS: renderer.markDirty(Qt3DRender::Render::AbstractRenderer::GeometryDirty, nullptr); jobs = renderer.renderBinJobs(); - // THEN (level + // THEN QCOMPARE(jobs.size(), - 1 + // updateLevelOfDetailJob - 1 + // cleanupJob - 1 + // sendRenderCaptureJob - 1 + // sendBufferCaptureJob - 1 + // VAOGatherer + flagIndependetRenderViewJobCount + + renderBarrierJobCount + + flagIndependentRendererJobCount + 1 + // CalculateBoundingVolumeJob 1 + // UpdateMeshTriangleListJob - 1 + // updateSkinningPaletteJob 1); // ExpandBoundingVolumeJob renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); @@ -149,14 +161,11 @@ private Q_SLOTS: renderer.markDirty(Qt3DRender::Render::AbstractRenderer::BuffersDirty, nullptr); jobs = renderer.renderBinJobs(); - // THEN (level + // THEN QCOMPARE(jobs.size(), - 1 + // updateLevelOfDetailJob - 1 + // cleanupJob - 1 + // sendRenderCaptureJob - 1 + // sendBufferCaptureJob - 1 + // VAOGatherer - 1 + // updateSkinningPaletteJob + flagIndependetRenderViewJobCount + + renderBarrierJobCount + + flagIndependentRendererJobCount + 1); // BufferGathererJob renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); @@ -165,16 +174,26 @@ private Q_SLOTS: renderer.markDirty(Qt3DRender::Render::AbstractRenderer::TexturesDirty, nullptr); jobs = renderer.renderBinJobs(); - // THEN (level + // THEN QCOMPARE(jobs.size(), - 1 + // updateLevelOfDetailJob - 1 + // cleanupJob - 1 + // sendRenderCaptureJob - 1 + // sendBufferCaptureJob - 1 + // VAOGatherer - 1 + // TexturesGathererJob - 1 + // updateSkinningPaletteJob - 1); // SyncTexturesGathererJob + flagIndependetRenderViewJobCount + + renderBarrierJobCount + + flagIndependentRendererJobCount + + 1 + // LoadTextureDataJob + 1); // TexturesGathererJob + + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + + // WHEN + renderer.markDirty(Qt3DRender::Render::AbstractRenderer::SkeletonDataDirty, nullptr); + jobs = renderer.renderBinJobs(); + + // THEN + QCOMPARE(jobs.size(), + flagIndependetRenderViewJobCount + + renderBarrierJobCount + + flagIndependentRendererJobCount + + 1); // SyncSkeletonLoadingJob renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); @@ -182,28 +201,47 @@ private Q_SLOTS: renderer.markDirty(Qt3DRender::Render::AbstractRenderer::AllDirty, nullptr); jobs = renderer.renderBinJobs(); - // THEN (level + // THEN QCOMPARE(jobs.size(), - 1 + // updateLevelOfDetailJob - 1 + // cleanupJob - 1 + // sendRenderCaptureJob - 1 + // sendBufferCaptureJob - 1 + // VAOGatherer - 1 + // EntityEnabledDirty + renderViewJobCount + + renderBarrierJobCount + + flagIndependentRendererJobCount + + 1 + // UpdateTreeEnablee 1 + // WorldTransformJob 1 + // UpdateWorldBoundingVolume 1 + // UpdateShaderDataTransform - 1 + // ExpandBoundingVolumeJob 1 + // CalculateBoundingVolumeJob 1 + // UpdateMeshTriangleListJob + 1 + // ExpandBoundingVolumeJob 1 + // BufferGathererJob + 1 + // LoadTextureDataJob 1 + // TexturesGathererJob - 1 + // updateSkinningPaletteJob - 1); // SyncTexturesGathererJob + 1 + // SyncSkeletonLoadingJob + 1 + // FilterCompatibleTechniqueJob + 1 + // ShaderGathererJob + Qt3DRender::Render::RenderViewBuilder::optimalJobCount() + // MaterialGathererJobs + 1); // syncMaterialGathererJob renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + } + + void checkRenderBarrierJobDependencies() + { + // GIVEN + Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + + // THEN + // internal dependencies + QVERIFY(renderer.beginDrawingBarrierJob()->dependencies().contains(renderer.readRenderQueueSizeBarrierJob())); + QVERIFY(renderer.updateGLResourcesBarrierJob()->dependencies().contains(renderer.beginDrawingBarrierJob())); + QVERIFY(renderer.prepareCommandSubmissionBarrierJob()->dependencies().contains(renderer.updateGLResourcesBarrierJob())); + QVERIFY(renderer.endDrawingBarrierJob()->dependencies().contains(renderer.prepareCommandSubmissionBarrierJob())); + QVERIFY(renderer.filterCompatibleTechniqueJob()->dependencies().contains(renderer.beginDrawingBarrierJob())); + QVERIFY(renderer.loadTextureJob()->dependencies().contains(renderer.updateGLResourcesBarrierJob())); + QVERIFY(renderer.prepareCommandSubmissionBarrierJob()->dependencies().contains(renderer.loadTextureJob())); + QVERIFY(renderer.updateGLResourcesBarrierJob()->dependencies().contains(renderer.filterCompatibleTechniqueJob())); } }; diff --git a/tests/auto/render/renderqueue/renderqueue.pro b/tests/auto/render/renderqueue/renderqueue.pro index 92e675285..945fe4cf4 100644 --- a/tests/auto/render/renderqueue/renderqueue.pro +++ b/tests/auto/render/renderqueue/renderqueue.pro @@ -7,3 +7,5 @@ QT += 3dcore 3dcore-private 3drender 3drender-private testlib CONFIG += testcase SOURCES += tst_renderqueue.cpp + +include(../../core/common/common.pri) diff --git a/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp b/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp index d18b270c5..1bdf20170 100644 --- a/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp +++ b/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp @@ -49,6 +49,7 @@ #include <Qt3DRender/private/qrenderaspect_p.h> #include <Qt3DRender/private/nodemanagers_p.h> #include <Qt3DRender/private/managers_p.h> +#include <Qt3DRender/private/renderbarrierjob_p.h> QT_BEGIN_NAMESPACE @@ -306,21 +307,25 @@ private Q_SLOTS: QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(renderViewBuilder.syncFrustumCullingJob())); QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob())); - QCOMPARE(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().size(), renderViewBuilder.materialGathererJobs().size() + 6); + QCOMPARE(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().size(), renderViewBuilder.materialGathererJobs().size() + 7); QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.renderableEntityFilterJob())); QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.computableEntityFilterJob())); QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.filterProximityJob())); QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.lightGathererJob())); QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.frustumCullingJob())); + QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(testAspect.renderer()->updateGLResourcesBarrierJob())); for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) { QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(materialGatherer)); } // Step 5 for (const auto renderViewBuilderJob : renderViewBuilder.renderViewBuilderJobs()) { - QCOMPARE(renderViewBuilderJob->dependencies().size(), 1); - QCOMPARE(renderViewBuilderJob->dependencies().first().data(), renderViewBuilder.syncRenderCommandBuildingJob().data()); + QCOMPARE(renderViewBuilderJob->dependencies().size(), 4); + QVERIFY(renderViewBuilderJob->dependencies().contains(renderViewBuilder.syncRenderCommandBuildingJob())); + QVERIFY(renderViewBuilderJob->dependencies().contains(testAspect.renderer()->updateSkinningPaletteJob())); + QVERIFY(renderViewBuilderJob->dependencies().contains(testAspect.renderer()->updateWorldBoundingVolumeJob())); + QVERIFY(renderViewBuilderJob->dependencies().contains(testAspect.renderer()->updateShaderDataTransformJob())); } // Step 6 @@ -378,7 +383,7 @@ private Q_SLOTS: QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(renderViewBuilder.syncFrustumCullingJob())); QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob())); - QCOMPARE(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().size(), renderViewBuilder.materialGathererJobs().size() + 7); + QCOMPARE(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().size(), renderViewBuilder.materialGathererJobs().size() + 8); QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.renderableEntityFilterJob())); QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.computableEntityFilterJob())); @@ -386,14 +391,18 @@ private Q_SLOTS: QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.lightGathererJob())); QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.frustumCullingJob())); QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.filterProximityJob())); + QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(testAspect.renderer()->updateGLResourcesBarrierJob())); for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) { QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(materialGatherer)); } // Step 5 for (const auto renderViewBuilderJob : renderViewBuilder.renderViewBuilderJobs()) { - QCOMPARE(renderViewBuilderJob->dependencies().size(), 1); - QCOMPARE(renderViewBuilderJob->dependencies().first().data(), renderViewBuilder.syncRenderCommandBuildingJob().data()); + QCOMPARE(renderViewBuilderJob->dependencies().size(), 4); + QVERIFY(renderViewBuilderJob->dependencies().contains(renderViewBuilder.syncRenderCommandBuildingJob())); + QVERIFY(renderViewBuilderJob->dependencies().contains(testAspect.renderer()->updateSkinningPaletteJob())); + QVERIFY(renderViewBuilderJob->dependencies().contains(testAspect.renderer()->updateWorldBoundingVolumeJob())); + QVERIFY(renderViewBuilderJob->dependencies().contains(testAspect.renderer()->updateShaderDataTransformJob())); } // Step 6 @@ -562,14 +571,14 @@ private Q_SLOTS: renderViewBuilder.buildJobHierachy(); // THEN - QCOMPARE(renderViewBuilder.frustumCullingJob()->viewProjection(), QMatrix4x4()); + QCOMPARE(renderViewBuilder.frustumCullingJob()->viewProjection(), Matrix4x4()); // WHEN renderViewBuilder.renderViewJob()->run(); renderViewBuilder.syncFrustumCullingJob()->run(); // THEN - QCOMPARE(renderViewBuilder.frustumCullingJob()->viewProjection(), camera->projectionMatrix() * camera->viewMatrix()); + QCOMPARE(convertToQMatrix4x4(renderViewBuilder.frustumCullingJob()->viewProjection()), camera->projectionMatrix() * camera->viewMatrix()); } void checkRemoveEntitiesNotInSubset() diff --git a/tests/auto/render/renderviews/tst_renderviews.cpp b/tests/auto/render/renderviews/tst_renderviews.cpp index d941126e2..8ff1a584a 100644 --- a/tests/auto/render/renderviews/tst_renderviews.cpp +++ b/tests/auto/render/renderviews/tst_renderviews.cpp @@ -59,23 +59,6 @@ private Q_SLOTS: } - void checkRenderViewDoesNotLeak() - { - QSKIP("Allocated Disabled"); - // GIVEN - Qt3DCore::QFrameAllocator allocator(192, 16, 128); - RenderView *rv = allocator.allocate<RenderView>(); - - // THEN - QVERIFY(!allocator.isEmpty()); - - // WHEN - delete rv; - - // THEN - QVERIFY(allocator.isEmpty()); - } - void checkRenderViewInitialState() { // GIVEN diff --git a/tests/auto/render/renderviewutils/tst_renderviewutils.cpp b/tests/auto/render/renderviewutils/tst_renderviewutils.cpp index 81d0ee4a2..247c5e0a3 100644 --- a/tests/auto/render/renderviewutils/tst_renderviewutils.cpp +++ b/tests/auto/render/renderviewutils/tst_renderviewutils.cpp @@ -711,17 +711,25 @@ void tst_RenderViewUtils::transformedProperties() QScopedPointer<Qt3DRender::Render::ShaderDataManager> manager(new Qt3DRender::Render::ShaderDataManager()); // WHEN - const QVector3D position = QVector3D(15.0f, -5.0f, 10.0f); - QMatrix4x4 worldMatrix; - QMatrix4x4 viewMatrix; - - worldMatrix.translate(-3.0f, 2.0f, 7.5f); - viewMatrix.translate(9.0f, 6.0f, 12.0f); + const Vector3D position = Vector3D(15.0f, -5.0f, 10.0f); + const QVector3D positionQt = convertToQVector3D(position); + Matrix4x4 worldMatrix; + { + QMatrix4x4 m; + m.translate(-3.0f, 2.0f, 7.5f); + worldMatrix = Matrix4x4(m); + } + Matrix4x4 viewMatrix; + { + QMatrix4x4 m; + m.translate(9.0f, 6.0f, 12.0f); + viewMatrix = Matrix4x4(m); + } - shaderData->setProperty("position0", position); - shaderData->setProperty("position1", position); - shaderData->setProperty("position2", position); - shaderData->setProperty("position3", position); + shaderData->setProperty("position0", positionQt); + shaderData->setProperty("position1", positionQt); + shaderData->setProperty("position2", positionQt); + shaderData->setProperty("position3", positionQt); shaderData->setProperty("position1Transformed", Qt3DRender::Render::ShaderData::ModelToEye); shaderData->setProperty("position2Transformed", Qt3DRender::Render::ShaderData::ModelToWorld); shaderData->setProperty("position3Transformed", Qt3DRender::Render::ShaderData::ModelToWorldDirection); @@ -737,16 +745,16 @@ void tst_RenderViewUtils::transformedProperties() // WHEN backendShaderData->updateWorldTransform(worldMatrix); - const QVector3D position1Value = backendShaderData->getTransformedProperty(QStringLiteral("position1"), viewMatrix).value<QVector3D>(); - const QVector3D position2Value = backendShaderData->getTransformedProperty(QStringLiteral("position2"), viewMatrix).value<QVector3D>(); - const QVector3D position3Value = backendShaderData->getTransformedProperty(QStringLiteral("position3"), viewMatrix).value<QVector3D>(); + const Vector3D position1Value = backendShaderData->getTransformedProperty(QStringLiteral("position1"), viewMatrix).value<Vector3D>(); + const Vector3D position2Value = backendShaderData->getTransformedProperty(QStringLiteral("position2"), viewMatrix).value<Vector3D>(); + const Vector3D position3Value = backendShaderData->getTransformedProperty(QStringLiteral("position3"), viewMatrix).value<Vector3D>(); const QVariant position0Value = backendShaderData->getTransformedProperty(QStringLiteral("position0"), viewMatrix); // THEN QCOMPARE(position0Value, QVariant()); QCOMPARE(position1Value, viewMatrix * worldMatrix * position); QCOMPARE(position2Value, worldMatrix * position); - QCOMPARE(position3Value, (worldMatrix * QVector4D(position, 0.0f)).toVector3D()); + QCOMPARE(position3Value, Vector3D((worldMatrix * Vector4D(position, 0.0f)))); } void tst_RenderViewUtils::shouldNotifyDynamicPropertyChanges() diff --git a/tests/auto/render/segmentvisitor/tst_segmentvisitor.cpp b/tests/auto/render/segmentvisitor/tst_segmentvisitor.cpp index 2c3f3f7c9..da420e1ac 100644 --- a/tests/auto/render/segmentvisitor/tst_segmentvisitor.cpp +++ b/tests/auto/render/segmentvisitor/tst_segmentvisitor.cpp @@ -49,7 +49,7 @@ public: } - virtual void visit(uint andx, const QVector3D &a, uint bndx, const QVector3D &b) + virtual void visit(uint andx, const Vector3D &a, uint bndx, const Vector3D &b) { m_segments.push_back(TestSegment(andx, a, bndx, b)); } @@ -69,7 +69,7 @@ public: return m_segments.size(); } - bool verifySegment(uint segment, uint andx, uint bndx, QVector3D a, QVector3D b) const + bool verifySegment(uint segment, uint andx, uint bndx, Vector3D a, Vector3D b) const { if (segment >= uint(m_segments.size())) return false; @@ -87,13 +87,13 @@ private: struct TestSegment { uint abcndx[2]; - QVector3D abc[2]; + Vector3D abc[2]; TestSegment() { abcndx[0] = abcndx[1] = uint(-1); } - TestSegment(uint andx, const QVector3D &a, uint bndx, const QVector3D &b) + TestSegment(uint andx, const Vector3D &a, uint bndx, const Vector3D &b) { abcndx[0] = andx; abcndx[1] = bndx; @@ -218,9 +218,9 @@ private Q_SLOTS: // THEN QCOMPARE(visitor.segmentCount(), uint(3)); - QVERIFY(visitor.verifySegment(0, 0,1, QVector3D(0,0,1), QVector3D(1,0,0))); - QVERIFY(visitor.verifySegment(1, 2,3, QVector3D(0,1,0), QVector3D(0,0,1))); - QVERIFY(visitor.verifySegment(2, 4,5, QVector3D(1,0,0), QVector3D(0,1,0))); + QVERIFY(visitor.verifySegment(0, 0,1, Vector3D(0,0,1), Vector3D(1,0,0))); + QVERIFY(visitor.verifySegment(1, 2,3, Vector3D(0,1,0), Vector3D(0,0,1))); + QVERIFY(visitor.verifySegment(2, 4,5, Vector3D(1,0,0), Vector3D(0,1,0))); } void testVisitSegmentsIndexed() @@ -318,11 +318,11 @@ private Q_SLOTS: // THEN QCOMPARE(visitor.segmentCount(), uint(5)); - QVERIFY(visitor.verifySegment(0, 0,1, QVector3D(0,0,0), QVector3D(1,0,0))); - QVERIFY(visitor.verifySegment(1, 1,2, QVector3D(1,0,0), QVector3D(1,1,0))); - QVERIFY(visitor.verifySegment(2, 2,3, QVector3D(1,1,0), QVector3D(0,1,0))); - QVERIFY(visitor.verifySegment(3, 0,2, QVector3D(0,0,0), QVector3D(1,1,0))); - QVERIFY(visitor.verifySegment(4, 1,3, QVector3D(1,0,0), QVector3D(0,1,0))); + QVERIFY(visitor.verifySegment(0, 0,1, Vector3D(0,0,0), Vector3D(1,0,0))); + QVERIFY(visitor.verifySegment(1, 1,2, Vector3D(1,0,0), Vector3D(1,1,0))); + QVERIFY(visitor.verifySegment(2, 2,3, Vector3D(1,1,0), Vector3D(0,1,0))); + QVERIFY(visitor.verifySegment(3, 0,2, Vector3D(0,0,0), Vector3D(1,1,0))); + QVERIFY(visitor.verifySegment(4, 1,3, Vector3D(1,0,0), Vector3D(0,1,0))); } void testVisitLineStrip() @@ -387,9 +387,9 @@ private Q_SLOTS: // THEN QCOMPARE(visitor.segmentCount(), uint(3)); - QVERIFY(visitor.verifySegment(0, 0,1, QVector3D(0,0,0), QVector3D(1,0,0))); - QVERIFY(visitor.verifySegment(1, 1,2, QVector3D(1,0,0), QVector3D(1,1,0))); - QVERIFY(visitor.verifySegment(2, 2,3, QVector3D(1,1,0), QVector3D(0,1,0))); + QVERIFY(visitor.verifySegment(0, 0,1, Vector3D(0,0,0), Vector3D(1,0,0))); + QVERIFY(visitor.verifySegment(1, 1,2, Vector3D(1,0,0), Vector3D(1,1,0))); + QVERIFY(visitor.verifySegment(2, 2,3, Vector3D(1,1,0), Vector3D(0,1,0))); } void testVisitListStripIndexed() @@ -481,9 +481,9 @@ private Q_SLOTS: // THEN QCOMPARE(visitor.segmentCount(), uint(3)); - QVERIFY(visitor.verifySegment(0, 0,1, QVector3D(0,0,0), QVector3D(1,0,0))); - QVERIFY(visitor.verifySegment(1, 1,2, QVector3D(1,0,0), QVector3D(1,1,0))); - QVERIFY(visitor.verifySegment(2, 2,3, QVector3D(1,1,0), QVector3D(0,1,0))); + QVERIFY(visitor.verifySegment(0, 0,1, Vector3D(0,0,0), Vector3D(1,0,0))); + QVERIFY(visitor.verifySegment(1, 1,2, Vector3D(1,0,0), Vector3D(1,1,0))); + QVERIFY(visitor.verifySegment(2, 2,3, Vector3D(1,1,0), Vector3D(0,1,0))); } void testVisitLineLoop() @@ -548,10 +548,10 @@ private Q_SLOTS: // THEN QCOMPARE(visitor.segmentCount(), uint(4)); - QVERIFY(visitor.verifySegment(0, 0,1, QVector3D(0,0,0), QVector3D(1,0,0))); - QVERIFY(visitor.verifySegment(1, 1,2, QVector3D(1,0,0), QVector3D(1,1,0))); - QVERIFY(visitor.verifySegment(2, 2,3, QVector3D(1,1,0), QVector3D(0,1,0))); - QVERIFY(visitor.verifySegment(3, 3,0, QVector3D(0,1,0), QVector3D(0,0,0))); + QVERIFY(visitor.verifySegment(0, 0,1, Vector3D(0,0,0), Vector3D(1,0,0))); + QVERIFY(visitor.verifySegment(1, 1,2, Vector3D(1,0,0), Vector3D(1,1,0))); + QVERIFY(visitor.verifySegment(2, 2,3, Vector3D(1,1,0), Vector3D(0,1,0))); + QVERIFY(visitor.verifySegment(3, 3,0, Vector3D(0,1,0), Vector3D(0,0,0))); } void testVisitLineLoopIndexed() @@ -643,10 +643,10 @@ private Q_SLOTS: // THEN QCOMPARE(visitor.segmentCount(), uint(4)); - QVERIFY(visitor.verifySegment(0, 0,1, QVector3D(0,0,0), QVector3D(1,0,0))); - QVERIFY(visitor.verifySegment(1, 1,2, QVector3D(1,0,0), QVector3D(1,1,0))); - QVERIFY(visitor.verifySegment(2, 2,3, QVector3D(1,1,0), QVector3D(0,1,0))); - QVERIFY(visitor.verifySegment(3, 3,0, QVector3D(0,1,0), QVector3D(0,0,0))); + QVERIFY(visitor.verifySegment(0, 0,1, Vector3D(0,0,0), Vector3D(1,0,0))); + QVERIFY(visitor.verifySegment(1, 1,2, Vector3D(1,0,0), Vector3D(1,1,0))); + QVERIFY(visitor.verifySegment(2, 2,3, Vector3D(1,1,0), Vector3D(0,1,0))); + QVERIFY(visitor.verifySegment(3, 3,0, Vector3D(0,1,0), Vector3D(0,0,0))); } void testVisitLineAdjacency() @@ -712,7 +712,7 @@ private Q_SLOTS: // THEN QCOMPARE(visitor.segmentCount(), uint(1)); - QVERIFY(visitor.verifySegment(0, 1, 2, QVector3D(1,0,0), QVector3D(0,1,0))); + QVERIFY(visitor.verifySegment(0, 1, 2, Vector3D(1,0,0), Vector3D(0,1,0))); } void testVisitLinesAdjacencyIndexed() @@ -805,7 +805,7 @@ private Q_SLOTS: // THEN QCOMPARE(visitor.segmentCount(), uint(1)); - QVERIFY(visitor.verifySegment(0, 1, 2, QVector3D(1,0,0), QVector3D(0,1,0))); + QVERIFY(visitor.verifySegment(0, 1, 2, Vector3D(1,0,0), Vector3D(0,1,0))); } }; diff --git a/tests/auto/render/shadercache/tst_shadercache.cpp b/tests/auto/render/shadercache/tst_shadercache.cpp index 1c70d4405..49628ef0f 100644 --- a/tests/auto/render/shadercache/tst_shadercache.cpp +++ b/tests/auto/render/shadercache/tst_shadercache.cpp @@ -131,6 +131,19 @@ void tst_ShaderCache::value() auto dnaC = ProgramDNA(54321); auto uncachedProgram = cache.getShaderProgramAndAddRef(dnaC, nodeIdB); QVERIFY(uncachedProgram == nullptr); + + cache.clear(); + // Test inserting nullptr. + cache.insert(dnaA, nodeIdA, nullptr); + bool wasPresent = false; + cachedProgramA = cache.getShaderProgramAndAddRef(dnaA, nodeIdA, &wasPresent); + QCOMPARE(wasPresent, true); + QCOMPARE(cachedProgramA, nullptr); + cache.clear(); + // Test wasPresent==false. + cachedProgramB = cache.getShaderProgramAndAddRef(dnaB, nodeIdB, &wasPresent); + QCOMPARE(wasPresent, false); + QCOMPARE(cachedProgramB, nullptr); } void tst_ShaderCache::removeRef() diff --git a/tests/auto/render/transform/tst_transform.cpp b/tests/auto/render/transform/tst_transform.cpp index ebb27953d..151baff76 100644 --- a/tests/auto/render/transform/tst_transform.cpp +++ b/tests/auto/render/transform/tst_transform.cpp @@ -49,7 +49,7 @@ private Q_SLOTS: // THEN QCOMPARE(backendTransform.isEnabled(), false); QVERIFY(backendTransform.peerId().isNull()); - QCOMPARE(backendTransform.transformMatrix(), QMatrix4x4()); + QCOMPARE(convertToQMatrix4x4(backendTransform.transformMatrix()), QMatrix4x4()); } void checkCleanupState() @@ -71,7 +71,7 @@ private Q_SLOTS: // THEN QCOMPARE(backendTransform.isEnabled(), false); - QCOMPARE(backendTransform.transformMatrix(), QMatrix4x4()); + QCOMPARE(convertToQMatrix4x4(backendTransform.transformMatrix()), QMatrix4x4()); QCOMPARE(backendTransform.rotation(), QQuaternion()); QCOMPARE(backendTransform.scale(), QVector3D()); QCOMPARE(backendTransform.translation(), QVector3D()); @@ -93,7 +93,7 @@ private Q_SLOTS: // THEN QCOMPARE(backendTransform.isEnabled(), true); QCOMPARE(backendTransform.peerId(), transform.id()); - QCOMPARE(backendTransform.transformMatrix(), transform.matrix()); + QCOMPARE(convertToQMatrix4x4(backendTransform.transformMatrix()), transform.matrix()); QCOMPARE(backendTransform.rotation(), transform.rotation()); QCOMPARE(backendTransform.scale(), transform.scale3D()); QCOMPARE(backendTransform.translation(), transform.translation()); diff --git a/tests/auto/render/triangleboundingvolume/triangleboundingvolume.pro b/tests/auto/render/triangleboundingvolume/triangleboundingvolume.pro index e88a997e2..dcbb2c17f 100644 --- a/tests/auto/render/triangleboundingvolume/triangleboundingvolume.pro +++ b/tests/auto/render/triangleboundingvolume/triangleboundingvolume.pro @@ -7,3 +7,4 @@ QT += 3dcore 3dcore-private 3drender 3drender-private testlib CONFIG += testcase SOURCES += tst_triangleboundingvolume.cpp + diff --git a/tests/auto/render/triangleboundingvolume/tst_triangleboundingvolume.cpp b/tests/auto/render/triangleboundingvolume/tst_triangleboundingvolume.cpp index df375e777..b037c461f 100644 --- a/tests/auto/render/triangleboundingvolume/tst_triangleboundingvolume.cpp +++ b/tests/auto/render/triangleboundingvolume/tst_triangleboundingvolume.cpp @@ -47,43 +47,43 @@ private Q_SLOTS: { // GIVEN Qt3DRender::Render::TriangleBoundingVolume volume = Qt3DRender::Render::TriangleBoundingVolume(Qt3DCore::QNodeId(), - QVector3D(), - QVector3D(), - QVector3D()); + Vector3D(), + Vector3D(), + Vector3D()); // THEN QCOMPARE(volume.id(), Qt3DCore::QNodeId()); - QCOMPARE(volume.a(), QVector3D()); - QCOMPARE(volume.b(), QVector3D()); - QCOMPARE(volume.c(), QVector3D()); + QCOMPARE(volume.a(), Vector3D()); + QCOMPARE(volume.b(), Vector3D()); + QCOMPARE(volume.c(), Vector3D()); QCOMPARE(volume.type(), Qt3DRender::RayCasting::QBoundingVolume::Triangle); } void transformed_data() { - QTest::addColumn<QVector3D>("a"); - QTest::addColumn<QVector3D>("b"); - QTest::addColumn<QVector3D>("c"); + QTest::addColumn<Vector3D>("a"); + QTest::addColumn<Vector3D>("b"); + QTest::addColumn<Vector3D>("c"); - QTest::addColumn<QVector3D>("transformedA"); - QTest::addColumn<QVector3D>("transformedB"); - QTest::addColumn<QVector3D>("transformedC"); + QTest::addColumn<Vector3D>("transformedA"); + QTest::addColumn<Vector3D>("transformedB"); + QTest::addColumn<Vector3D>("transformedC"); QTest::newRow("onFarPlane") - << QVector3D(-1.0, 1.0, 0.0) - << QVector3D(0.0, -1.0, 0.0) - << QVector3D(1.0, 1.0, 0.0) - << QVector3D(-1.0, 1.0, -40.0) - << QVector3D(0.0, -1.0, -40.0) - << QVector3D(1.0, 1.0, -40.0); + << Vector3D(-1.0, 1.0, 0.0) + << Vector3D(0.0, -1.0, 0.0) + << Vector3D(1.0, 1.0, 0.0) + << Vector3D(-1.0, 1.0, -40.0) + << Vector3D(0.0, -1.0, -40.0) + << Vector3D(1.0, 1.0, -40.0); QTest::newRow("onNearPlane") - << QVector3D(-1.0, 1.0, 40.0) - << QVector3D(0.0, -1.0, 40.0) - << QVector3D(1.0, 1.0, 40.0) - << QVector3D(-1.0, 1.0, 0.0) - << QVector3D(0.0, -1.0, 0.0) - << QVector3D(1.0, 1.0, 0.0); + << Vector3D(-1.0, 1.0, 40.0) + << Vector3D(0.0, -1.0, 40.0) + << Vector3D(1.0, 1.0, 40.0) + << Vector3D(-1.0, 1.0, 0.0) + << Vector3D(0.0, -1.0, 0.0) + << Vector3D(1.0, 1.0, 0.0); } @@ -91,12 +91,12 @@ private Q_SLOTS: void transformed() { // GIVEN - QFETCH(QVector3D, a); - QFETCH(QVector3D, b); - QFETCH(QVector3D, c); - QFETCH(QVector3D, transformedA); - QFETCH(QVector3D, transformedB); - QFETCH(QVector3D, transformedC); + QFETCH(Vector3D, a); + QFETCH(Vector3D, b); + QFETCH(Vector3D, c); + QFETCH(Vector3D, transformedA); + QFETCH(Vector3D, transformedB); + QFETCH(Vector3D, transformedC); Qt3DRender::Render::TriangleBoundingVolume volume(Qt3DCore::QNodeId(), a, b, @@ -111,7 +111,7 @@ private Q_SLOTS: camera.setUpVector(QVector3D(0.0f, 1.0f, 0.0f)); camera.setViewCenter(QVector3D(0.0f, 0.0f, 0.0f)); - const QMatrix4x4 viewMatrix = camera.viewMatrix(); + const Matrix4x4 viewMatrix(camera.viewMatrix()); // WHEN volume.transform(viewMatrix); @@ -125,61 +125,61 @@ private Q_SLOTS: void intersects_data() { QTest::addColumn<Qt3DRender::RayCasting::QRay3D>("ray"); - QTest::addColumn<QVector3D>("a"); - QTest::addColumn<QVector3D>("b"); - QTest::addColumn<QVector3D>("c"); - QTest::addColumn<QVector3D>("uvw"); + QTest::addColumn<Vector3D>("a"); + QTest::addColumn<Vector3D>("b"); + QTest::addColumn<Vector3D>("c"); + QTest::addColumn<Vector3D>("uvw"); QTest::addColumn<float>("t"); QTest::addColumn<bool>("isIntersecting"); const float farPlaneDistance = 40.0; QTest::newRow("halfway_center") - << Qt3DRender::RayCasting::QRay3D(QVector3D(), QVector3D(0.0, 0.0, 1.0), farPlaneDistance) - << QVector3D(3.0, 1.5, 20.0) - << QVector3D(0.0, -1.5, 20.0) - << QVector3D(-3, 1.5, 20.0) - << QVector3D(0.25, 0.5, 0.25) + << Qt3DRender::RayCasting::QRay3D(Vector3D(), Vector3D(0.0, 0.0, 1.0), farPlaneDistance) + << Vector3D(3.0, 1.5, 20.0) + << Vector3D(0.0, -1.5, 20.0) + << Vector3D(-3, 1.5, 20.0) + << Vector3D(0.25, 0.5, 0.25) << 0.5f << true; QTest::newRow("miss_halfway_center_too_short") - << Qt3DRender::RayCasting::QRay3D(QVector3D(), QVector3D(0.0, 0.0, 1.0), farPlaneDistance * 0.25f) - << QVector3D(3.0, 1.5, 20.0) - << QVector3D(0.0, -1.5, 20.0) - << QVector3D(-3, 1.5, 20.0) - << QVector3D() + << Qt3DRender::RayCasting::QRay3D(Vector3D(), Vector3D(0.0, 0.0, 1.0), farPlaneDistance * 0.25f) + << Vector3D(3.0, 1.5, 20.0) + << Vector3D(0.0, -1.5, 20.0) + << Vector3D(-3, 1.5, 20.0) + << Vector3D() << 0.0f << false; QTest::newRow("far_center") - << Qt3DRender::RayCasting::QRay3D(QVector3D(), QVector3D(0.0, 0.0, 1.0), farPlaneDistance) - << QVector3D(3.0, 1.5, 40.0) - << QVector3D(0.0, -1.5, 40.0) - << QVector3D(-3, 1.5, 40.0) - << QVector3D(0.25, 0.5, 0.25) + << Qt3DRender::RayCasting::QRay3D(Vector3D(), Vector3D(0.0, 0.0, 1.0), farPlaneDistance) + << Vector3D(3.0, 1.5, 40.0) + << Vector3D(0.0, -1.5, 40.0) + << Vector3D(-3, 1.5, 40.0) + << Vector3D(0.25, 0.5, 0.25) << 1.0f << true; QTest::newRow("near_center") - << Qt3DRender::RayCasting::QRay3D(QVector3D(), QVector3D(0.0, 0.0, 1.0), 1.0f) - << QVector3D(3.0, 1.5, 0.0) - << QVector3D(0.0, -1.5, 0.0) - << QVector3D(-3, 1.5, 0.0) - << QVector3D(0.25, 0.5, 0.25) + << Qt3DRender::RayCasting::QRay3D(Vector3D(), Vector3D(0.0, 0.0, 1.0), 1.0f) + << Vector3D(3.0, 1.5, 0.0) + << Vector3D(0.0, -1.5, 0.0) + << Vector3D(-3, 1.5, 0.0) + << Vector3D(0.25, 0.5, 0.25) << 0.0f << true; QTest::newRow("above_miss_center") - << Qt3DRender::RayCasting::QRay3D(QVector3D(0.0, 2.0, 0.0), QVector3D(0.0, 2.0, 1.0), 1.0f) - << QVector3D(3.0, 1.5, 0.0) - << QVector3D(0.0, -1.5, 0.0) - << QVector3D(-3, 1.5, 0.0) - << QVector3D() + << Qt3DRender::RayCasting::QRay3D(Vector3D(0.0, 2.0, 0.0), Vector3D(0.0, 2.0, 1.0), 1.0f) + << Vector3D(3.0, 1.5, 0.0) + << Vector3D(0.0, -1.5, 0.0) + << Vector3D(-3, 1.5, 0.0) + << Vector3D() << 0.0f << false; QTest::newRow("below_miss_center") - << Qt3DRender::RayCasting::QRay3D(QVector3D(0.0, -2.0, 0.0), QVector3D(0.0, -2.0, 1.0), 1.0f) - << QVector3D(3.0, 1.5, 0.0) - << QVector3D(0.0, -1.5, 0.0) - << QVector3D(-3, 1.5, 0.0) - << QVector3D() + << Qt3DRender::RayCasting::QRay3D(Vector3D(0.0, -2.0, 0.0), Vector3D(0.0, -2.0, 1.0), 1.0f) + << Vector3D(3.0, 1.5, 0.0) + << Vector3D(0.0, -1.5, 0.0) + << Vector3D(-3, 1.5, 0.0) + << Vector3D() << 0.0f << false; } @@ -188,15 +188,15 @@ private Q_SLOTS: { // GIVEN QFETCH(Qt3DRender::RayCasting::QRay3D, ray); - QFETCH(QVector3D, a); - QFETCH(QVector3D, b); - QFETCH(QVector3D, c); - QFETCH(QVector3D, uvw); + QFETCH(Vector3D, a); + QFETCH(Vector3D, b); + QFETCH(Vector3D, c); + QFETCH(Vector3D, uvw); QFETCH(float, t); QFETCH(bool, isIntersecting); // WHEN - QVector3D tmp_uvw; + Vector3D tmp_uvw; float tmp_t; const bool shouldBeIntersecting = Qt3DRender::Render::intersectsSegmentTriangle(ray, a, b, c, diff --git a/tests/auto/render/trianglesextractor/tst_trianglesextractor.cpp b/tests/auto/render/trianglesextractor/tst_trianglesextractor.cpp index c6db3f62d..2f6d283be 100644 --- a/tests/auto/render/trianglesextractor/tst_trianglesextractor.cpp +++ b/tests/auto/render/trianglesextractor/tst_trianglesextractor.cpp @@ -353,10 +353,10 @@ private Q_SLOTS: QVector<Qt3DRender::Render::TriangleBoundingVolume *> v = QVector<Qt3DRender::Render::TriangleBoundingVolume *>() - << new Qt3DRender::Render::TriangleBoundingVolume(Qt3DCore::QNodeId(), QVector3D(0, 1, 0), QVector3D(1, 0, -1), QVector3D(-1, 0, -1)) - << new Qt3DRender::Render::TriangleBoundingVolume(Qt3DCore::QNodeId(), QVector3D(-1, 0, -1), QVector3D(1, 0, -1), QVector3D(0, 0, 1)) - << new Qt3DRender::Render::TriangleBoundingVolume(Qt3DCore::QNodeId(), QVector3D(0, 0, 1), QVector3D(0, 1, 0), QVector3D(-1, 0, -1)) - << new Qt3DRender::Render::TriangleBoundingVolume(Qt3DCore::QNodeId(), QVector3D(0, 1, 0), QVector3D(0, 0, 1), QVector3D(1, 0, -1)); + << new Qt3DRender::Render::TriangleBoundingVolume(Qt3DCore::QNodeId(), Vector3D(0, 1, 0), Vector3D(1, 0, -1), Vector3D(-1, 0, -1)) + << new Qt3DRender::Render::TriangleBoundingVolume(Qt3DCore::QNodeId(), Vector3D(-1, 0, -1), Vector3D(1, 0, -1), Vector3D(0, 0, 1)) + << new Qt3DRender::Render::TriangleBoundingVolume(Qt3DCore::QNodeId(), Vector3D(0, 0, 1), Vector3D(0, 1, 0), Vector3D(-1, 0, -1)) + << new Qt3DRender::Render::TriangleBoundingVolume(Qt3DCore::QNodeId(), Vector3D(0, 1, 0), Vector3D(0, 0, 1), Vector3D(1, 0, -1)); QTest::newRow("indexedMesh") << customIndexedGeometryRenderer() << v; QTest::newRow("nonIndexedMesh") << customNonIndexedGeometryRenderer() << v; diff --git a/tests/auto/render/trianglevisitor/tst_trianglevisitor.cpp b/tests/auto/render/trianglevisitor/tst_trianglevisitor.cpp index 9b6481423..4205d598e 100644 --- a/tests/auto/render/trianglevisitor/tst_trianglevisitor.cpp +++ b/tests/auto/render/trianglevisitor/tst_trianglevisitor.cpp @@ -49,7 +49,7 @@ public: } - virtual void visit(uint andx, const QVector3D &a, uint bndx, const QVector3D &b, uint cndx, const QVector3D &c) + virtual void visit(uint andx, const Vector3D &a, uint bndx, const Vector3D &b, uint cndx, const Vector3D &c) { m_triangles.push_back(TestTriangle(andx, a, bndx, b, cndx, c)); } @@ -69,7 +69,7 @@ public: return m_triangles.size(); } - bool verifyTriangle(uint triangle, uint andx, uint bndx, uint cndx, QVector3D a, QVector3D b, QVector3D c) const + bool verifyTriangle(uint triangle, uint andx, uint bndx, uint cndx, Vector3D a, Vector3D b, Vector3D c) const { if (triangle >= uint(m_triangles.size())) return false; @@ -89,13 +89,13 @@ private: struct TestTriangle { uint abcndx[3]; - QVector3D abc[3]; + Vector3D abc[3]; TestTriangle() { abcndx[0] = abcndx[1] = abcndx[2] = uint(-1); } - TestTriangle(uint andx, const QVector3D &a, uint bndx, const QVector3D &b, uint cndx, const QVector3D &c) + TestTriangle(uint andx, const Vector3D &a, uint bndx, const Vector3D &b, uint cndx, const Vector3D &c) { abcndx[0] = andx; abcndx[1] = bndx; @@ -194,7 +194,7 @@ private Q_SLOTS: positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); positionAttribute->setVertexSize(3); positionAttribute->setCount(6); - positionAttribute->setByteStride(3*4); + positionAttribute->setByteStride(0); positionAttribute->setByteOffset(0); positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); geometry->addAttribute(positionAttribute.data()); @@ -220,8 +220,8 @@ private Q_SLOTS: // THEN QVERIFY(visitor.triangleCount() == 2); - QVERIFY(visitor.verifyTriangle(0, 2,1,0, QVector3D(0,1,0), QVector3D(1,0,0), QVector3D(0,0,1))); - QVERIFY(visitor.verifyTriangle(1, 5,4,3, QVector3D(0,1,0), QVector3D(1,0,0), QVector3D(0,0,1))); + QVERIFY(visitor.verifyTriangle(0, 2,1,0, Vector3D(0,1,0), Vector3D(1,0,0), Vector3D(0,0,1))); + QVERIFY(visitor.verifyTriangle(1, 5,4,3, Vector3D(0,1,0), Vector3D(1,0,0), Vector3D(0,0,1))); } void testVisitTrianglesIndexed() @@ -331,11 +331,11 @@ private Q_SLOTS: // THEN QVERIFY(visitor.triangleCount() == 5); - QVERIFY(visitor.verifyTriangle(0, 2,1,0, QVector3D(0,1,0), QVector3D(1,0,0), QVector3D(0,0,1))); - QVERIFY(visitor.verifyTriangle(1, 5,4,3, QVector3D(0,1,0), QVector3D(1,0,0), QVector3D(0,0,1))); - QVERIFY(visitor.verifyTriangle(2, 0,1,5, QVector3D(0,0,1), QVector3D(1,0,0), QVector3D(0,1,0))); - QVERIFY(visitor.verifyTriangle(3, 2,3,4, QVector3D(0,1,0), QVector3D(0,0,1), QVector3D(1,0,0))); - QVERIFY(visitor.verifyTriangle(4, 4,2,0, QVector3D(1,0,0), QVector3D(0,1,0), QVector3D(0,0,1))); + QVERIFY(visitor.verifyTriangle(0, 2,1,0, Vector3D(0,1,0), Vector3D(1,0,0), Vector3D(0,0,1))); + QVERIFY(visitor.verifyTriangle(1, 5,4,3, Vector3D(0,1,0), Vector3D(1,0,0), Vector3D(0,0,1))); + QVERIFY(visitor.verifyTriangle(2, 0,1,5, Vector3D(0,0,1), Vector3D(1,0,0), Vector3D(0,1,0))); + QVERIFY(visitor.verifyTriangle(3, 2,3,4, Vector3D(0,1,0), Vector3D(0,0,1), Vector3D(1,0,0))); + QVERIFY(visitor.verifyTriangle(4, 4,2,0, Vector3D(1,0,0), Vector3D(0,1,0), Vector3D(0,0,1))); } void testVisitTriangleStrip() @@ -407,10 +407,10 @@ private Q_SLOTS: // THEN QVERIFY(visitor.triangleCount() == 4); - QVERIFY(visitor.verifyTriangle(0, 2,1,0, QVector3D(0,1,0), QVector3D(1,0,0), QVector3D(0,0,1))); - QVERIFY(visitor.verifyTriangle(1, 3,2,1, QVector3D(0,0,1), QVector3D(0,1,0), QVector3D(1,0,0))); - QVERIFY(visitor.verifyTriangle(2, 4,3,2, QVector3D(1,0,0), QVector3D(0,0,1), QVector3D(0,1,0))); - QVERIFY(visitor.verifyTriangle(3, 5,4,3, QVector3D(0,1,0), QVector3D(1,0,0), QVector3D(0,0,1))); + QVERIFY(visitor.verifyTriangle(0, 2,1,0, Vector3D(0,1,0), Vector3D(1,0,0), Vector3D(0,0,1))); + QVERIFY(visitor.verifyTriangle(1, 3,2,1, Vector3D(0,0,1), Vector3D(0,1,0), Vector3D(1,0,0))); + QVERIFY(visitor.verifyTriangle(2, 4,3,2, Vector3D(1,0,0), Vector3D(0,0,1), Vector3D(0,1,0))); + QVERIFY(visitor.verifyTriangle(3, 5,4,3, Vector3D(0,1,0), Vector3D(1,0,0), Vector3D(0,0,1))); } void testVisitTriangleStripIndexed() @@ -517,14 +517,14 @@ private Q_SLOTS: // THEN QVERIFY(visitor.triangleCount() == 8); - QVERIFY(visitor.verifyTriangle(0, 2,1,0, QVector3D(0,1,0), QVector3D(1,0,0), QVector3D(0,0,1))); - QVERIFY(visitor.verifyTriangle(1, 3,2,1, QVector3D(0,0,1), QVector3D(0,1,0), QVector3D(1,0,0))); - QVERIFY(visitor.verifyTriangle(2, 4,3,2, QVector3D(1,0,0), QVector3D(0,0,1), QVector3D(0,1,0))); - QVERIFY(visitor.verifyTriangle(3, 5,4,3, QVector3D(0,1,0), QVector3D(1,0,0), QVector3D(0,0,1))); - QVERIFY(visitor.verifyTriangle(4, 0,1,5, QVector3D(0,0,1), QVector3D(1,0,0), QVector3D(0,1,0))); - QVERIFY(visitor.verifyTriangle(5, 4,0,1, QVector3D(1,0,0), QVector3D(0,0,1), QVector3D(1,0,0))); - QVERIFY(visitor.verifyTriangle(6, 3,4,0, QVector3D(0,0,1), QVector3D(1,0,0), QVector3D(0,0,1))); - QVERIFY(visitor.verifyTriangle(7, 2,3,4, QVector3D(0,1,0), QVector3D(0,0,1), QVector3D(1,0,0))); + QVERIFY(visitor.verifyTriangle(0, 2,1,0, Vector3D(0,1,0), Vector3D(1,0,0), Vector3D(0,0,1))); + QVERIFY(visitor.verifyTriangle(1, 3,2,1, Vector3D(0,0,1), Vector3D(0,1,0), Vector3D(1,0,0))); + QVERIFY(visitor.verifyTriangle(2, 4,3,2, Vector3D(1,0,0), Vector3D(0,0,1), Vector3D(0,1,0))); + QVERIFY(visitor.verifyTriangle(3, 5,4,3, Vector3D(0,1,0), Vector3D(1,0,0), Vector3D(0,0,1))); + QVERIFY(visitor.verifyTriangle(4, 0,1,5, Vector3D(0,0,1), Vector3D(1,0,0), Vector3D(0,1,0))); + QVERIFY(visitor.verifyTriangle(5, 4,0,1, Vector3D(1,0,0), Vector3D(0,0,1), Vector3D(1,0,0))); + QVERIFY(visitor.verifyTriangle(6, 3,4,0, Vector3D(0,0,1), Vector3D(1,0,0), Vector3D(0,0,1))); + QVERIFY(visitor.verifyTriangle(7, 2,3,4, Vector3D(0,1,0), Vector3D(0,0,1), Vector3D(1,0,0))); } void testVisitTriangleFan() @@ -596,10 +596,10 @@ private Q_SLOTS: // THEN QVERIFY(visitor.triangleCount() == 4); - QVERIFY(visitor.verifyTriangle(0, 2,1,0, QVector3D(0,1,0), QVector3D(1,0,0), QVector3D(0,0,1))); - QVERIFY(visitor.verifyTriangle(1, 3,2,0, QVector3D(0,0,1), QVector3D(0,1,0), QVector3D(0,0,1))); - QVERIFY(visitor.verifyTriangle(2, 4,3,0, QVector3D(1,0,0), QVector3D(0,0,1), QVector3D(0,0,1))); - QVERIFY(visitor.verifyTriangle(3, 5,4,0, QVector3D(0,1,0), QVector3D(1,0,0), QVector3D(0,0,1))); + QVERIFY(visitor.verifyTriangle(0, 2,1,0, Vector3D(0,1,0), Vector3D(1,0,0), Vector3D(0,0,1))); + QVERIFY(visitor.verifyTriangle(1, 3,2,0, Vector3D(0,0,1), Vector3D(0,1,0), Vector3D(0,0,1))); + QVERIFY(visitor.verifyTriangle(2, 4,3,0, Vector3D(1,0,0), Vector3D(0,0,1), Vector3D(0,0,1))); + QVERIFY(visitor.verifyTriangle(3, 5,4,0, Vector3D(0,1,0), Vector3D(1,0,0), Vector3D(0,0,1))); } void testVisitTriangleFanIndexed() @@ -700,10 +700,10 @@ private Q_SLOTS: // THEN QVERIFY(visitor.triangleCount() == 4); - QVERIFY(visitor.verifyTriangle(0, 2,1,0, QVector3D(0,1,0), QVector3D(1,0,0), QVector3D(0,0,1))); - QVERIFY(visitor.verifyTriangle(1, 3,2,0, QVector3D(0,0,1), QVector3D(0,1,0), QVector3D(0,0,1))); - QVERIFY(visitor.verifyTriangle(2, 4,3,0, QVector3D(1,0,0), QVector3D(0,0,1), QVector3D(0,0,1))); - QVERIFY(visitor.verifyTriangle(3, 5,4,0, QVector3D(0,1,0), QVector3D(1,0,0), QVector3D(0,0,1))); + QVERIFY(visitor.verifyTriangle(0, 2,1,0, Vector3D(0,1,0), Vector3D(1,0,0), Vector3D(0,0,1))); + QVERIFY(visitor.verifyTriangle(1, 3,2,0, Vector3D(0,0,1), Vector3D(0,1,0), Vector3D(0,0,1))); + QVERIFY(visitor.verifyTriangle(2, 4,3,0, Vector3D(1,0,0), Vector3D(0,0,1), Vector3D(0,0,1))); + QVERIFY(visitor.verifyTriangle(3, 5,4,0, Vector3D(0,1,0), Vector3D(1,0,0), Vector3D(0,0,1))); } void testVisitTrianglesAdjacency() @@ -775,7 +775,7 @@ private Q_SLOTS: // THEN QVERIFY(visitor.triangleCount() == 1); - QVERIFY(visitor.verifyTriangle(0, 4,2,0, QVector3D(1,0,0), QVector3D(0,1,0), QVector3D(0,0,1))); + QVERIFY(visitor.verifyTriangle(0, 4,2,0, Vector3D(1,0,0), Vector3D(0,1,0), Vector3D(0,0,1))); } void testVisitTrianglesAdjacencyIndexed() @@ -883,8 +883,8 @@ private Q_SLOTS: // THEN QVERIFY(visitor.triangleCount() == 2); - QVERIFY(visitor.verifyTriangle(0, 4,2,0, QVector3D(1,0,0), QVector3D(0,1,0), QVector3D(0,0,1))); - QVERIFY(visitor.verifyTriangle(1, 3,0,5, QVector3D(0,0,1), QVector3D(0,0,1), QVector3D(0,1,0))); + QVERIFY(visitor.verifyTriangle(0, 4,2,0, Vector3D(1,0,0), Vector3D(0,1,0), Vector3D(0,0,1))); + QVERIFY(visitor.verifyTriangle(1, 3,0,5, Vector3D(0,0,1), Vector3D(0,0,1), Vector3D(0,1,0))); } void testVisitTriangleStripAdjacency() @@ -969,8 +969,8 @@ private Q_SLOTS: // THEN QVERIFY(visitor.triangleCount() == 2); - QVERIFY(visitor.verifyTriangle(0, 4,2,0, QVector3D(1,0,0), QVector3D(0,1,0), QVector3D(0,0,1))); - QVERIFY(visitor.verifyTriangle(1, 6,4,2, QVector3D(1,1,1), QVector3D(1,0,0), QVector3D(0,1,0))); + QVERIFY(visitor.verifyTriangle(0, 4,2,0, Vector3D(1,0,0), Vector3D(0,1,0), Vector3D(0,0,1))); + QVERIFY(visitor.verifyTriangle(1, 6,4,2, Vector3D(1,1,1), Vector3D(1,0,0), Vector3D(0,1,0))); } void testVisitTriangleStripAdjacencyIndexed() @@ -1074,8 +1074,8 @@ private Q_SLOTS: // THEN QVERIFY(visitor.triangleCount() == 2); - QVERIFY(visitor.verifyTriangle(0, 4,2,0, QVector3D(1,0,0), QVector3D(0,1,0), QVector3D(0,0,1))); - QVERIFY(visitor.verifyTriangle(1, 5,4,2, QVector3D(0,1,0), QVector3D(1,0,0), QVector3D(0,1,0))); + QVERIFY(visitor.verifyTriangle(0, 4,2,0, Vector3D(1,0,0), Vector3D(0,1,0), Vector3D(0,0,1))); + QVERIFY(visitor.verifyTriangle(1, 5,4,2, Vector3D(0,1,0), Vector3D(1,0,0), Vector3D(0,1,0))); } }; diff --git a/tests/auto/render/uniform/tst_uniform.cpp b/tests/auto/render/uniform/tst_uniform.cpp index b8578b294..213646369 100644 --- a/tests/auto/render/uniform/tst_uniform.cpp +++ b/tests/auto/render/uniform/tst_uniform.cpp @@ -107,7 +107,7 @@ private Q_SLOTS: } { // GIVEN - UniformValue v(QVector3D(572.0f, 355.0f, 383.0f)); + UniformValue v(Vector3D(572.0f, 355.0f, 383.0f)); // THEN QCOMPARE(v.constData<float>()[0], 572.0f); QCOMPARE(v.constData<float>()[1], 355.0f); @@ -116,7 +116,7 @@ private Q_SLOTS: } { // GIVEN - UniformValue v(QVector4D(355.0f, 383.0f, 1340.0f, 1603.0f)); + UniformValue v(Vector4D(355.0f, 383.0f, 1340.0f, 1603.0f)); // THEN QCOMPARE(v.constData<float>()[0], 355.0f); QCOMPARE(v.constData<float>()[1], 383.0f); @@ -340,7 +340,7 @@ private Q_SLOTS: void checkComparison() { // GIVEN - const UniformValue v1(QVector3D(454.0f, 883.0f, 572.0f)); + const UniformValue v1(Vector3D(454.0f, 883.0f, 572.0f)); UniformValue v2(454.0f); // THEN @@ -348,13 +348,13 @@ private Q_SLOTS: QVERIFY(v1 != v2); // WHEN - v2 = UniformValue::fromVariant(QVector3D(454.0f, 883.0f, 572.0f)); + v2 = UniformValue::fromVariant(QVariant::fromValue(Vector3D(454.0f, 883.0f, 572.0f))); // THEN QVERIFY(v1 == v2); QVERIFY(!(v1 != v2)); // WHEN - v2 = UniformValue::fromVariant(QVector3D(454.0f, 883.0f, 572.0f)); + v2 = UniformValue::fromVariant(QVariant::fromValue(Vector3D(454.0f, 883.0f, 572.0f))); // THEN QVERIFY(v1 == v2); QVERIFY(!(v1 != v2)); diff --git a/tests/auto/render/updateshaderdatatransformjob/tst_updateshaderdatatransformjob.cpp b/tests/auto/render/updateshaderdatatransformjob/tst_updateshaderdatatransformjob.cpp index c076aa21e..67ddccd9b 100644 --- a/tests/auto/render/updateshaderdatatransformjob/tst_updateshaderdatatransformjob.cpp +++ b/tests/auto/render/updateshaderdatatransformjob/tst_updateshaderdatatransformjob.cpp @@ -179,7 +179,8 @@ private Q_SLOTS: // THEN // See scene file to find translation - QCOMPARE(backendShaderData->getTransformedProperty(QLatin1String("eyePosition"), camera->viewMatrix()).value<QVector3D>(), camera->viewMatrix() * (QVector3D(1.0f, 1.0f, 1.0f) + QVector3D(0.0f, 5.0f, 0.0f))); + QCOMPARE(backendShaderData->getTransformedProperty(QLatin1String("eyePosition"), Matrix4x4(camera->viewMatrix())).value<Vector3D>(), + Matrix4x4(camera->viewMatrix()) * (Vector3D(1.0f, 1.0f, 1.0f) + Vector3D(0.0f, 5.0f, 0.0f))); } void checkRunModelToWorld() @@ -219,7 +220,8 @@ private Q_SLOTS: // THEN // See scene file to find translation - QCOMPARE(backendShaderData->getTransformedProperty(QLatin1String("position"), camera->viewMatrix()).value<QVector3D>(), QVector3D(1.0f, 1.0f, 1.0f) + QVector3D(5.0f, 5.0f, 5.0f)); + QCOMPARE(backendShaderData->getTransformedProperty(QLatin1String("position"), Matrix4x4(camera->viewMatrix())).value<Vector3D>(), + Vector3D(1.0f, 1.0f, 1.0f) + Vector3D(5.0f, 5.0f, 5.0f)); } }; |