diff options
-rw-r--r-- | src/core/bounds/qaxisalignedboundingbox.h | 2 | ||||
-rw-r--r-- | src/render/backend/entity.cpp | 5 | ||||
-rw-r--r-- | src/render/backend/entity_p.h | 2 | ||||
-rw-r--r-- | src/render/frontend/qrenderaspect.cpp | 13 | ||||
-rw-r--r-- | src/render/frontend/qrenderaspect_p.h | 4 | ||||
-rw-r--r-- | src/render/geometry/qgeometryrenderer.h | 2 | ||||
-rw-r--r-- | src/render/jobs/calcboundingvolumejob.cpp | 130 | ||||
-rw-r--r-- | src/render/jobs/calcboundingvolumejob_p.h | 73 | ||||
-rw-r--r-- | src/render/jobs/framepreparationjob.cpp | 16 | ||||
-rw-r--r-- | src/render/jobs/jobs.pri | 6 | ||||
-rw-r--r-- | src/render/jobs/renderviewjobutils.cpp | 7 | ||||
-rw-r--r-- | src/render/jobs/updateboundingvolumejob.cpp | 10 | ||||
-rw-r--r-- | src/render/jobs/updateworldtransformjob.cpp | 1 |
13 files changed, 239 insertions, 32 deletions
diff --git a/src/core/bounds/qaxisalignedboundingbox.h b/src/core/bounds/qaxisalignedboundingbox.h index bf25fada3..8ef26871b 100644 --- a/src/core/bounds/qaxisalignedboundingbox.h +++ b/src/core/bounds/qaxisalignedboundingbox.h @@ -70,6 +70,8 @@ public: m_radii = QVector3D(); } + bool isNull() const { return m_center.isNull() && m_radii.isNull(); } + void update(const QVector<QVector3D> &points); inline QVector3D center() const { return m_center; } diff --git a/src/render/backend/entity.cpp b/src/render/backend/entity.cpp index e76eb2102..a0f8d4c98 100644 --- a/src/render/backend/entity.cpp +++ b/src/render/backend/entity.cpp @@ -67,6 +67,7 @@ Entity::Entity() , m_renderer(Q_NULLPTR) , m_localBoundingVolume(new Sphere) , m_worldBoundingVolume(new Sphere) + , m_worldBoundingVolumeWithChildren(new Sphere) { } @@ -102,10 +103,10 @@ void Entity::cleanup() } delete m_localBoundingVolume; delete m_worldBoundingVolume; + delete m_worldBoundingVolumeWithChildren; m_localBoundingVolume = Q_NULLPTR; m_worldBoundingVolume = Q_NULLPTR; - - + m_worldBoundingVolumeWithChildren = Q_NULLPTR; } void Entity::setParentHandle(HEntity parentHandle) diff --git a/src/render/backend/entity_p.h b/src/render/backend/entity_p.h index 947dccef1..74c8e1b51 100644 --- a/src/render/backend/entity_p.h +++ b/src/render/backend/entity_p.h @@ -103,6 +103,7 @@ public: const QMatrix4x4 *worldTransform() const; Sphere *localBoundingVolume() { return m_localBoundingVolume; } Sphere *worldBoundingVolume() { return m_worldBoundingVolume; } + Sphere *worldBoundingVolumeWithChildren() { return m_worldBoundingVolumeWithChildren; } void addComponent(Qt3DCore::QComponent *component); void removeComponent(const Qt3DCore::QNodeId &nodeId); @@ -164,6 +165,7 @@ private: HMatrix m_worldTransform; Sphere *m_localBoundingVolume; Sphere *m_worldBoundingVolume; + Sphere *m_worldBoundingVolumeWithChildren; // Handles to Components Qt3DCore::QNodeId m_transformComponent; diff --git a/src/render/frontend/qrenderaspect.cpp b/src/render/frontend/qrenderaspect.cpp index 3e9dffdcd..d67090ebb 100644 --- a/src/render/frontend/qrenderaspect.cpp +++ b/src/render/frontend/qrenderaspect.cpp @@ -273,7 +273,8 @@ QVector<Qt3DCore::QAspectJobPtr> QRenderAspect::jobsToExecute(qint64 time) d->m_framePreparationJob.reset(new Render::FramePreparationJob(d->m_renderer->renderSceneRoot())); d->m_cleanupJob.reset(new Render::FrameCleanupJob(d->m_renderer)); d->m_worldTransformJob.reset(new Render::UpdateWorldTransformJob(d->m_renderer->renderSceneRoot())); - d->m_boundingVolumeJob.reset(new Render::UpdateBoundingVolumeJob(d->m_renderer->renderSceneRoot())); + d->m_updateBoundingVolumeJob.reset(new Render::UpdateBoundingVolumeJob(d->m_renderer->renderSceneRoot())); + d->m_calculateBoundingVolumeJob.reset(new Render::CalculateBoundingVolumeJob(d->m_renderer, d->m_renderer->renderSceneRoot())); const QVector<QNodeId> texturesPending = d->m_renderer->textureDataManager()->texturesPending(); Q_FOREACH (const QNodeId &textureId, texturesPending) { @@ -298,12 +299,16 @@ QVector<Qt3DCore::QAspectJobPtr> QRenderAspect::jobsToExecute(qint64 time) // Create jobs to update transforms and bounding volumes // We can only update bounding volumes once all world transforms are known - d->m_boundingVolumeJob->addDependency(d->m_worldTransformJob); + d->m_updateBoundingVolumeJob->addDependency(d->m_worldTransformJob); d->m_framePreparationJob->addDependency(d->m_worldTransformJob); + // All world stuff depends on the RenderEntity's localBoundingVolume + d->m_worldTransformJob->addDependency(d->m_calculateBoundingVolumeJob); + // Add all jobs to queue + jobs.append(d->m_calculateBoundingVolumeJob); jobs.append(d->m_worldTransformJob); - jobs.append(d->m_boundingVolumeJob); + jobs.append(d->m_updateBoundingVolumeJob); jobs.append(d->m_framePreparationJob); // Traverse the current framegraph and create jobs to populate @@ -312,7 +317,7 @@ QVector<Qt3DCore::QAspectJobPtr> QRenderAspect::jobsToExecute(qint64 time) // TODO: Add wrapper around ThreadWeaver::Collection for (int i = 0; i < renderBinJobs.size(); ++i) { QAspectJobPtr renderBinJob = renderBinJobs.at(i); - renderBinJob->addDependency(d->m_boundingVolumeJob); + renderBinJob->addDependency(d->m_updateBoundingVolumeJob); jobs.append(renderBinJob); d->m_cleanupJob->addDependency(renderBinJob); } diff --git a/src/render/frontend/qrenderaspect_p.h b/src/render/frontend/qrenderaspect_p.h index 18b1ce91a..c4a54e017 100644 --- a/src/render/frontend/qrenderaspect_p.h +++ b/src/render/frontend/qrenderaspect_p.h @@ -52,6 +52,7 @@ #include <Qt3DRenderer/qrenderaspect.h> #include <Qt3DRenderer/private/updateboundingvolumejob_p.h> #include <Qt3DRenderer/private/updateworldtransformjob_p.h> +#include <Qt3DRenderer/private/calcboundingvolumejob_p.h> #include <Qt3DRenderer/private/framepreparationjob_p.h> #include <Qt3DRenderer/private/framecleanupjob_p.h> #include <Qt3DRenderer/private/platformsurfacefilter_p.h> @@ -86,7 +87,8 @@ class QRenderAspectPrivate : public Qt3DCore::QAbstractAspectPrivate Render::FramePreparationJobPtr m_framePreparationJob; Render::FrameCleanupJobPtr m_cleanupJob; Render::UpdateWorldTransformJobPtr m_worldTransformJob; - Render::UpdateBoundingVolumeJobPtr m_boundingVolumeJob; + Render::UpdateBoundingVolumeJobPtr m_updateBoundingVolumeJob; + Render::CalculateBoundingVolumeJobPtr m_calculateBoundingVolumeJob; }; } diff --git a/src/render/geometry/qgeometryrenderer.h b/src/render/geometry/qgeometryrenderer.h index 31e42e2db..bb4d8a85b 100644 --- a/src/render/geometry/qgeometryrenderer.h +++ b/src/render/geometry/qgeometryrenderer.h @@ -82,7 +82,7 @@ public: }; Q_ENUM(PrimitiveType) - // how to figure out index count, bounding boxes, and all the fancy stuff that QMeshData provides for us? + // how to figure out index count and all the fancy stuff that QMeshData provides for us? // also how to figure out which attribute(s?) hold the indices? int instanceCount() const; diff --git a/src/render/jobs/calcboundingvolumejob.cpp b/src/render/jobs/calcboundingvolumejob.cpp new file mode 100644 index 000000000..798de964d --- /dev/null +++ b/src/render/jobs/calcboundingvolumejob.cpp @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Copyright (C) 2015 The Qt Company Ltd and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "calcboundingvolumejob_p.h" + +#include <Qt3DRenderer/private/renderer_p.h> +#include <Qt3DRenderer/private/entity_p.h> +#include <Qt3DRenderer/private/renderlogging_p.h> +#include <Qt3DRenderer/private/managers_p.h> +#include <Qt3DRenderer/private/geometryrenderer_p.h> +#include <Qt3DRenderer/private/buffermanager_p.h> +#include <Qt3DRenderer/private/buffer_p.h> +#include <Qt3DRenderer/sphere.h> +#include <Qt3DCore/qaxisalignedboundingbox.h> + +#include <QtCore/qmath.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { +namespace Render { + +namespace { + +void calculateLocalBoundingVolume(Renderer *renderer, Entity *node) +{ + Qt3DRender::Render::GeometryRenderer *mesh = node->renderComponent<GeometryRenderer>(); + if (mesh) { + Geometry *geom = renderer->geometryManager()->lookupResource(mesh->geometryId()); + if (geom) { + Q_FOREACH (const Qt3DCore::QNodeId &attrId, geom->attributes()) { + Attribute *attr = renderer->attributeManager()->lookupResource(attrId); + if (!attr + || attr->attributeType() != Qt3DCore::QAbstractAttribute::VertexAttribute + || !attr->isDirty() + || attr->name() != QAttribute::defaultPositionAttributeName() + || attr->dataType() != Qt3DCore::QAbstractAttribute::Float + || attr->dataSize() < 3) + continue; + + Buffer *buf = renderer->bufferManager()->lookupResource(attr->bufferId()); + // No point in continuing if the positionAttribute doesn't have a suitable buffer + if (!buf) + break; + + Qt3DCore::QAxisAlignedBoundingBox bbox; + const QByteArray buffer = buf->data(); + const char *rawBuffer = buffer.constData(); + rawBuffer += attr->byteOffset(); + const int stride = attr->byteStride() ? attr->byteStride() : sizeof(float) * attr->dataSize(); + QVector<QVector3D> vertices(attr->count()); + + // TO DO: We don't need to create a vector of QVector3D + // to build bbox used to then build a sphere, we could build the sphere + // by just looking at the vertices using more efficient algorithms (EPOS, Ritters) + for (int c = 0, vC = vertices.size(); c < vC; ++c) { + QVector3D v; + const float *fptr = reinterpret_cast<const float*>(rawBuffer); + for (uint i = 0, m = qMin(attr->dataSize(), 3U); i < m; ++i) + v[i] = fptr[i]; + vertices[c] = v; + rawBuffer += stride; + } + //Phase 1 + bbox.update(vertices); + + //Phase 2 + node->localBoundingVolume()->setCenter(bbox.center()); + node->localBoundingVolume()->setRadius(bbox.maxExtent() * 0.5f); + break; + } + } + } + + Q_FOREACH (Entity *child, node->children()) + calculateLocalBoundingVolume(renderer, child); +} + +} // anonymous + +CalculateBoundingVolumeJob::CalculateBoundingVolumeJob(Renderer *renderer, Entity *node) + : m_renderer(renderer), + m_node(node) +{ +} + +void CalculateBoundingVolumeJob::run() +{ + calculateLocalBoundingVolume(m_renderer, m_node); +} + +} // namespace Render +} // namespace Qt3DRender + +QT_END_NAMESPACE + diff --git a/src/render/jobs/calcboundingvolumejob_p.h b/src/render/jobs/calcboundingvolumejob_p.h new file mode 100644 index 000000000..3ab704b7b --- /dev/null +++ b/src/render/jobs/calcboundingvolumejob_p.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Copyright (C) 2015 The Qt Company Ltd and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DRENDER_RENDER_CALCBOUNDINGVOLUMEJOB_H +#define QT3DRENDER_RENDER_CALCBOUNDINGVOLUMEJOB_H + +#include <Qt3DCore/qaspectjob.h> + +#include <QSharedPointer> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { +namespace Render { + +class Renderer; +class Entity; + +class CalculateBoundingVolumeJob : public Qt3DCore::QAspectJob +{ +public: + CalculateBoundingVolumeJob(Renderer *renderer, Entity *node); + +protected: + void run() Q_DECL_OVERRIDE; + +private: + Renderer *m_renderer; + Entity *m_node; +}; + +typedef QSharedPointer<CalculateBoundingVolumeJob> CalculateBoundingVolumeJobPtr; + +} // namespace Render +} // namespace Qt3DRender + +QT_END_NAMESPACE + +#endif // QT3DRENDER_RENDER_CALCBOUNDINGVOLUMEJOB_H diff --git a/src/render/jobs/framepreparationjob.cpp b/src/render/jobs/framepreparationjob.cpp index 8b98fb54d..8578cdb7f 100644 --- a/src/render/jobs/framepreparationjob.cpp +++ b/src/render/jobs/framepreparationjob.cpp @@ -62,22 +62,6 @@ void FramePreparationJob::run() void FramePreparationJob::parseNodeTree(Entity *node) { - // Initialize worldBoundingVolume if Mesh associated - Qt3DRender::Render::GeometryRenderer *mesh = Q_NULLPTR; - if ((node->localBoundingVolume()->isNull()) - && (mesh = node->renderComponent<GeometryRenderer>()) != Q_NULLPTR) { - // if (!mesh->meshDataHandle().isNull()) { - // Qt3DRender::QMeshData *meshData = mesh->meshData(); - // if (meshData != Q_NULLPTR) { - // const QAxisAlignedBoundingBox box = meshData->boundingBox(); - // node->localBoundingVolume()->setCenter(box.center()); - // const QVector3D &radii = box.radii(); - // node->localBoundingVolume()->setRadius(qMax(radii.x(), qMax(radii.y(), radii.z()))); - // } - // } - // TO DO: Make that work with the GeometryRenderer - } - // Update transform properties in ShaderData QList<ShaderData *> shadersData = node->renderComponents<ShaderData>(); Q_FOREACH (ShaderData *r, shadersData) { diff --git a/src/render/jobs/jobs.pri b/src/render/jobs/jobs.pri index 2c9b93a4e..166ee8554 100644 --- a/src/render/jobs/jobs.pri +++ b/src/render/jobs/jobs.pri @@ -10,7 +10,8 @@ HEADERS += \ $$PWD/framepreparationjob_p.h \ $$PWD/loadtexturedatajob_p.h \ $$PWD/loadbufferjob_p.h \ - $$PWD/loadgeometryjob_p.h + $$PWD/loadgeometryjob_p.h \ + $$PWD/calcboundingvolumejob_p.h SOURCES += \ $$PWD/updateworldtransformjob.cpp \ @@ -22,4 +23,5 @@ SOURCES += \ $$PWD/framepreparationjob.cpp \ $$PWD/loadtexturedatajob.cpp \ $$PWD/loadbufferjob.cpp \ - $$PWD/loadgeometryjob.cpp + $$PWD/loadgeometryjob.cpp \ + $$PWD/calcboundingvolumejob.cpp diff --git a/src/render/jobs/renderviewjobutils.cpp b/src/render/jobs/renderviewjobutils.cpp index 7de8e4726..9d4d52797 100644 --- a/src/render/jobs/renderviewjobutils.cpp +++ b/src/render/jobs/renderviewjobutils.cpp @@ -95,7 +95,12 @@ void setRenderViewConfigFromFrameGraphLeafNode(RenderView *rv, const FrameGraphN if (lens && lens->isEnabled()) { rv->setRenderCamera(lens); rv->setViewMatrix(*camNode->worldTransform()); - rv->setEyePosition(camNode->worldBoundingVolume()->center()); + + //To get the eyePostion of the camera, we need to use the inverse of the + //camera's worldTransform matrix. + const QMatrix4x4 inverseWorldTransform = camNode->worldTransform()->inverted(); + const QVector3D eyePostion(inverseWorldTransform.column(3)); + rv->setEyePosition(eyePostion); } } break; diff --git a/src/render/jobs/updateboundingvolumejob.cpp b/src/render/jobs/updateboundingvolumejob.cpp index 3c8f47262..7ec3c110c 100644 --- a/src/render/jobs/updateboundingvolumejob.cpp +++ b/src/render/jobs/updateboundingvolumejob.cpp @@ -69,14 +69,14 @@ void expandWorldBoundingVolume(Qt3DRender::Render::Entity *node) // Initialize parent bounding volume to be equal to that of the first child Qt3DRender::Render::Entity *parentNode = currentNode->parent(); - Qt3DRender::Sphere *parentBoundingVolume = parentNode->worldBoundingVolume(); - *(parentBoundingVolume) = *(currentNode->worldBoundingVolume()); + Qt3DRender::Sphere *parentBoundingVolume = parentNode->worldBoundingVolumeWithChildren(); + *(parentBoundingVolume) = *(currentNode->worldBoundingVolumeWithChildren()); // Expand the parent bounding volume by each of remaining the siblings QVector<Entity *> siblings = parentNode->children(); const int siblingCount = siblings.count(); for (int i = 1; i < siblingCount; ++i) { - Qt3DRender::Sphere *siblingBoundingVolume = siblings.at(i)->worldBoundingVolume(); + Qt3DRender::Sphere *siblingBoundingVolume = siblings.at(i)->worldBoundingVolumeWithChildren(); parentBoundingVolume->expandToContain(*siblingBoundingVolume); } @@ -101,8 +101,8 @@ UpdateBoundingVolumeJob::UpdateBoundingVolumeJob(Entity *node) void UpdateBoundingVolumeJob::run() { - // Expand the bounding volumes of each node that has children by the - // bounding volumes of the children + // Expand worldBoundingVolumeWithChildren of each node that has children by the + // bounding volumes of the children. // TODO: Implement this using a parallel_for qCDebug(Jobs) << "Entering" << Q_FUNC_INFO << QThread::currentThread(); diff --git a/src/render/jobs/updateworldtransformjob.cpp b/src/render/jobs/updateworldtransformjob.cpp index 736325560..ba338f676 100644 --- a/src/render/jobs/updateworldtransformjob.cpp +++ b/src/render/jobs/updateworldtransformjob.cpp @@ -59,6 +59,7 @@ void updateWorldTransformAndBounds(Qt3DRender::Render::Entity *node, const QMatr *(node->worldTransform()) = worldTransform; *(node->worldBoundingVolume()) = node->localBoundingVolume()->transformed(worldTransform); + *(node->worldBoundingVolumeWithChildren()) = *(node->worldBoundingVolume()); // expanded in UpdateBoundingVolumeJob Q_FOREACH (Qt3DRender::Render::Entity *child, node->children()) updateWorldTransformAndBounds(child, worldTransform); |