diff options
author | Mike Krus <mike.krus@kdab.com> | 2017-01-25 08:07:42 +0000 |
---|---|---|
committer | Mike Krus <mike.krus@kdab.com> | 2017-05-23 17:31:00 +0000 |
commit | 939b9b4b7591e8a421cf048a0a84ed3e75d81d21 (patch) | |
tree | 828ee7a6862ec5c0bd24f97cb540625a2c647376 /src/render/backend | |
parent | e27ce2bf3b76ab4ed09508f780a8601875ea2fe8 (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.h | 1 | ||||
-rw-r--r-- | src/render/backend/cameralens.cpp | 88 | ||||
-rw-r--r-- | src/render/backend/cameralens_p.h | 7 | ||||
-rw-r--r-- | src/render/backend/renderer.cpp | 5 | ||||
-rw-r--r-- | src/render/backend/renderer_p.h | 2 |
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; } |