summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMike Krus <mike.krus@kdab.com>2018-01-15 20:58:15 +0000
committerMike Krus <mike.krus@kdab.com>2018-02-01 20:05:57 +0000
commit89ec1b820a3be3ab5d3abb408bea4408954e82ac (patch)
treef46f92a25f38db8dc6435a8d503801334192b1fc /src
parent2a4ecc509d6bc810b4bcdd09220c38f92614032e (diff)
Ray casting job
Does the intersection calculations and sends hits back to frontend object. The entity pointer is updated in the front end before emitting the signal. This is done using private friend method to avoid detaching the hit object and causing a copy. Change-Id: If2fa0573f8f7120f2dcbb433c46efe1859f0eb5f Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
Diffstat (limited to 'src')
-rw-r--r--src/render/backend/abstractrenderer_p.h1
-rw-r--r--src/render/backend/renderer.cpp16
-rw-r--r--src/render/backend/renderer_p.h3
-rw-r--r--src/render/frontend/qrenderaspect.cpp6
-rw-r--r--src/render/jobs/job_common_p.h1
-rw-r--r--src/render/jobs/jobs.pri6
-rw-r--r--src/render/jobs/raycastingjob.cpp265
-rw-r--r--src/render/jobs/raycastingjob_p.h115
-rw-r--r--src/render/picking/raycaster.cpp10
-rw-r--r--src/render/picking/raycaster_p.h1
10 files changed, 418 insertions, 6 deletions
diff --git a/src/render/backend/abstractrenderer_p.h b/src/render/backend/abstractrenderer_p.h
index c934dbfae..a9d6f19a5 100644
--- a/src/render/backend/abstractrenderer_p.h
+++ b/src/render/backend/abstractrenderer_p.h
@@ -147,6 +147,7 @@ public:
virtual QVector<Qt3DCore::QAspectJobPtr> renderBinJobs() = 0;
virtual Qt3DCore::QAspectJobPtr pickBoundingVolumeJob() = 0;
+ virtual Qt3DCore::QAspectJobPtr rayCastingJob() = 0;
virtual Qt3DCore::QAspectJobPtr syncTextureLoadingJob() = 0;
virtual Qt3DCore::QAspectJobPtr expandBoundingVolumeJob() = 0;
diff --git a/src/render/backend/renderer.cpp b/src/render/backend/renderer.cpp
index 535b10b85..70daa9904 100644
--- a/src/render/backend/renderer.cpp
+++ b/src/render/backend/renderer.cpp
@@ -167,6 +167,7 @@ Renderer::Renderer(QRenderAspect::RenderType type)
, m_glContext(nullptr)
, m_shareContext(nullptr)
, m_pickBoundingVolumeJob(PickBoundingVolumeJobPtr::create())
+ , m_rayCastingJob(RayCastingJobPtr::create())
, m_time(0)
, m_settings(nullptr)
, m_updateShaderDataTransformJob(Render::UpdateShaderDataTransformJobPtr::create())
@@ -217,6 +218,7 @@ Renderer::Renderer(QRenderAspect::RenderType type)
// All world stuff depends on the RenderEntity's localBoundingVolume
m_updateLevelOfDetailJob->addDependency(m_updateMeshTriangleListJob);
m_pickBoundingVolumeJob->addDependency(m_updateMeshTriangleListJob);
+ m_rayCastingJob->addDependency(m_updateMeshTriangleListJob);
m_filterCompatibleTechniqueJob->setRenderer(this);
@@ -276,6 +278,7 @@ void Renderer::setNodeManagers(NodeManagers *managers)
m_cleanupJob->setManagers(m_nodesManager);
m_calculateBoundingVolumeJob->setManagers(m_nodesManager);
m_pickBoundingVolumeJob->setManagers(m_nodesManager);
+ m_rayCastingJob->setManagers(m_nodesManager);
m_updateWorldBoundingVolumeJob->setManager(m_nodesManager->renderNodesManager());
m_sendRenderCaptureJob->setManagers(m_nodesManager);
m_sendBufferCaptureJob->setManagers(m_nodesManager);
@@ -509,6 +512,7 @@ void Renderer::setSceneRoot(QBackendNodeFactory *factory, Entity *sgRoot)
m_calculateBoundingVolumeJob->setRoot(m_renderSceneRoot);
m_cleanupJob->setRoot(m_renderSceneRoot);
m_pickBoundingVolumeJob->setRoot(m_renderSceneRoot);
+ m_rayCastingJob->setRoot(m_renderSceneRoot);
m_updateLevelOfDetailJob->setRoot(m_renderSceneRoot);
m_updateSkinningPaletteJob->setRoot(m_renderSceneRoot);
m_updateTreeEnabledJob->setRoot(m_renderSceneRoot);
@@ -1622,6 +1626,18 @@ QAspectJobPtr Renderer::pickBoundingVolumeJob()
return m_pickBoundingVolumeJob;
}
+QAspectJobPtr Renderer::rayCastingJob()
+{
+ // Set values on rayCastingJob
+ RenderSettings *renderSetting = settings();
+ if (renderSetting != nullptr) {
+ m_rayCastingJob->setRenderSettings(renderSetting);
+ m_rayCastingJob->setFrameGraphRoot(frameGraphRoot());
+ }
+
+ return m_rayCastingJob;
+}
+
QAspectJobPtr Renderer::syncTextureLoadingJob()
{
return m_syncTextureLoadingJob;
diff --git a/src/render/backend/renderer_p.h b/src/render/backend/renderer_p.h
index c7ca49401..f996ebfe1 100644
--- a/src/render/backend/renderer_p.h
+++ b/src/render/backend/renderer_p.h
@@ -60,6 +60,7 @@
#include <Qt3DCore/qaspectjob.h>
#include <Qt3DRender/private/qt3drender_global_p.h>
#include <Qt3DRender/private/pickboundingvolumejob_p.h>
+#include <Qt3DRender/private/raycastingjob_p.h>
#include <Qt3DRender/private/rendersettings_p.h>
#include <Qt3DRender/private/renderviewinitializerjob_p.h>
#include <Qt3DRender/private/expandboundingvolumejob_p.h>
@@ -190,6 +191,7 @@ public:
QVector<Qt3DCore::QAspectJobPtr> renderBinJobs() override;
Qt3DCore::QAspectJobPtr pickBoundingVolumeJob() override;
+ Qt3DCore::QAspectJobPtr rayCastingJob() override;
Qt3DCore::QAspectJobPtr syncTextureLoadingJob() override;
Qt3DCore::QAspectJobPtr expandBoundingVolumeJob() override;
@@ -312,6 +314,7 @@ private:
QOpenGLContext *m_glContext;
QOpenGLContext *m_shareContext;
PickBoundingVolumeJobPtr m_pickBoundingVolumeJob;
+ RayCastingJobPtr m_rayCastingJob;
qint64 m_time;
diff --git a/src/render/frontend/qrenderaspect.cpp b/src/render/frontend/qrenderaspect.cpp
index 5a83745ab..bbbb08a09 100644
--- a/src/render/frontend/qrenderaspect.cpp
+++ b/src/render/frontend/qrenderaspect.cpp
@@ -493,12 +493,10 @@ QVector<Qt3DCore::QAspectJobPtr> QRenderAspect::jobsToExecute(qint64 time)
const QVector<QAspectJobPtr> geometryJobs = d->createGeometryRendererJobs();
jobs.append(geometryJobs);
-
// Add all jobs to queue
- const Qt3DCore::QAspectJobPtr pickBoundingVolumeJob = d->m_renderer->pickBoundingVolumeJob();
// Note: the getter is also responsible for returning a job ready to run
- jobs.append(pickBoundingVolumeJob);
-
+ jobs.append(d->m_renderer->pickBoundingVolumeJob());
+ jobs.append(d->m_renderer->rayCastingJob());
// Don't spawn any rendering jobs, if the renderer decides to skip this frame
// Note: this only affects rendering jobs (jobs that load buffers,
diff --git a/src/render/jobs/job_common_p.h b/src/render/jobs/job_common_p.h
index 582bd454c..0e570ca19 100644
--- a/src/render/jobs/job_common_p.h
+++ b/src/render/jobs/job_common_p.h
@@ -71,6 +71,7 @@ namespace JobTypes {
LoadScene,
LoadTextureData,
PickBoundingVolume,
+ RayCasting,
RenderView,
UpdateTransform,
UpdateTreeEnabled,
diff --git a/src/render/jobs/jobs.pri b/src/render/jobs/jobs.pri
index 745af6d85..42219da49 100644
--- a/src/render/jobs/jobs.pri
+++ b/src/render/jobs/jobs.pri
@@ -33,7 +33,8 @@ HEADERS += \
$$PWD/sendbuffercapturejob_p.h \
$$PWD/loadskeletonjob_p.h \
$$PWD/updateskinningpalettejob_p.h \
- $$PWD/filterproximitydistancejob_p.h
+ $$PWD/filterproximitydistancejob_p.h \
+ $$PWD/raycastingjob_p.h
SOURCES += \
$$PWD/updateworldtransformjob.cpp \
@@ -65,5 +66,6 @@ SOURCES += \
$$PWD/sendbuffercapturejob.cpp \
$$PWD/loadskeletonjob.cpp \
$$PWD/updateskinningpalettejob.cpp \
- $$PWD/filterproximitydistancejob.cpp
+ $$PWD/filterproximitydistancejob.cpp \
+ $$PWD/raycastingjob.cpp
diff --git a/src/render/jobs/raycastingjob.cpp b/src/render/jobs/raycastingjob.cpp
new file mode 100644
index 000000000..ad69f81be
--- /dev/null
+++ b/src/render/jobs/raycastingjob.cpp
@@ -0,0 +1,265 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 "raycastingjob_p.h"
+#include <Qt3DRender/qgeometryrenderer.h>
+#include <Qt3DRender/private/entity_p.h>
+#include <Qt3DRender/private/geometryrenderer_p.h>
+#include <Qt3DRender/private/job_common_p.h>
+#include <Qt3DRender/private/managers_p.h>
+#include <Qt3DRender/private/nodemanagers_p.h>
+#include <Qt3DRender/private/pickboundingvolumeutils_p.h>
+#include <Qt3DRender/private/qray3d_p.h>
+#include <Qt3DRender/private/renderer_p.h>
+#include <Qt3DRender/private/rendersettings_p.h>
+#include <Qt3DRender/private/trianglesvisitor_p.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt3DRender;
+using namespace Qt3DRender::RayCasting;
+using namespace Render;
+
+namespace {
+
+class Q_AUTOTEST_EXPORT EntityCasterGatherer
+{
+public:
+ using EntityCasterList = QVector<QPair<Entity *, RayCaster*>>;
+
+ explicit EntityCasterGatherer(Entity *root) : m_root(root), m_needsRefresh(true) { }
+
+ EntityCasterList result() const {
+ if (m_needsRefresh) {
+ m_result.clear();
+ m_result = gatherEntities(m_root, std::move(m_result));
+ m_needsRefresh = false;
+ }
+ return m_result;
+ }
+
+private:
+ EntityCasterList gatherEntities(Entity *entity, EntityCasterList entities) const
+ {
+ if (entity != nullptr && entity->isEnabled()) {
+ QVector<RayCaster *> components = entity->renderComponents<RayCaster>();
+ for (const auto c: qAsConst(components)) {
+ if (c->isEnabled())
+ entities.push_back(qMakePair(entity, c));
+ }
+
+ // Traverse children
+ const auto children = entity->children();
+ for (Entity *child : children)
+ entities = gatherEntities(child, std::move(entities));
+ }
+ return entities;
+ }
+
+ Entity *m_root;
+ mutable EntityCasterList m_result;
+ mutable bool m_needsRefresh;
+};
+
+} // anonymous
+
+
+RayCastingJob::RayCastingJob()
+ : m_manager(nullptr)
+ , m_node(nullptr)
+ , m_frameGraphRoot(nullptr)
+ , m_renderSettings(nullptr)
+ , m_castersDirty(true)
+{
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::RayCasting, 0);
+}
+
+void RayCastingJob::setRoot(Entity *root)
+{
+ m_node = root;
+}
+
+void RayCastingJob::setFrameGraphRoot(FrameGraphNode *frameGraphRoot)
+{
+ m_frameGraphRoot = frameGraphRoot;
+}
+
+void RayCastingJob::setRenderSettings(RenderSettings *settings)
+{
+ m_renderSettings = settings;
+}
+
+void RayCastingJob::setManagers(NodeManagers *manager)
+{
+ m_manager = manager;
+}
+
+void RayCastingJob::markCastersDirty()
+{
+ m_castersDirty = true;
+}
+
+void RayCastingJob::run()
+{
+ Q_ASSERT(m_frameGraphRoot && m_renderSettings && m_node && m_manager);
+ runHelper();
+}
+
+bool RayCastingJob::runHelper()
+{
+ // Quickly look which caster settings we've got
+ // NOTE: should not really cached, we're tracking the state of
+ // RayCaster components but not of the parent entities
+ if (m_castersDirty) {
+ m_castersDirty = false;
+ m_oneEnabledAtLeast = false;
+
+ const auto activeHandles = m_manager->rayCasterManager()->activeHandles();
+ for (const auto &handle : activeHandles) {
+ const auto caster = m_manager->rayCasterManager()->data(handle);
+ m_oneEnabledAtLeast |= caster->isEnabled();
+ if (m_oneEnabledAtLeast)
+ break;
+ }
+ }
+
+ // bail out early if no caster is enabled
+ if (!m_oneEnabledAtLeast)
+ return false;
+
+ const bool trianglePickingRequested = (m_renderSettings->pickMethod() & QPickingSettings::TrianglePicking);
+ const bool edgePickingRequested = (m_renderSettings->pickMethod() & QPickingSettings::LinePicking);
+ const bool pointPickingRequested = (m_renderSettings->pickMethod() & QPickingSettings::PointPicking);
+ const bool primitivePickingRequested = pointPickingRequested | edgePickingRequested | trianglePickingRequested;
+ const bool frontFaceRequested =
+ m_renderSettings->faceOrientationPickingMode() != QPickingSettings::BackFace;
+ const bool backFaceRequested =
+ m_renderSettings->faceOrientationPickingMode() != QPickingSettings::FrontFace;
+ const float pickWorldSpaceTolerance = m_renderSettings->pickWorldSpaceTolerance();
+
+ EntityCasterGatherer gatherer(m_node);
+ const EntityCasterGatherer::EntityCasterList &entities = gatherer.result();
+ for (const EntityCasterGatherer::EntityCasterList::value_type &pair: entities) {
+ QRay3D ray(pair.second->origin(), pair.second->direction(), pair.second->length());
+ ray.transform(*pair.first->worldTransform());
+
+ PickingUtils::HitList sphereHits;
+ PickingUtils::HierarchicalEntityPicker entityPicker(ray, false);
+ 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;
+ gathererFunctor.m_objectPickersRequired = false;
+ sphereHits << gathererFunctor.computeHits(entityPicker.entities(), true);
+ }
+ if (edgePickingRequested) {
+ PickingUtils::LineCollisionGathererFunctor gathererFunctor;
+ gathererFunctor.m_manager = m_manager;
+ gathererFunctor.m_ray = ray;
+ gathererFunctor.m_pickWorldSpaceTolerance = pickWorldSpaceTolerance;
+ gathererFunctor.m_objectPickersRequired = false;
+ sphereHits << gathererFunctor.computeHits(entityPicker.entities(), true);
+ PickingUtils::AbstractCollisionGathererFunctor::sortHits(sphereHits);
+ }
+ if (pointPickingRequested) {
+ PickingUtils::PointCollisionGathererFunctor gathererFunctor;
+ gathererFunctor.m_manager = m_manager;
+ gathererFunctor.m_ray = ray;
+ gathererFunctor.m_pickWorldSpaceTolerance = pickWorldSpaceTolerance;
+ gathererFunctor.m_objectPickersRequired = false;
+ sphereHits << gathererFunctor.computeHits(entityPicker.entities(), true);
+ PickingUtils::AbstractCollisionGathererFunctor::sortHits(sphereHits);
+ }
+ if (!primitivePickingRequested) {
+ sphereHits << entityPicker.hits();
+ PickingUtils::AbstractCollisionGathererFunctor::sortHits(sphereHits);
+ }
+ }
+
+ dispatchHits(pair.second, sphereHits);
+ }
+
+ return true;
+}
+
+void RayCastingJob::dispatchHits(RayCaster *rayCaster, const PickingUtils::HitList &sphereHits)
+{
+ QRayCaster::Hits hits;
+ for (const PickingUtils::HitList::value_type &sphereHit: sphereHits) {
+ Entity *entity = m_manager->renderNodesManager()->lookupResource(sphereHit.m_entityId);
+ QVector3D localIntersection = sphereHit.m_intersection;
+ if (entity && entity->worldTransform())
+ localIntersection = entity->worldTransform()->inverted() * localIntersection;
+
+ QRayCasterHit::HitType hitType = QRayCasterHit::EntityHit;
+ switch (sphereHit.m_type) {
+ case RayCasting::QCollisionQueryResult::Hit::Entity:
+ break;
+ case RayCasting::QCollisionQueryResult::Hit::Triangle:
+ hitType = QRayCasterHit::TriangleHit;
+ break;
+ case RayCasting::QCollisionQueryResult::Hit::Edge:
+ hitType = QRayCasterHit::LineHit;
+ break;
+ case RayCasting::QCollisionQueryResult::Hit::Point:
+ hitType = QRayCasterHit::PointHit;
+ break;
+ default: Q_UNREACHABLE();
+ }
+
+ hits << QRayCasterHit{
+ hitType,
+ sphereHit.m_entityId,
+ sphereHit.m_distance,
+ localIntersection,
+ sphereHit.m_intersection,
+ sphereHit.m_primitiveIndex,
+ sphereHit.m_vertexIndex[0],
+ sphereHit.m_vertexIndex[1],
+ sphereHit.m_vertexIndex[2]
+ };
+ }
+
+ rayCaster->dispatchHits(hits);
+}
+
+QT_END_NAMESPACE
diff --git a/src/render/jobs/raycastingjob_p.h b/src/render/jobs/raycastingjob_p.h
new file mode 100644
index 000000000..7ae7721d0
--- /dev/null
+++ b/src/render/jobs/raycastingjob_p.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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_RAYCASTINGJOB_H
+#define QT3DRENDER_RENDER_RAYCASTINGJOB_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/qpickevent.h>
+#include <Qt3DRender/private/handle_types_p.h>
+#include <Qt3DRender/private/qcollisionqueryresult_p.h>
+#include <QMouseEvent>
+#include <QKeyEvent>
+#include <QSharedPointer>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DCore {
+class QNodeId;
+}
+
+namespace Qt3DRender {
+namespace Render {
+
+class Entity;
+class NodeManagers;
+class RenderSettings;
+class RayCaster;
+
+namespace PickingUtils {
+typedef QVector<RayCasting::QCollisionQueryResult::Hit> HitList;
+}
+
+class Q_AUTOTEST_EXPORT RayCastingJob : public Qt3DCore::QAspectJob
+{
+public:
+ RayCastingJob();
+
+ void setRoot(Entity *root);
+ void setFrameGraphRoot(FrameGraphNode *frameGraphRoot);
+ void setRenderSettings(RenderSettings *settings);
+ void setManagers(NodeManagers *manager);
+
+ void markCastersDirty();
+ bool runHelper();
+
+protected:
+ void run() final;
+ void dispatchHits(RayCaster *rayCaster, const PickingUtils::HitList &sphereHits);
+
+private:
+ NodeManagers *m_manager;
+ Entity *m_node;
+ FrameGraphNode *m_frameGraphRoot;
+ RenderSettings *m_renderSettings;
+
+ bool m_castersDirty;
+ bool m_oneEnabledAtLeast;
+};
+
+typedef QSharedPointer<RayCastingJob> RayCastingJobPtr;
+
+} // namespace Render
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_RENDER_RAYCASTINGJOB_H
diff --git a/src/render/picking/raycaster.cpp b/src/render/picking/raycaster.cpp
index 9a73d02d6..38e69d7a5 100644
--- a/src/render/picking/raycaster.cpp
+++ b/src/render/picking/raycaster.cpp
@@ -42,6 +42,7 @@
#include "renderer_p.h"
#include <Qt3DRender/qraycaster.h>
#include <Qt3DRender/private/qraycaster_p.h>
+#include <Qt3DRender/private/raycastingjob_p.h>
#include <Qt3DRender/qattribute.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
@@ -58,6 +59,7 @@ RayCaster::RayCaster()
RayCaster::~RayCaster()
{
+ notifyJob();
}
QRayCaster::RunMode RayCaster::runMode() const
@@ -87,6 +89,7 @@ void RayCaster::cleanup()
m_direction = QVector3D(0.f, 0.f, 1.f);
m_origin = {};
m_length = 0.f;
+ notifyJob();
}
void RayCaster::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
@@ -114,6 +117,7 @@ void RayCaster::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
m_runMode = propertyChange->value().value<QRayCaster::RunMode>();
}
+ notifyJob();
markDirty(AbstractRenderer::AllDirty);
}
@@ -138,6 +142,12 @@ void RayCaster::dispatchHits(const QRayCaster::Hits &hits)
}
}
+void RayCaster::notifyJob()
+{
+ if (m_renderer && m_renderer->rayCastingJob())
+ qSharedPointerCast<RayCastingJob>(m_renderer->rayCastingJob())->markCastersDirty();
+}
+
} // Render
} // Qt3DRender
diff --git a/src/render/picking/raycaster_p.h b/src/render/picking/raycaster_p.h
index 7a9b0fa7c..1cefb5bea 100644
--- a/src/render/picking/raycaster_p.h
+++ b/src/render/picking/raycaster_p.h
@@ -80,6 +80,7 @@ public:
private:
void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
+ void notifyJob();
QRayCaster::RunMode m_runMode = QRayCaster::SingleShot;
QVector3D m_origin;