summaryrefslogtreecommitdiffstats
path: root/src/render/backend
diff options
context:
space:
mode:
authorMike Krus <mike.krus@kdab.com>2017-01-25 08:07:42 +0000
committerMike Krus <mike.krus@kdab.com>2017-05-23 17:31:00 +0000
commit939b9b4b7591e8a421cf048a0a84ed3e75d81d21 (patch)
tree828ee7a6862ec5c0bd24f97cb540625a2c647376 /src/render/backend
parente27ce2bf3b76ab4ed09508f780a8601875ea2fe8 (diff)
Add support to move the camera so that the entire model is visible
Adds QCamera::viewAll(), QCamera::viewEntity() and QCamera::viewSphere() to move and rotate the camera so that the view center is the center of the sphere and the sphere fits inside the viewport Only works in perspective projection. Introduces a job to compute the bounding sphere of the scene excluding the camera. Change-Id: Id9d67787ea91c354009d5358d5db63a1c9480c70 Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
Diffstat (limited to 'src/render/backend')
-rw-r--r--src/render/backend/abstractrenderer_p.h1
-rw-r--r--src/render/backend/cameralens.cpp88
-rw-r--r--src/render/backend/cameralens_p.h7
-rw-r--r--src/render/backend/renderer.cpp5
-rw-r--r--src/render/backend/renderer_p.h2
5 files changed, 99 insertions, 4 deletions
diff --git a/src/render/backend/abstractrenderer_p.h b/src/render/backend/abstractrenderer_p.h
index f8d9850e7..2f7545454 100644
--- a/src/render/backend/abstractrenderer_p.h
+++ b/src/render/backend/abstractrenderer_p.h
@@ -139,6 +139,7 @@ public:
virtual QVector<Qt3DCore::QAspectJobPtr> renderBinJobs() = 0;
virtual Qt3DCore::QAspectJobPtr pickBoundingVolumeJob() = 0;
virtual Qt3DCore::QAspectJobPtr syncTextureLoadingJob() = 0;
+ virtual Qt3DCore::QAspectJobPtr expandBoundingVolumeJob() = 0;
virtual void setSceneRoot(Qt3DCore::QBackendNodeFactory *factory, Entity *root) = 0;
diff --git a/src/render/backend/cameralens.cpp b/src/render/backend/cameralens.cpp
index 5bb3ca863..ef71507eb 100644
--- a/src/render/backend/cameralens.cpp
+++ b/src/render/backend/cameralens.cpp
@@ -39,10 +39,14 @@
#include "cameralens_p.h"
#include <Qt3DRender/qcameralens.h>
+#include <Qt3DRender/private/nodemanagers_p.h>
+#include <Qt3DRender/private/managers_p.h>
#include <Qt3DRender/private/qcameralens_p.h>
#include <Qt3DRender/private/renderlogging_p.h>
-#include <Qt3DRender/private/managers_p.h>
-#include <Qt3DRender/private/nodemanagers_p.h>
+#include <Qt3DRender/private/renderer_p.h>
+#include <Qt3DRender/private/entity_p.h>
+#include <Qt3DRender/private/sphere_p.h>
+#include <Qt3DRender/private/computefilteredboundingvolumejob_p.h>
#include <Qt3DCore/qentity.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qtransform.h>
@@ -54,8 +58,33 @@ using namespace Qt3DCore;
namespace Qt3DRender {
namespace Render {
+
+namespace {
+
+class GetBoundingVolumeWithoutCameraJob : public ComputeFilteredBoundingVolumeJob
+{
+public:
+ GetBoundingVolumeWithoutCameraJob(CameraLens *lens,
+ QNodeCommand::CommandId commandId)
+ : m_lens(lens), m_commandId(commandId)
+ {
+ }
+
+protected:
+ void finished(const Sphere &sphere) override
+ {
+ m_lens->notifySceneBoundingVolume(sphere, m_commandId);
+ }
+
+private:
+ CameraLens *m_lens;
+ QNodeCommand::CommandId m_commandId;
+};
+
+} // namespace
+
CameraLens::CameraLens()
- : BackendNode()
+ : BackendNode(QBackendNode::ReadWrite)
, m_renderAspect(nullptr)
, m_exposure(0.0f)
{
@@ -84,6 +113,41 @@ void CameraLens::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &c
m_exposure = data.exposure;
}
+void CameraLens::computeSceneBoundingVolume(QNodeId entityId,
+ QNodeId cameraId,
+ QNodeCommand::CommandId commandId)
+{
+ if (!m_renderer || !m_renderAspect)
+ return;
+ NodeManagers *nodeManagers = m_renderer->nodeManagers();
+
+ Entity *root = m_renderer->sceneRoot();
+ if (!entityId.isNull())
+ root = nodeManagers->renderNodesManager()->lookupResource(entityId);
+ if (!root)
+ return;
+
+ Entity *camNode = nodeManagers->renderNodesManager()->lookupResource(cameraId);
+ ComputeFilteredBoundingVolumeJobPtr job(new GetBoundingVolumeWithoutCameraJob(this, commandId));
+ job->addDependency(m_renderer->expandBoundingVolumeJob());
+ job->setRoot(root);
+ job->ignoreSubTree(camNode);
+ m_renderAspect->scheduleSingleShotJob(job);
+}
+
+void CameraLens::notifySceneBoundingVolume(const Sphere &sphere, QNodeCommand::CommandId commandId)
+{
+ if (m_pendingViewAllCommand != commandId)
+ return;
+ if (sphere.radius() > 0.f) {
+ QVector<float> data = { sphere.center().x(), sphere.center().y(), sphere.center().z(),
+ sphere.radius() };
+ QVariant v;
+ v.setValue(data);
+ sendCommand(QLatin1Literal("ViewAll"), v, m_pendingViewAllCommand);
+ }
+}
+
void CameraLens::setProjection(const QMatrix4x4 &projection)
{
m_projection = projection;
@@ -111,6 +175,24 @@ void CameraLens::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
}
break;
+ case CommandRequested: {
+ QNodeCommandPtr command = qSharedPointerCast<QNodeCommand>(e);
+
+ if (command->name() == QLatin1Literal("QueryRootBoundingVolume")) {
+ m_pendingViewAllCommand = command->commandId();
+ QVariant v = command->data();
+ QNodeId id = v.value<QNodeId>();
+ computeSceneBoundingVolume({}, id, command->commandId());
+ } else if (command->name() == QLatin1Literal("QueryEntityBoundingVolume")) {
+ m_pendingViewAllCommand = command->commandId();
+ QVariant v = command->data();
+ QVector<QNodeId> ids = v.value<QVector<QNodeId>>();
+ if (ids.size() == 2)
+ computeSceneBoundingVolume(ids[0], ids[1], command->commandId());
+ }
+ }
+ break;
+
default:
break;
}
diff --git a/src/render/backend/cameralens_p.h b/src/render/backend/cameralens_p.h
index 4d9df84e1..4bf147f48 100644
--- a/src/render/backend/cameralens_p.h
+++ b/src/render/backend/cameralens_p.h
@@ -52,6 +52,7 @@
//
#include <Qt3DRender/private/backendnode_p.h>
+#include <Qt3DCore/private/qnodecommand_p.h>
#include <QMatrix4x4>
#include <QRectF>
@@ -62,6 +63,7 @@ namespace Qt3DRender {
namespace Render {
class CameraManager;
+class Sphere;
class CameraLensFunctor : public Qt3DCore::QBackendNodeMapper
{
@@ -93,12 +95,17 @@ public:
inline float exposure() const { return m_exposure; }
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Q_DECL_OVERRIDE;
+ void notifySceneBoundingVolume(const Sphere &sphere, Qt3DCore::QNodeCommand::CommandId commandId);
private:
void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL;
+ void computeSceneBoundingVolume(Qt3DCore::QNodeId entityId,
+ Qt3DCore::QNodeId cameraId,
+ Qt3DCore::QNodeCommand::CommandId commandId);
QRenderAspect *m_renderAspect;
QMatrix4x4 m_projection;
+ Qt3DCore::QNodeCommand::CommandId m_pendingViewAllCommand;
float m_exposure;
};
diff --git a/src/render/backend/renderer.cpp b/src/render/backend/renderer.cpp
index 6cc0dba7b..b89f21522 100644
--- a/src/render/backend/renderer.cpp
+++ b/src/render/backend/renderer.cpp
@@ -1467,6 +1467,11 @@ QAspectJobPtr Renderer::syncTextureLoadingJob()
return m_syncTextureLoadingJob;
}
+QAspectJobPtr Renderer::expandBoundingVolumeJob()
+{
+ return m_expandBoundingVolumeJob;
+}
+
QAbstractFrameAdvanceService *Renderer::frameAdvanceService() const
{
return static_cast<Qt3DCore::QAbstractFrameAdvanceService *>(m_vsyncFrameAdvanceService.data());
diff --git a/src/render/backend/renderer_p.h b/src/render/backend/renderer_p.h
index de0b2a59b..e311261e0 100644
--- a/src/render/backend/renderer_p.h
+++ b/src/render/backend/renderer_p.h
@@ -189,11 +189,11 @@ public:
QVector<Qt3DCore::QAspectJobPtr> renderBinJobs() Q_DECL_OVERRIDE;
Qt3DCore::QAspectJobPtr pickBoundingVolumeJob() Q_DECL_OVERRIDE;
Qt3DCore::QAspectJobPtr syncTextureLoadingJob() Q_DECL_OVERRIDE;
+ Qt3DCore::QAspectJobPtr expandBoundingVolumeJob() Q_DECL_OVERRIDE;
QVector<Qt3DCore::QAspectJobPtr> createRenderBufferJobs() const;
inline FrameCleanupJobPtr frameCleanupJob() const { return m_cleanupJob; }
- inline ExpandBoundingVolumeJobPtr expandBoundingVolumeJob() const { return m_expandBoundingVolumeJob; }
inline UpdateShaderDataTransformJobPtr updateShaderDataTransformJob() const { return m_updateShaderDataTransformJob; }
inline CalculateBoundingVolumeJobPtr calculateBoundingVolumeJob() const { return m_calculateBoundingVolumeJob; }
inline UpdateTreeEnabledJobPtr updateTreeEnabledJob() const { return m_updateTreeEnabledJob; }