summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/core/bounds/qaxisalignedboundingbox.h2
-rw-r--r--src/render/backend/entity.cpp5
-rw-r--r--src/render/backend/entity_p.h2
-rw-r--r--src/render/frontend/qrenderaspect.cpp13
-rw-r--r--src/render/frontend/qrenderaspect_p.h4
-rw-r--r--src/render/geometry/qgeometryrenderer.h2
-rw-r--r--src/render/jobs/calcboundingvolumejob.cpp130
-rw-r--r--src/render/jobs/calcboundingvolumejob_p.h73
-rw-r--r--src/render/jobs/framepreparationjob.cpp16
-rw-r--r--src/render/jobs/jobs.pri6
-rw-r--r--src/render/jobs/renderviewjobutils.cpp7
-rw-r--r--src/render/jobs/updateboundingvolumejob.cpp10
-rw-r--r--src/render/jobs/updateworldtransformjob.cpp1
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);