diff options
Diffstat (limited to 'src/render/jobs')
-rw-r--r-- | src/render/jobs/calcboundingvolumejob.cpp | 188 | ||||
-rw-r--r-- | src/render/jobs/computefilteredboundingvolumejob.cpp | 130 | ||||
-rw-r--r-- | src/render/jobs/computefilteredboundingvolumejob_p.h | 91 | ||||
-rw-r--r-- | src/render/jobs/job_common_p.h | 2 | ||||
-rw-r--r-- | src/render/jobs/jobs.pri | 9 | ||||
-rw-r--r-- | src/render/jobs/lightgatherer.cpp | 9 | ||||
-rw-r--r-- | src/render/jobs/lightgatherer_p.h | 8 | ||||
-rw-r--r-- | src/render/jobs/loadscenejob.cpp | 68 | ||||
-rw-r--r-- | src/render/jobs/loadscenejob_p.h | 2 | ||||
-rw-r--r-- | src/render/jobs/pickboundingvolumejob.cpp | 75 | ||||
-rw-r--r-- | src/render/jobs/pickboundingvolumejob_p.h | 10 | ||||
-rw-r--r-- | src/render/jobs/pickboundingvolumeutils.cpp | 57 | ||||
-rw-r--r-- | src/render/jobs/pickboundingvolumeutils_p.h | 17 | ||||
-rw-r--r-- | src/render/jobs/renderviewjobutils.cpp | 33 | ||||
-rw-r--r-- | src/render/jobs/renderviewjobutils_p.h | 2 | ||||
-rw-r--r-- | src/render/jobs/sendbuffercapturejob.cpp | 89 | ||||
-rw-r--r-- | src/render/jobs/sendbuffercapturejob_p.h | 99 | ||||
-rw-r--r-- | src/render/jobs/updatelevelofdetailjob.cpp | 8 |
18 files changed, 781 insertions, 116 deletions
diff --git a/src/render/jobs/calcboundingvolumejob.cpp b/src/render/jobs/calcboundingvolumejob.cpp index 9e373c655..e81836502 100644 --- a/src/render/jobs/calcboundingvolumejob.cpp +++ b/src/render/jobs/calcboundingvolumejob.cpp @@ -50,6 +50,7 @@ #include <Qt3DRender/private/attribute_p.h> #include <Qt3DRender/private/buffer_p.h> #include <Qt3DRender/private/sphere_p.h> +#include <Qt3DRender/private/buffervisitor_p.h> #include <QtCore/qmath.h> #include <QtConcurrent/QtConcurrent> @@ -73,6 +74,114 @@ struct UpdateBoundFunctor { } }; +class BoundingVolumeCalculator +{ +public: + BoundingVolumeCalculator(NodeManagers *manager) : m_manager(manager) { } + + const Sphere& result() { return m_volume; } + + bool apply(Qt3DRender::Render::Attribute *positionAttribute) + { + FindExtremePoints findExtremePoints(m_manager); + if (!findExtremePoints.apply(positionAttribute)) + return false; + + // Calculate squared distance for the pairs of points + const float xDist2 = (findExtremePoints.xMaxPt - findExtremePoints.xMinPt).lengthSquared(); + const float yDist2 = (findExtremePoints.yMaxPt - findExtremePoints.yMinPt).lengthSquared(); + const float zDist2 = (findExtremePoints.zMaxPt - findExtremePoints.zMinPt).lengthSquared(); + + // Select most distant pair + QVector3D p = findExtremePoints.xMinPt; + QVector3D q = findExtremePoints.xMaxPt; + if (yDist2 > xDist2 && yDist2 > zDist2) { + p = findExtremePoints.yMinPt; + q = findExtremePoints.yMaxPt; + } + if (zDist2 > xDist2 && zDist2 > yDist2) { + p = findExtremePoints.zMinPt; + q = findExtremePoints.zMaxPt; + } + + const QVector3D 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)) + return false; + + return true; + } + +private: + Sphere m_volume; + NodeManagers *m_manager; + + class FindExtremePoints : public Buffer3fVisitor + { + public: + FindExtremePoints(NodeManagers *manager) + : Buffer3fVisitor(manager) + , xMin(0.0f), xMax(0.0f), yMin(0.0f), yMax(0.0f), zMin(0.0f), zMax(0.0f) + { } + + float xMin, xMax, yMin, yMax, zMin, zMax; + QVector3D 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); + } + if (x > xMax) { + xMax = x; + xMaxPt = QVector3D(x, y, z); + } + if (y < yMin) { + yMin = y; + yMinPt = QVector3D(x, y, z); + } + if (y > yMax) { + yMax = y; + yMaxPt = QVector3D(x, y, z); + } + if (z < zMin) { + zMin = z; + zMinPt = QVector3D(x, y, z); + } + if (z > zMax) { + zMax = z; + zMaxPt = QVector3D(x, y, z); + } + } else { + xMin = xMax = x; + yMin = yMax = y; + zMin = zMax = z; + xMinPt = xMaxPt = yMinPt = yMaxPt = zMinPt = zMaxPt = QVector3D(x, y, z); + } + } + }; + + class ExpandSphere : public Buffer3fVisitor + { + public: + ExpandSphere(NodeManagers *manager, Sphere& volume) + : Buffer3fVisitor(manager), m_volume(volume) + { } + + Sphere& m_volume; + void visit(uint ndx, float x, float y, float z) override + { + Q_UNUSED(ndx); + m_volume.expandToContain(QVector3D(x, y, z)); + } + }; +}; + void calculateLocalBoundingVolume(NodeManagers *manager, Entity *node) { // The Bounding volume will only be computed if the position Buffer @@ -86,63 +195,48 @@ void calculateLocalBoundingVolume(NodeManagers *manager, Entity *node) Geometry *geom = manager->lookupResource<Geometry, GeometryManager>(gRenderer->geometryId()); if (geom) { - Qt3DRender::Render::Attribute *pickVolumeAttribute = manager->lookupResource<Attribute, AttributeManager>(geom->boundingPositionAttribute()); + Qt3DRender::Render::Attribute *positionAttribute = manager->lookupResource<Attribute, AttributeManager>(geom->boundingPositionAttribute()); // Use the default position attribute if attribute is null - if (!pickVolumeAttribute) { + if (!positionAttribute) { const auto attrIds = geom->attributes(); for (const Qt3DCore::QNodeId attrId : attrIds) { - pickVolumeAttribute = manager->lookupResource<Attribute, AttributeManager>(attrId); - if (pickVolumeAttribute && - pickVolumeAttribute->name() == QAttribute::defaultPositionAttributeName()) + positionAttribute = manager->lookupResource<Attribute, AttributeManager>(attrId); + if (positionAttribute && + positionAttribute->name() == QAttribute::defaultPositionAttributeName()) break; } } - if (pickVolumeAttribute) { - if (!pickVolumeAttribute - || pickVolumeAttribute->attributeType() != QAttribute::VertexAttribute - || pickVolumeAttribute->vertexBaseType() != QAttribute::Float - || pickVolumeAttribute->vertexSize() < 3) { - qWarning() << "QGeometry::boundingVolumePositionAttribute pickVolume Attribute not suited for bounding volume computation"; - return; - } + if (!positionAttribute + || positionAttribute->attributeType() != QAttribute::VertexAttribute + || positionAttribute->vertexBaseType() != QAttribute::Float + || positionAttribute->vertexSize() < 3) { + qWarning() << "QGeometry::boundingVolumePositionAttribute position Attribute not suited for bounding volume computation"; + return; + } - Buffer *buf = manager->lookupResource<Buffer, BufferManager>(pickVolumeAttribute->bufferId()); - // No point in continuing if the positionAttribute doesn't have a suitable buffer - if (!buf) { - qWarning() << "ObjectPicker pickVolume Attribute not referencing a valid buffer"; - return; - } + Buffer *buf = manager->lookupResource<Buffer, BufferManager>(positionAttribute->bufferId()); + // No point in continuing if the positionAttribute doesn't have a suitable buffer + if (!buf) { + qWarning() << "ObjectPicker position Attribute not referencing a valid buffer"; + return; + } + + // Buf will be set to not dirty once it's loaded + // 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()) { - // Buf will be set to not dirty once it's loaded - // 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() || - pickVolumeAttribute->isDirty() || - geom->isDirty() || - gRenderer->isDirty()) { - - const QByteArray buffer = buf->data(); - const char *rawBuffer = buffer.constData(); - rawBuffer += pickVolumeAttribute->byteOffset(); - const int stride = pickVolumeAttribute->byteStride() ? pickVolumeAttribute->byteStride() : sizeof(float) * pickVolumeAttribute->vertexSize(); - QVector<QVector3D> vertices(pickVolumeAttribute->count()); - - // TODO avoid copying the vertices - for (int c = 0, vC = vertices.size(); c < vC; ++c) { - QVector3D v; - const float *fptr = reinterpret_cast<const float*>(rawBuffer); - // TODO unwrap loop (switch?) - for (uint i = 0, m = qMin(pickVolumeAttribute->vertexSize(), 3U); i < m; ++i) - v[i] = fptr[i]; - vertices[c] = v; - rawBuffer += stride; - } - - node->localBoundingVolume()->initializeFromPoints(vertices); + BoundingVolumeCalculator reader(manager); + if (reader.apply(positionAttribute)) { + node->localBoundingVolume()->setCenter(reader.result().center()); + node->localBoundingVolume()->setRadius(reader.result().radius()); node->unsetBoundingVolumeDirty(); } } diff --git a/src/render/jobs/computefilteredboundingvolumejob.cpp b/src/render/jobs/computefilteredboundingvolumejob.cpp new file mode 100644 index 000000000..d8a7b5094 --- /dev/null +++ b/src/render/jobs/computefilteredboundingvolumejob.cpp @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "computefilteredboundingvolumejob_p.h" + +#include <Qt3DRender/private/renderer_p.h> +#include <Qt3DRender/private/entity_p.h> +#include <Qt3DRender/private/renderlogging_p.h> +#include <Qt3DRender/private/sphere_p.h> +#include <Qt3DRender/private/job_common_p.h> + +#include <QThread> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { +namespace Render { + +namespace { + +void expandWorldBoundingVolume(Qt3DRender::Render::Sphere *sphere, + Qt3DRender::Render::Entity *node, + Qt3DRender::Render::Entity *excludeSubTree) +{ + Qt3DRender::Render::Sphere childSphere(*node->worldBoundingVolume()); + // Go to the nodes that have the most depth + const auto children = node->children(); + for (Entity *c : children) { + if (c != excludeSubTree) + expandWorldBoundingVolume(&childSphere, c, excludeSubTree); + } + sphere->expandToContain(childSphere); +} + +} // namespace + +ComputeFilteredBoundingVolumeJob::ComputeFilteredBoundingVolumeJob() + : m_root(nullptr) + , m_ignoreSubTree(nullptr) +{ + SET_JOB_RUN_STAT_TYPE(this, JobTypes::ExpandBoundingVolume, 0); +} + +void ComputeFilteredBoundingVolumeJob::setRoot(Entity *root) +{ + m_root = root; +} + +void ComputeFilteredBoundingVolumeJob::ignoreSubTree(Entity *node) +{ + m_ignoreSubTree = node; +} + +void ComputeFilteredBoundingVolumeJob::run() +{ + qCDebug(Jobs) << "Entering" << Q_FUNC_INFO << QThread::currentThread(); + + if (!m_root) + return; + if (!m_ignoreSubTree) { + finished(*m_root->worldBoundingVolumeWithChildren()); + return; + } + + bool isFilterChildOfRoot = false; + Entity *parent = m_ignoreSubTree->parent(); + while (parent) { + if (parent == m_root) { + isFilterChildOfRoot = true; + break; + } + parent = parent->parent(); + } + if (!isFilterChildOfRoot) { + finished(*m_root->worldBoundingVolumeWithChildren()); + return; + } + + Qt3DRender::Render::Sphere sphere; + expandWorldBoundingVolume(&sphere, m_root, m_ignoreSubTree); + finished(sphere); + + qCDebug(Jobs) << "Exiting" << Q_FUNC_INFO << QThread::currentThread(); +} + +void ComputeFilteredBoundingVolumeJob::finished(const Qt3DRender::Render::Sphere &sphere) +{ + Q_UNUSED(sphere); +} + +} // namespace Render +} // namespace Qt3DRender + +QT_END_NAMESPACE diff --git a/src/render/jobs/computefilteredboundingvolumejob_p.h b/src/render/jobs/computefilteredboundingvolumejob_p.h new file mode 100644 index 000000000..d7681e604 --- /dev/null +++ b/src/render/jobs/computefilteredboundingvolumejob_p.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** 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_COMPUTEFILTEREDBOUNDINGVOLUMEJOB_H +#define QT3DRENDER_RENDER_COMPUTEFILTEREDBOUNDINGVOLUMEJOB_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.h> +#include <private/qt3drender_global_p.h> + +#include <QtCore/QSharedPointer> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { +namespace Render { + +class Entity; +class Sphere; + +class QT3DRENDERSHARED_PRIVATE_EXPORT ComputeFilteredBoundingVolumeJob : public Qt3DCore::QAspectJob +{ +public: + ComputeFilteredBoundingVolumeJob(); + + void setRoot(Entity *root); + void ignoreSubTree(Entity *node); + void run() Q_DECL_OVERRIDE; + +protected: + virtual void finished(const Qt3DRender::Render::Sphere &sphere); + +private: + Entity *m_root; + Entity *m_ignoreSubTree; +}; + +typedef QSharedPointer<ComputeFilteredBoundingVolumeJob> ComputeFilteredBoundingVolumeJobPtr; + +} // namespace Render +} // namespace Qt3DRender + +QT_END_NAMESPACE + +#endif // QT3DRENDER_RENDER_COMPUTEFILTEREDBOUNDINGVOLUMEJOB_H diff --git a/src/render/jobs/job_common_p.h b/src/render/jobs/job_common_p.h index 90e29d0dc..332b62547 100644 --- a/src/render/jobs/job_common_p.h +++ b/src/render/jobs/job_common_p.h @@ -86,9 +86,11 @@ namespace JobTypes { UpdateWorldBoundingVolume, FrameSubmissionPart2, DirtyBufferGathering, + DirtyVaoGathering, DirtyTextureGathering, DirtyShaderGathering, SendRenderCapture, + SendBufferCapture, SyncRenderViewCommandBuilding, SyncRenderViewInitialization, SyncRenderViewCommandBuilder, diff --git a/src/render/jobs/jobs.pri b/src/render/jobs/jobs.pri index d7f05ec4c..66c98b1c0 100644 --- a/src/render/jobs/jobs.pri +++ b/src/render/jobs/jobs.pri @@ -11,6 +11,7 @@ HEADERS += \ $$PWD/calcboundingvolumejob_p.h \ $$PWD/pickboundingvolumejob_p.h \ $$PWD/calcgeometrytrianglevolumes_p.h \ + $$PWD/computefilteredboundingvolumejob_p.h \ $$PWD/job_common_p.h \ $$PWD/filterlayerentityjob_p.h \ $$PWD/filterentitybycomponentjob_p.h \ @@ -28,7 +29,8 @@ HEADERS += \ $$PWD/updatemeshtrianglelistjob_p.h \ $$PWD/pickboundingvolumeutils_p.h \ $$PWD/filtercompatibletechniquejob_p.h \ - $$PWD/updatetreeenabledjob_p.h + $$PWD/updatetreeenabledjob_p.h \ + $$PWD/sendbuffercapturejob_p.h SOURCES += \ $$PWD/updateworldtransformjob.cpp \ @@ -41,6 +43,7 @@ SOURCES += \ $$PWD/calcboundingvolumejob.cpp \ $$PWD/pickboundingvolumejob.cpp \ $$PWD/calcgeometrytrianglevolumes.cpp \ + $$PWD/computefilteredboundingvolumejob.cpp \ $$PWD/filterlayerentityjob.cpp \ $$PWD/materialparametergathererjob.cpp \ $$PWD/renderviewbuilderjob.cpp \ @@ -55,4 +58,6 @@ SOURCES += \ $$PWD/updatelevelofdetailjob.cpp \ $$PWD/pickboundingvolumeutils.cpp \ $$PWD/filtercompatibletechniquejob.cpp \ - $$PWD/updatetreeenabledjob.cpp + $$PWD/updatetreeenabledjob.cpp \ + $$PWD/sendbuffercapturejob.cpp + diff --git a/src/render/jobs/lightgatherer.cpp b/src/render/jobs/lightgatherer.cpp index 39023bc35..e62544f15 100644 --- a/src/render/jobs/lightgatherer.cpp +++ b/src/render/jobs/lightgatherer.cpp @@ -51,6 +51,7 @@ namespace Render { LightGatherer::LightGatherer() : Qt3DCore::QAspectJob() , m_manager(nullptr) + , m_environmentLight(nullptr) { SET_JOB_RUN_STAT_TYPE(this, JobTypes::LightGathering, 0); } @@ -58,13 +59,21 @@ LightGatherer::LightGatherer() void LightGatherer::run() { const QVector<HEntity> handles = m_manager->activeHandles(); + int envLightCount = 0; for (const HEntity handle : handles) { Entity *node = m_manager->data(handle); const QVector<Light *> lights = node->renderComponents<Light>(); if (!lights.isEmpty()) m_lights.push_back(LightSource(node, lights)); + const QVector<EnvironmentLight *> envLights = node->renderComponents<EnvironmentLight>(); + envLightCount += envLights.size(); + if (!envLights.isEmpty() && !m_environmentLight) + m_environmentLight = envLights.first(); } + + if (envLightCount > 1) + qWarning() << "More than one environment light found, extra instances are ignored"; } } // Render diff --git a/src/render/jobs/lightgatherer_p.h b/src/render/jobs/lightgatherer_p.h index e2954fd07..4eaeb8f19 100644 --- a/src/render/jobs/lightgatherer_p.h +++ b/src/render/jobs/lightgatherer_p.h @@ -61,6 +61,7 @@ namespace Qt3DRender { namespace Render { class EntityManager; +class EnvironmentLight; class Q_AUTOTEST_EXPORT LightGatherer : public Qt3DCore::QAspectJob { @@ -69,12 +70,19 @@ public: inline void setManager(EntityManager *manager) Q_DECL_NOTHROW { m_manager = manager; } inline QVector<LightSource> &lights() { return m_lights; } + inline EnvironmentLight *takeEnvironmentLight() + { + auto envLight = m_environmentLight; + m_environmentLight = nullptr; + return envLight; + } void run() Q_DECL_FINAL; private: EntityManager *m_manager; QVector<LightSource> m_lights; + EnvironmentLight *m_environmentLight; }; typedef QSharedPointer<LightGatherer> LightGathererPtr; diff --git a/src/render/jobs/loadscenejob.cpp b/src/render/jobs/loadscenejob.cpp index 9b3374627..3d6326e93 100644 --- a/src/render/jobs/loadscenejob.cpp +++ b/src/render/jobs/loadscenejob.cpp @@ -44,6 +44,7 @@ #include <Qt3DCore/qentity.h> #include <Qt3DRender/private/job_common_p.h> #include <Qt3DRender/private/qsceneimporter_p.h> +#include <Qt3DRender/private/qurlhelper_p.h> #include <Qt3DRender/qsceneloader.h> QT_BEGIN_NAMESPACE @@ -60,6 +61,11 @@ LoadSceneJob::LoadSceneJob(const QUrl &source, Qt3DCore::QNodeId m_sceneComponen SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadScene, 0); } +void LoadSceneJob::setData(const QByteArray &data) +{ + m_data = data; +} + NodeManagers *LoadSceneJob::nodeManagers() const { return m_managers; @@ -95,20 +101,54 @@ void LoadSceneJob::run() // Perform the loading only if the source wasn't explicitly set to empty if (!m_source.isEmpty()) { finalStatus = QSceneLoader::Error; - for (QSceneImporter *sceneImporter : qAsConst(m_sceneImporters)) { - if (!sceneImporter->isFileTypeSupported(m_source)) - continue; - - // If the file type is supported -> enter Loading status - scene->setStatus(QSceneLoader::Loading); - - // File type is supported, try to load it - sceneImporter->setSource(m_source); - sceneSubTree = sceneImporter->scene(); - if (sceneSubTree != nullptr) { - // Successfully built a subtree - finalStatus = QSceneLoader::Ready; - break; + + if (m_data.isEmpty()) { + const QString path = QUrlHelper::urlToLocalFileOrQrc(m_source); + QFileInfo finfo(path); + if (finfo.exists()) { + QStringList extensions(finfo.suffix()); + + for (QSceneImporter *sceneImporter : qAsConst(m_sceneImporters)) { + if (!sceneImporter->areFileTypesSupported(extensions)) + continue; + + // If the file type is supported -> enter Loading status + scene->setStatus(QSceneLoader::Loading); + + // File type is supported, try to load it + sceneImporter->setSource(m_source); + sceneSubTree = sceneImporter->scene(); + if (sceneSubTree != nullptr) { + // Successfully built a subtree + finalStatus = QSceneLoader::Ready; + break; + } + } + } + } else { + QStringList extensions; + QMimeDatabase db; + QMimeType mtype = db.mimeTypeForData(m_data); + if (mtype.isValid()) { + extensions = mtype.suffixes(); + } + + QString basePath = m_source.adjusted(QUrl::RemoveFilename).toString(); + for (QSceneImporter *sceneImporter : qAsConst(m_sceneImporters)) { + if (!sceneImporter->areFileTypesSupported(extensions)) + continue; + + // If the file type is supported -> enter Loading status + scene->setStatus(QSceneLoader::Loading); + + // File type is supported, try to load it + sceneImporter->setData(m_data, basePath); + sceneSubTree = sceneImporter->scene(); + if (sceneSubTree != nullptr) { + // Successfully built a subtree + finalStatus = QSceneLoader::Ready; + break; + } } } } diff --git a/src/render/jobs/loadscenejob_p.h b/src/render/jobs/loadscenejob_p.h index 7538c6eb0..5217c6f43 100644 --- a/src/render/jobs/loadscenejob_p.h +++ b/src/render/jobs/loadscenejob_p.h @@ -70,6 +70,7 @@ class Q_AUTOTEST_EXPORT LoadSceneJob : public Qt3DCore::QAspectJob { public: explicit LoadSceneJob(const QUrl &source, Qt3DCore::QNodeId sceneComponent); + void setData(const QByteArray &data); void setNodeManagers(NodeManagers *managers) { m_managers = managers; } void setSceneImporters(const QList<QSceneImporter *> sceneImporters) { m_sceneImporters = sceneImporters; } @@ -82,6 +83,7 @@ public: private: QUrl m_source; + QByteArray m_data; Qt3DCore::QNodeId m_sceneComponent; NodeManagers *m_managers; QList<QSceneImporter *> m_sceneImporters; diff --git a/src/render/jobs/pickboundingvolumejob.cpp b/src/render/jobs/pickboundingvolumejob.cpp index 6b8b93647..f9c7a390c 100644 --- a/src/render/jobs/pickboundingvolumejob.cpp +++ b/src/render/jobs/pickboundingvolumejob.cpp @@ -49,6 +49,7 @@ #include <Qt3DRender/private/rendersettings_p.h> #include <Qt3DRender/qgeometryrenderer.h> #include <Qt3DRender/private/job_common_p.h> +#include <Qt3DRender/private/qpickevent_p.h> QT_BEGIN_NAMESPACE @@ -59,6 +60,8 @@ namespace Render { namespace { +typedef PickingUtils::AbstractCollisionGathererFunctor::result_type HitList; + void setEventButtonAndModifiers(const QMouseEvent &event, QPickEvent::Buttons &eventButton, int &eventButtons, int &eventModifiers) { switch (event.button()) { @@ -120,6 +123,11 @@ void PickBoundingVolumeJob::setMouseEvents(const QList<QMouseEvent> &pendingEven m_pendingMouseEvents = pendingEvents; } +void PickBoundingVolumeJob::setKeyEvents(const QList<QKeyEvent> &pendingEvents) +{ + m_pendingKeyEvents = pendingEvents; +} + void PickBoundingVolumeJob::setFrameGraphRoot(FrameGraphNode *frameGraphRoot) { m_frameGraphRoot = frameGraphRoot; @@ -159,7 +167,8 @@ bool PickBoundingVolumeJob::runHelper() m_oneEnabledAtLeast = false; m_oneHoverAtLeast = false; - for (auto handle : m_manager->objectPickerManager()->activeHandles()) { + const auto activeHandles = m_manager->objectPickerManager()->activeHandles(); + for (auto handle : activeHandles) { auto picker = m_manager->objectPickerManager()->data(handle); m_oneEnabledAtLeast |= picker->isEnabled(); m_oneHoverAtLeast |= picker->isHoverEnabled(); @@ -214,11 +223,6 @@ bool PickBoundingVolumeJob::runHelper() // If we have move or hover move events that someone cares about, we try to avoid expensive computations // by compressing them into a single one - // Gather the entities for the frame - // TO DO: We could skip doing that every frame and only do it when we know for sure - // that the tree structure has changed - PickingUtils::EntityGatherer entitiesGatherer(m_node); - // Store the reducer function which varies depending on the picking settings set on the renderer using ReducerFunction = PickingUtils::CollisionVisitor::HitList (*)(PickingUtils::CollisionVisitor::HitList &results, const PickingUtils::CollisionVisitor::HitList &intermediate); @@ -244,25 +248,30 @@ bool PickBoundingVolumeJob::runHelper() // For each triplet of Viewport / Camera and Area for (const PickingUtils::ViewportCameraAreaTriplet &vca : vcaTriplets) { - typedef PickingUtils::AbstractCollisionGathererFunctor::result_type HitList; HitList sphereHits; QRay3D ray = rayForViewportAndCamera(vca.area, event.pos(), vca.viewport, vca.cameraId); - if (trianglePickingRequested) { - PickingUtils::TriangleCollisionGathererFunctor gathererFunctor; - gathererFunctor.m_frontFaceRequested = frontFaceRequested; - gathererFunctor.m_backFaceRequested = backFaceRequested; - gathererFunctor.m_manager = m_manager; - gathererFunctor.m_ray = ray; - sphereHits = QtConcurrent::blockingMappedReduced<HitList>(entitiesGatherer.entities(), gathererFunctor, reducerOp); - } else { - PickingUtils::EntityCollisionGathererFunctor gathererFunctor; - gathererFunctor.m_manager = m_manager; - gathererFunctor.m_ray = ray; - sphereHits = QtConcurrent::blockingMappedReduced<HitList>(entitiesGatherer.entities(), gathererFunctor, reducerOp); + + PickingUtils::HierarchicalEntityPicker entityPicker(ray); + if (entityPicker.collectHits(m_node)) { + if (trianglePickingRequested) { + PickingUtils::TriangleCollisionGathererFunctor gathererFunctor; + gathererFunctor.m_frontFaceRequested = frontFaceRequested; + gathererFunctor.m_backFaceRequested = backFaceRequested; + gathererFunctor.m_manager = m_manager; + gathererFunctor.m_ray = ray; + sphereHits = QtConcurrent::blockingMappedReduced<HitList>(entityPicker.entities(), + gathererFunctor, reducerOp); + } else { + sphereHits = entityPicker.hits(); + PickingUtils::AbstractCollisionGathererFunctor::sortHits(sphereHits); + if (!allHitsRequested) + sphereHits = { sphereHits.front() }; + } } // Dispatch events based on hit results - dispatchPickEvents(event, sphereHits, eventButton, eventButtons, eventModifiers, trianglePickingRequested, allHitsRequested); + dispatchPickEvents(event, sphereHits, eventButton, eventButtons, eventModifiers, + trianglePickingRequested, allHitsRequested); } } @@ -331,17 +340,18 @@ void PickBoundingVolumeJob::dispatchPickEvents(const QMouseEvent &event, // Send the corresponding event QVector3D localIntersection = hit.m_intersection; if (entity && entity->worldTransform()) - localIntersection = hit.m_intersection * entity->worldTransform()->inverted(); + localIntersection = entity->worldTransform()->inverted() * hit.m_intersection; QPickEventPtr pickEvent; - if (trianglePickingRequested) + if (trianglePickingRequested) { pickEvent.reset(new QPickTriangleEvent(event.localPos(), hit.m_intersection, localIntersection, hit.m_distance, hit.m_triangleIndex, hit.m_vertexIndex[0], hit.m_vertexIndex[1], hit.m_vertexIndex[2], - eventButton, eventButtons, eventModifiers)); - else + eventButton, eventButtons, eventModifiers, hit.m_uvw)); + QPickEventPrivate::get(pickEvent.data())->m_entity = hit.m_entityId; + } else { pickEvent.reset(new QPickEvent(event.localPos(), hit.m_intersection, localIntersection, hit.m_distance, eventButton, eventButtons, eventModifiers)); - + } switch (event.type()) { case QEvent::MouseButtonPress: { // Store pressed object handle @@ -352,24 +362,23 @@ void PickBoundingVolumeJob::dispatchPickEvents(const QMouseEvent &event, } case QEvent::MouseButtonRelease: { - if (lastCurrentPicker != nullptr && m_currentPicker == objectPickerHandle) - m_currentPicker = HObjectPicker(); // Only send the release event if it was pressed - if (objectPicker->isPressed()) { - if (lastCurrentPicker == objectPicker) - objectPicker->onClicked(pickEvent); + if (objectPicker->isPressed()) objectPicker->onReleased(pickEvent); + if (lastCurrentPicker != nullptr && m_currentPicker == objectPickerHandle) { + objectPicker->onClicked(pickEvent); + m_currentPicker = HObjectPicker(); } break; } - +#if QT_CONFIG(gestures) case Qt::TapGesture: { objectPicker->onClicked(pickEvent); break; } - +#endif case QEvent::MouseMove: { - if (objectPicker->isPressed() && objectPicker->isDragEnabled()) { + if ((objectPicker->isPressed() || objectPicker->isHoverEnabled()) && objectPicker->isDragEnabled()) { objectPicker->onMoved(pickEvent); } // fallthrough diff --git a/src/render/jobs/pickboundingvolumejob_p.h b/src/render/jobs/pickboundingvolumejob_p.h index 9f52943d1..5239c5c6c 100644 --- a/src/render/jobs/pickboundingvolumejob_p.h +++ b/src/render/jobs/pickboundingvolumejob_p.h @@ -59,6 +59,7 @@ #include <Qt3DRender/private/pickboundingvolumeutils_p.h> #include <Qt3DRender/qpickevent.h> #include <QMouseEvent> +#include <QKeyEvent> #include <QSharedPointer> QT_BEGIN_NAMESPACE @@ -82,6 +83,7 @@ public: void setRoot(Entity *root); void setMouseEvents(const QList<QMouseEvent> &pendingEvents); + void setKeyEvents(const QList<QKeyEvent> &pendingEvents); void setFrameGraphRoot(FrameGraphNode *frameGraphRoot); void setRenderSettings(RenderSettings *settings); void setManagers(NodeManagers *manager); @@ -102,8 +104,10 @@ protected: void run() Q_DECL_FINAL; void dispatchPickEvents(const QMouseEvent &event, const PickingUtils::CollisionVisitor::HitList &sphereHits, QPickEvent::Buttons eventButton, - int eventButtons, int eventModifiers, - bool trianglePickingRequested, bool allHitsRequested); + int eventButtons, + int eventModifiers, + bool trianglePickingRequested, + bool allHitsRequested); private: NodeManagers *m_manager; @@ -115,6 +119,8 @@ private: bool m_oneEnabledAtLeast; bool m_oneHoverAtLeast; + QList<QKeyEvent> m_pendingKeyEvents; + void viewMatrixForCamera(Qt3DCore::QNodeId cameraId, QMatrix4x4 &viewMatrix, QMatrix4x4 &projectionMatrix) const; diff --git a/src/render/jobs/pickboundingvolumeutils.cpp b/src/render/jobs/pickboundingvolumeutils.cpp index 1573aa112..f08398a5a 100644 --- a/src/render/jobs/pickboundingvolumeutils.cpp +++ b/src/render/jobs/pickboundingvolumeutils.cpp @@ -175,6 +175,7 @@ bool CollisionVisitor::intersectsSegmentTriangle(uint andx, const QVector3D &a, queryResult.m_vertexIndex[0] = andx; queryResult.m_vertexIndex[1] = bndx; queryResult.m_vertexIndex[2] = cndx; + queryResult.m_uvw = uvw; queryResult.m_intersection = m_ray.point(t * m_ray.distance()); queryResult.m_distance = m_ray.projectedDistance(queryResult.m_intersection); hits.push_back(queryResult); @@ -212,6 +213,15 @@ AbstractCollisionGathererFunctor::result_type AbstractCollisionGathererFunctor:: return pick(&rayCasting, entity); } +void AbstractCollisionGathererFunctor::sortHits(CollisionVisitor::HitList &results) +{ + auto compareHitsDistance = [](const CollisionVisitor::HitList::value_type &a, + const CollisionVisitor::HitList::value_type &b) { + return a.m_distance < b.m_distance; + }; + std::sort(results.begin(), results.end(), compareHitsDistance); +} + AbstractCollisionGathererFunctor::result_type EntityCollisionGathererFunctor::pick(RayCasting::QAbstractCollisionQueryService *rayCasting, const Entity *entity) const { result_type result; @@ -236,14 +246,7 @@ AbstractCollisionGathererFunctor::result_type TriangleCollisionGathererFunctor:: visitor.apply(gRenderer, entity->peerId()); result = visitor.hits; - struct - { - bool operator()(const result_type::value_type &a, const result_type::value_type &b) - { - return a.m_distance < b.m_distance; - } - } compareHitsDistance; - std::sort(result.begin(), result.end(), compareHitsDistance); + sortHits(result); } return result; @@ -281,6 +284,44 @@ CollisionVisitor::HitList reduceToAllHits(CollisionVisitor::HitList &results, co return results; } +HierarchicalEntityPicker::HierarchicalEntityPicker(const QRay3D &ray) + : m_ray(ray) +{ + +} + +bool HierarchicalEntityPicker::collectHits(Entity *root) +{ + m_hits.clear(); + m_entities.clear(); + + QRayCastingService rayCasting; + QVector<Entity *> worklist; + worklist << root; + + while (!worklist.empty()) { + Entity *current = worklist.takeLast(); + + // first pick entry sub-scene-graph + QCollisionQueryResult::Hit queryResult = + rayCasting.query(m_ray, current->worldBoundingVolumeWithChildren()); + if (queryResult.m_distance < 0.f) + continue; + + // if we get a hit, we check again for this specific entity + queryResult = rayCasting.query(m_ray, current->worldBoundingVolume()); + if (queryResult.m_distance >= 0.f) { + m_entities.push_back(current); + m_hits.push_back(queryResult); + } + + // and pick children + worklist << current->children(); + } + + return !m_hits.empty(); +} + } // PickingUtils } // Render diff --git a/src/render/jobs/pickboundingvolumeutils_p.h b/src/render/jobs/pickboundingvolumeutils_p.h index 0a65c58cc..08615c094 100644 --- a/src/render/jobs/pickboundingvolumeutils_p.h +++ b/src/render/jobs/pickboundingvolumeutils_p.h @@ -136,6 +136,21 @@ private: uint cndx, const QVector3D &c); }; +class Q_AUTOTEST_EXPORT HierarchicalEntityPicker +{ +public: + explicit HierarchicalEntityPicker(const RayCasting::QRay3D &ray); + + bool collectHits(Entity *root); + inline CollisionVisitor::HitList hits() const { return m_hits; } + inline QVector<Entity *> entities() const { return m_entities; } + +private: + RayCasting::QRay3D m_ray; + CollisionVisitor::HitList m_hits; + QVector<Entity *> m_entities; +}; + struct Q_AUTOTEST_EXPORT AbstractCollisionGathererFunctor { AbstractCollisionGathererFunctor(); @@ -148,6 +163,8 @@ struct Q_AUTOTEST_EXPORT AbstractCollisionGathererFunctor typedef CollisionVisitor::HitList result_type; result_type operator ()(const Entity *entity) const; virtual result_type pick(RayCasting::QAbstractCollisionQueryService *rayCasting, const Entity *entity) const = 0; + + static void sortHits(CollisionVisitor::HitList &results); }; struct Q_AUTOTEST_EXPORT EntityCollisionGathererFunctor : public AbstractCollisionGathererFunctor diff --git a/src/render/jobs/renderviewjobutils.cpp b/src/render/jobs/renderviewjobutils.cpp index e587dd828..9f1b51cc1 100644 --- a/src/render/jobs/renderviewjobutils.cpp +++ b/src/render/jobs/renderviewjobutils.cpp @@ -63,6 +63,7 @@ #include <Qt3DRender/private/dispatchcompute_p.h> #include <Qt3DRender/private/rendersurfaceselector_p.h> #include <Qt3DRender/private/rendercapture_p.h> +#include <Qt3DRender/private/buffercapture_p.h> #include <Qt3DRender/private/stringtoint_p.h> #include <Qt3DRender/private/techniquemanager_p.h> #include <Qt3DRender/private/memorybarrier_p.h> @@ -164,6 +165,7 @@ void setRenderViewConfigFromFrameGraphLeafNode(RenderView *rv, const FrameGraphN // a subregion relative to that of the parent viewport const ViewportNode *vpNode = static_cast<const ViewportNode *>(node); rv->setViewport(computeViewport(rv->viewport(), vpNode)); + rv->setGamma(vpNode->gamma()); break; } @@ -238,7 +240,15 @@ void setRenderViewConfigFromFrameGraphLeafNode(RenderView *rv, const FrameGraphN case FrameGraphNode::MemoryBarrier: { const Render::MemoryBarrier *barrier = static_cast<const Render::MemoryBarrier *>(node); - rv->setMemoryBarrier(barrier->barrierTypes()|rv->memoryBarrier()); + rv->setMemoryBarrier(barrier->waitOperations()|rv->memoryBarrier()); + break; + } + + case FrameGraphNode::BufferCapture: { + auto *bufferCapture = const_cast<Render::BufferCapture *>( + static_cast<const Render::BufferCapture *>(node)); + if (bufferCapture != nullptr) + rv->setIsDownloadBuffersEnable(bufferCapture->isEnabled()); break; } @@ -404,7 +414,9 @@ const int qNodeIdTypeId = qMetaTypeId<QNodeId>(); } UniformBlockValueBuilder::UniformBlockValueBuilder() - : shaderDataManager(nullptr) + : updatedPropertiesOnly(false) + , shaderDataManager(nullptr) + , textureManager(nullptr) { } @@ -420,12 +432,16 @@ void UniformBlockValueBuilder::buildActiveUniformNameValueMapHelper(ShaderData * QVariantList list = value.value<QVariantList>(); if (list.at(0).userType() == qNodeIdTypeId) { // Array of struct qmlPropertyName[i].structMember for (int i = 0; i < list.size(); ++i) { + const QVariant variantElement = list.at(i); if (list.at(i).userType() == qNodeIdTypeId) { - ShaderData *subShaderData = shaderDataManager->lookupResource(list.at(i).value<QNodeId>()); - if (subShaderData) + const auto nodeId = variantElement.value<QNodeId>(); + ShaderData *subShaderData = shaderDataManager->lookupResource(nodeId); + if (subShaderData) { buildActiveUniformNameValueMapStructHelper(subShaderData, blockName + QLatin1Char('.') + qmlPropertyName + blockArray.arg(i), QLatin1String("")); + } + // Note: we only handle ShaderData as nested container nodes here } } } else { // Array of scalar/vec qmlPropertyName[0] @@ -436,11 +452,16 @@ void UniformBlockValueBuilder::buildActiveUniformNameValueMapHelper(ShaderData * } } } else if (value.userType() == qNodeIdTypeId) { // Struct qmlPropertyName.structMember - ShaderData *rSubShaderData = shaderDataManager->lookupResource(value.value<QNodeId>()); - if (rSubShaderData) + const auto nodeId = value.value<QNodeId>(); + ShaderData *rSubShaderData = shaderDataManager->lookupResource(nodeId); + if (rSubShaderData) { buildActiveUniformNameValueMapStructHelper(rSubShaderData, blockName, qmlPropertyName); + } else if (textureManager->contains(nodeId)) { + const auto varId = StringToInt::lookupId(blockName + QLatin1Char('.') + qmlPropertyName); + activeUniformNamesToValue.insert(varId, value); + } } else { // Scalar / Vec QString varName = blockName + QLatin1Char('.') + qmlPropertyName; if (uniforms.contains(varName)) { diff --git a/src/render/jobs/renderviewjobutils_p.h b/src/render/jobs/renderviewjobutils_p.h index bc042a582..c1d37b28a 100644 --- a/src/render/jobs/renderviewjobutils_p.h +++ b/src/render/jobs/renderviewjobutils_p.h @@ -83,6 +83,7 @@ class NodeManagers; class ShaderDataManager; struct ShaderUniform; class ShaderData; +class TextureManager; class RenderStateManager; class RenderStateCollection; @@ -169,6 +170,7 @@ struct Q_AUTOTEST_EXPORT UniformBlockValueBuilder QHash<QString, ShaderUniform> uniforms; UniformBlockValueBuilderHash activeUniformNamesToValue; ShaderDataManager *shaderDataManager; + TextureManager *textureManager; QMatrix4x4 viewMatrix; }; diff --git a/src/render/jobs/sendbuffercapturejob.cpp b/src/render/jobs/sendbuffercapturejob.cpp new file mode 100644 index 000000000..7829931f7 --- /dev/null +++ b/src/render/jobs/sendbuffercapturejob.cpp @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Juan José Casafranca +** 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$ +** +****************************************************************************/ + +#include "sendbuffercapturejob_p.h" + + +#include "Qt3DRender/private/renderer_p.h" +#include "Qt3DRender/private/nodemanagers_p.h" +#include <Qt3DRender/private/job_common_p.h> +#include <Qt3DRender/private/buffer_p.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +namespace Render { + +SendBufferCaptureJob::SendBufferCaptureJob() + : Qt3DCore::QAspectJob() +{ + SET_JOB_RUN_STAT_TYPE(this, JobTypes::SendBufferCapture, 0); +} + +SendBufferCaptureJob::~SendBufferCaptureJob() +{ +} + +void SendBufferCaptureJob::setManagers(NodeManagers *managers) +{ + m_managers = managers; +} + +void SendBufferCaptureJob::addRequest(QPair<Buffer *, QByteArray> request) +{ + QMutexLocker locker(&m_mutex); + m_pendingSendBufferCaptures.push_back(request); +} + +void SendBufferCaptureJob::run() +{ + QMutexLocker locker(&m_mutex); + for (const QPair<Buffer*, QByteArray> &pendingCapture : qAsConst(m_pendingSendBufferCaptures)) { + pendingCapture.first->updateDataFromGPUToCPU(pendingCapture.second); + } + + m_pendingSendBufferCaptures.clear(); +} + +} // Render + +} // Qt3DRender + +QT_END_NAMESPACE diff --git a/src/render/jobs/sendbuffercapturejob_p.h b/src/render/jobs/sendbuffercapturejob_p.h new file mode 100644 index 000000000..d01ecec72 --- /dev/null +++ b/src/render/jobs/sendbuffercapturejob_p.h @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Juan José Casafranca +** 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_SENDBUFFERCAPTUREJOB_P_H +#define QT3DRENDER_SENDBUFFERCAPTUREJOB_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.h> +#include <Qt3DRender/qt3drender_global.h> +#include <Qt3DRender/private/qt3drender_global_p.h> +#include <QMutex> + + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +namespace Render { + +class NodeManagers; +class Entity; +class Renderer; +class Buffer; + +class QT3DRENDERSHARED_PRIVATE_EXPORT SendBufferCaptureJob : public Qt3DCore::QAspectJob +{ +public: + explicit SendBufferCaptureJob(); + ~SendBufferCaptureJob(); + + void setManagers(NodeManagers *managers); + + void addRequest(QPair<Buffer*, QByteArray> request); + + void run() Q_DECL_FINAL; + +private: + NodeManagers *m_managers; + QMutex m_mutex; + + QVector<QPair<Buffer*, QByteArray> > m_pendingSendBufferCaptures; +}; + +typedef QSharedPointer<SendBufferCaptureJob> SendBufferCaptureJobPtr; + +} //Render + +} //Qt3DRender + +QT_END_NAMESPACE + + +#endif // QT3DRENDER_SENDBUFFERCAPTUREJOB_P_H diff --git a/src/render/jobs/updatelevelofdetailjob.cpp b/src/render/jobs/updatelevelofdetailjob.cpp index 940d26850..24891f9b8 100644 --- a/src/render/jobs/updatelevelofdetailjob.cpp +++ b/src/render/jobs/updatelevelofdetailjob.cpp @@ -135,10 +135,10 @@ void UpdateLevelOfDetailJob::updateEntityLod(Entity *entity) if (lod->isEnabled() && !lod->thresholds().isEmpty()) { switch (lod->thresholdType()) { - case QLevelOfDetail::DistanceToCamera: + case QLevelOfDetail::DistanceToCameraThreshold: updateEntityLodByDistance(entity, lod); break; - case QLevelOfDetail::ProjectedScreenPixelSize: + case QLevelOfDetail::ProjectedScreenPixelSizeThreshold: updateEntityLodByScreenArea(entity, lod); break; default: @@ -162,7 +162,7 @@ void UpdateLevelOfDetailJob::updateEntityLodByDistance(Entity *entity, LevelOfDe const QVector<qreal> thresholds = lod->thresholds(); QVector3D center = lod->center(); - if (lod->radius() > 0.f || entity->worldBoundingVolume() == nullptr) { + if (lod->hasBoundingVolumeOverride() || entity->worldBoundingVolume() == nullptr) { center = *entity->worldTransform() * center; } else { center = entity->worldBoundingVolume()->center(); @@ -198,7 +198,7 @@ void UpdateLevelOfDetailJob::updateEntityLodByScreenArea(Entity *entity, LevelOf const QVector<qreal> thresholds = lod->thresholds(); Sphere bv(lod->center(), lod->radius()); - if (lod->radius() <= 0.f && entity->worldBoundingVolume() != nullptr) { + if (!lod->hasBoundingVolumeOverride() && entity->worldBoundingVolume() != nullptr) { bv = *(entity->worldBoundingVolume()); } else { bv.transform(*entity->worldTransform()); |