From 6eedeff84f8e518028342aa63dca479db3b0654e Mon Sep 17 00:00:00 2001 From: Mike Krus Date: Wed, 11 Mar 2020 15:58:38 +0000 Subject: Introduce QPickingProxy Lets user provide a separate mesh for picking. Change-Id: I30a61920e1673d8bc3473ca85046b236bad0a2af Reviewed-by: Paul Lemire --- .../imports/render/qt3dquick3drenderplugin.cpp | 2 + src/render/backend/entity.cpp | 8 + src/render/backend/entity_p.h | 2 + src/render/backend/handle_types_p.h | 2 + src/render/backend/managers_p.h | 9 ++ src/render/backend/nodemanagers.cpp | 7 + src/render/backend/nodemanagers_p.h | 7 + src/render/backend/pointsvisitor.cpp | 13 +- src/render/backend/pointsvisitor_p.h | 2 + src/render/backend/segmentsvisitor.cpp | 13 +- src/render/backend/segmentsvisitor_p.h | 2 + src/render/backend/trianglesvisitor.cpp | 14 +- src/render/backend/trianglesvisitor_p.h | 2 + src/render/backend/visitorutils_p.h | 8 +- src/render/frontend/qrenderaspect.cpp | 3 + src/render/geometry/geometry.pri | 10 +- src/render/geometry/pickingproxy.cpp | 178 +++++++++++++++++++++ src/render/geometry/pickingproxy_p.h | 124 ++++++++++++++ src/render/geometry/qpickingproxy.cpp | 156 ++++++++++++++++++ src/render/geometry/qpickingproxy.h | 72 +++++++++ src/render/geometry/qpickingproxy_p.h | 81 ++++++++++ src/render/jobs/pickboundingvolumeutils.cpp | 87 ++++++---- tests/manual/picking-qml/main.qml | 57 ++++++- 23 files changed, 818 insertions(+), 41 deletions(-) create mode 100644 src/render/geometry/pickingproxy.cpp create mode 100644 src/render/geometry/pickingproxy_p.h create mode 100644 src/render/geometry/qpickingproxy.cpp create mode 100644 src/render/geometry/qpickingproxy.h create mode 100644 src/render/geometry/qpickingproxy_p.h diff --git a/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp b/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp index 48a3aa7ed..afa40d958 100644 --- a/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp +++ b/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp @@ -76,6 +76,7 @@ #include #include #include +#include #include #include #include @@ -235,6 +236,7 @@ void Qt3DQuick3DRenderPlugin::registerTypes(const char *uri) qmlRegisterUncreatableType(uri, 2, 14, "PickEvent", QStringLiteral("Events cannot be created")); qmlRegisterType(uri, 2, 11, "RayCaster"); qmlRegisterType(uri, 2, 11, "ScreenRayCaster"); + qmlRegisterType(uri, 2, 16, "PickingProxy"); // Compute Job qmlRegisterType(uri, 2, 0, "ComputeCommand"); diff --git a/src/render/backend/entity.cpp b/src/render/backend/entity.cpp index aeb318c5a..a483fe89f 100644 --- a/src/render/backend/entity.cpp +++ b/src/render/backend/entity.cpp @@ -53,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -138,6 +139,7 @@ void Entity::cleanup() m_cameraComponent = Qt3DCore::QNodeId(); m_materialComponent = Qt3DCore::QNodeId(); m_geometryRendererComponent = Qt3DCore::QNodeId(); + m_pickingProxyComponent = Qt3DCore::QNodeId(); m_objectPickerComponent = QNodeId(); m_boundingVolumeDebugComponent = QNodeId(); m_computeComponent = QNodeId(); @@ -219,6 +221,7 @@ void Entity::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) m_materialComponent = QNodeId(); m_cameraComponent = QNodeId(); m_geometryRendererComponent = QNodeId(); + m_pickingProxyComponent = QNodeId(); m_objectPickerComponent = QNodeId(); m_boundingVolumeDebugComponent = QNodeId(); m_computeComponent = QNodeId(); @@ -338,6 +341,8 @@ void Entity::addComponent(Qt3DCore::QNodeIdTypePair idAndType) } else if (type->inherits(&QGeometryRenderer::staticMetaObject)) { m_geometryRendererComponent = id; m_boundingDirty = true; + } else if (type->inherits(&QPickingProxy::staticMetaObject)) { + m_pickingProxyComponent = id; } else if (type->inherits(&QObjectPicker::staticMetaObject)) { m_objectPickerComponent = id; // } else if (type->inherits(&QBoundingVolumeDebug::staticMetaObject)) { @@ -369,6 +374,8 @@ void Entity::removeComponent(Qt3DCore::QNodeId nodeId) } else if (m_geometryRendererComponent == nodeId) { m_geometryRendererComponent = QNodeId(); m_boundingDirty = true; + } else if (m_pickingProxyComponent == nodeId) { + m_pickingProxyComponent = QNodeId(); } else if (m_objectPickerComponent == nodeId) { m_objectPickerComponent = QNodeId(); // } else if (m_boundingVolumeDebugComponent == nodeId) { @@ -410,6 +417,7 @@ ENTITY_COMPONENT_TEMPLATE_IMPL(Material, HMaterial, MaterialManager, m_materialC ENTITY_COMPONENT_TEMPLATE_IMPL(CameraLens, HCamera, CameraManager, m_cameraComponent) ENTITY_COMPONENT_TEMPLATE_IMPL(Transform, HTransform, TransformManager, m_transformComponent) ENTITY_COMPONENT_TEMPLATE_IMPL(GeometryRenderer, HGeometryRenderer, GeometryRendererManager, m_geometryRendererComponent) +ENTITY_COMPONENT_TEMPLATE_IMPL(PickingProxy, HPickingProxy, PickingProxyManager, m_pickingProxyComponent) ENTITY_COMPONENT_TEMPLATE_IMPL(ObjectPicker, HObjectPicker, ObjectPickerManager, m_objectPickerComponent) ENTITY_COMPONENT_TEMPLATE_IMPL(ComputeCommand, HComputeCommand, ComputeCommandManager, m_computeComponent) ENTITY_COMPONENT_TEMPLATE_IMPL(Armature, HArmature, ArmatureManager, m_armatureComponent) diff --git a/src/render/backend/entity_p.h b/src/render/backend/entity_p.h index 474d8747b..5a9340c1a 100644 --- a/src/render/backend/entity_p.h +++ b/src/render/backend/entity_p.h @@ -200,6 +200,7 @@ private: QVector m_lightComponents; QVector m_environmentLightComponents; Qt3DCore::QNodeId m_geometryRendererComponent; + Qt3DCore::QNodeId m_pickingProxyComponent; Qt3DCore::QNodeId m_objectPickerComponent; Qt3DCore::QNodeId m_boundingVolumeDebugComponent; Qt3DCore::QNodeId m_computeComponent; @@ -292,6 +293,7 @@ ENTITY_COMPONENT_TEMPLATE_SPECIALIZATION(CameraLens, HCamera) ENTITY_COMPONENT_TEMPLATE_SPECIALIZATION(Transform, HTransform) ENTITY_COMPONENT_TEMPLATE_SPECIALIZATION(GeometryRenderer, HGeometryRenderer) ENTITY_COMPONENT_TEMPLATE_SPECIALIZATION(ObjectPicker, HObjectPicker) +ENTITY_COMPONENT_TEMPLATE_SPECIALIZATION(PickingProxy, HPickingProxy) ENTITY_COMPONENT_TEMPLATE_SPECIALIZATION(ComputeCommand, HComputeCommand) ENTITY_COMPONENT_TEMPLATE_SPECIALIZATION(Armature, HArmature) ENTITY_COMPONENT_LIST_TEMPLATE_SPECIALIZATION(Layer, HLayer) diff --git a/src/render/backend/handle_types_p.h b/src/render/backend/handle_types_p.h index 73b4df341..de08f7013 100644 --- a/src/render/backend/handle_types_p.h +++ b/src/render/backend/handle_types_p.h @@ -86,6 +86,7 @@ class Buffer; class Attribute; class Geometry; class GeometryRenderer; +class PickingProxy; class ObjectPicker; class RayCaster; class BoundingVolumeDebug; @@ -123,6 +124,7 @@ typedef Qt3DCore::QHandle HBuffer; typedef Qt3DCore::QHandle HAttribute; typedef Qt3DCore::QHandle HGeometry; typedef Qt3DCore::QHandle HGeometryRenderer; +typedef Qt3DCore::QHandle HPickingProxy; typedef Qt3DCore::QHandle HObjectPicker; typedef Qt3DCore::QHandle HRayCaster; typedef Qt3DCore::QHandle HBoundingVolumeDebug; diff --git a/src/render/backend/managers_p.h b/src/render/backend/managers_p.h index a3d42d24a..3ce8f6353 100644 --- a/src/render/backend/managers_p.h +++ b/src/render/backend/managers_p.h @@ -84,6 +84,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -486,6 +487,13 @@ private: QVector m_dirtyJoints; }; +class Q_3DRENDERSHARED_PRIVATE_EXPORT PickingProxyManager : public Qt3DCore::QResourceManager< + PickingProxy, + Qt3DCore::QNodeId, + Qt3DCore::NonLockingPolicy> +{ +}; + } // namespace Render } // namespace Qt3DRender @@ -512,6 +520,7 @@ Q_DECLARE_RESOURCE_INFO(Qt3DRender::Render::Skeleton, Q_REQUIRES_CLEANUP) Q_DECLARE_RESOURCE_INFO(Qt3DRender::Render::Joint, Q_REQUIRES_CLEANUP) Q_DECLARE_RESOURCE_INFO(Qt3DRender::Render::ShaderBuilder, Q_REQUIRES_CLEANUP) Q_DECLARE_RESOURCE_INFO(Qt3DRender::Render::ShaderImage, Q_REQUIRES_CLEANUP) +Q_DECLARE_RESOURCE_INFO(Qt3DRender::Render::PickingProxy, Q_REQUIRES_CLEANUP) QT_END_NAMESPACE diff --git a/src/render/backend/nodemanagers.cpp b/src/render/backend/nodemanagers.cpp index df660a19e..45313d00c 100644 --- a/src/render/backend/nodemanagers.cpp +++ b/src/render/backend/nodemanagers.cpp @@ -91,6 +91,7 @@ NodeManagers::NodeManagers() , m_skeletonManager(new SkeletonManager()) , m_jointManager(new JointManager()) , m_shaderImageManager(new ShaderImageManager()) + , m_pickingProxyManager(new PickingProxyManager()) { } @@ -293,6 +294,12 @@ ObjectPickerManager *NodeManagers::manager() const noexcept return m_objectPickerManager; } +template<> +PickingProxyManager *NodeManagers::manager() const noexcept +{ + return m_pickingProxyManager; +} + template<> RayCasterManager *NodeManagers::manager() const noexcept { diff --git a/src/render/backend/nodemanagers_p.h b/src/render/backend/nodemanagers_p.h index e6f7469de..2abdc5c54 100644 --- a/src/render/backend/nodemanagers_p.h +++ b/src/render/backend/nodemanagers_p.h @@ -102,6 +102,7 @@ class ArmatureManager; class SkeletonManager; class JointManager; class ShaderImageManager; +class PickingProxyManager; class FrameGraphNode; class Entity; @@ -139,6 +140,7 @@ class Armature; class Skeleton; class Joint; class ShaderImage; +class PickingProxy; class Q_3DRENDERSHARED_PRIVATE_EXPORT NodeManagers @@ -217,6 +219,7 @@ public: inline SkeletonManager *skeletonManager() const noexcept { return m_skeletonManager; } inline JointManager *jointManager() const noexcept { return m_jointManager; } inline ShaderImageManager *shaderImageManager() const noexcept { return m_shaderImageManager; } + inline PickingProxyManager *pickingProxyManager() const noexcept { return m_pickingProxyManager; } private: CameraManager *m_cameraManager; @@ -255,6 +258,7 @@ private: SkeletonManager *m_skeletonManager; JointManager *m_jointManager; ShaderImageManager *m_shaderImageManager; + PickingProxyManager *m_pickingProxyManager; }; // Specializations @@ -367,6 +371,9 @@ Q_3DRENDERSHARED_PRIVATE_EXPORT JointManager *NodeManagers::manager() con template<> Q_3DRENDERSHARED_PRIVATE_EXPORT ShaderImageManager *NodeManagers::manager() const noexcept; +template<> +Q_3DRENDERSHARED_PRIVATE_EXPORT PickingProxyManager *NodeManagers::manager() const noexcept; + } // Render } // Qt3DRender diff --git a/src/render/backend/pointsvisitor.cpp b/src/render/backend/pointsvisitor.cpp index 750182b19..41cdb382a 100644 --- a/src/render/backend/pointsvisitor.cpp +++ b/src/render/backend/pointsvisitor.cpp @@ -176,8 +176,17 @@ void PointsVisitor::apply(const GeometryRenderer *renderer, const Qt3DCore::QNod { m_nodeId = id; if (renderer && renderer->instanceCount() == 1) { - Visitor::visitPrimitives, - IndexExecutor, PointsVisitor>(m_manager, renderer, this); + Visitor::visitPrimitives, + IndexExecutor, PointsVisitor>(m_manager, renderer, this); + } +} + +void PointsVisitor::apply(const PickingProxy *proxy, const Qt3DCore::QNodeId id) +{ + m_nodeId = id; + if (proxy && proxy->instanceCount() == 1) { + Visitor::visitPrimitives, + IndexExecutor, PointsVisitor>(m_manager, proxy, this); } } diff --git a/src/render/backend/pointsvisitor_p.h b/src/render/backend/pointsvisitor_p.h index 1614f185b..b198fe176 100644 --- a/src/render/backend/pointsvisitor_p.h +++ b/src/render/backend/pointsvisitor_p.h @@ -66,6 +66,7 @@ namespace Render { class GeometryRenderer; class NodeManagers; +class PickingProxy; class Q_AUTOTEST_EXPORT PointsVisitor { @@ -75,6 +76,7 @@ public: void apply(const Qt3DCore::QEntity *entity); void apply(const GeometryRenderer *renderer, const Qt3DCore::QNodeId id); + void apply(const PickingProxy *proxy, const Qt3DCore::QNodeId id); virtual void visit(uint ndx, const Vector3D &c) = 0; diff --git a/src/render/backend/segmentsvisitor.cpp b/src/render/backend/segmentsvisitor.cpp index d9f2d79ec..f19801ddf 100644 --- a/src/render/backend/segmentsvisitor.cpp +++ b/src/render/backend/segmentsvisitor.cpp @@ -367,8 +367,17 @@ void SegmentsVisitor::apply(const GeometryRenderer *renderer, const Qt3DCore::QN { m_nodeId = id; if (renderer && renderer->instanceCount() == 1 && isSegmentBased(renderer->primitiveType())) { - Visitor::visitPrimitives, - IndexExecutor, SegmentsVisitor>(m_manager, renderer, this); + Visitor::visitPrimitives, + IndexExecutor, SegmentsVisitor>(m_manager, renderer, this); + } +} + +void SegmentsVisitor::apply(const PickingProxy *proxy, const Qt3DCore::QNodeId id) +{ + m_nodeId = id; + if (proxy && proxy->instanceCount() == 1 && isSegmentBased(static_cast(proxy->primitiveType()))) { + Visitor::visitPrimitives, + IndexExecutor, SegmentsVisitor>(m_manager, proxy, this); } } diff --git a/src/render/backend/segmentsvisitor_p.h b/src/render/backend/segmentsvisitor_p.h index cd5df1268..e05e9fe00 100644 --- a/src/render/backend/segmentsvisitor_p.h +++ b/src/render/backend/segmentsvisitor_p.h @@ -66,6 +66,7 @@ namespace Render { class GeometryRenderer; class NodeManagers; +class PickingProxy; class Q_AUTOTEST_EXPORT SegmentsVisitor { @@ -75,6 +76,7 @@ public: void apply(const Qt3DCore::QEntity *entity); void apply(const GeometryRenderer *renderer, const Qt3DCore::QNodeId id); + void apply(const PickingProxy *proxy, const Qt3DCore::QNodeId id); virtual void visit(uint andx, const Vector3D &a, uint bndx, const Vector3D &b) = 0; diff --git a/src/render/backend/trianglesvisitor.cpp b/src/render/backend/trianglesvisitor.cpp index 4cdf8a2bf..336e57c7e 100644 --- a/src/render/backend/trianglesvisitor.cpp +++ b/src/render/backend/trianglesvisitor.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -473,11 +474,20 @@ void TrianglesVisitor::apply(const GeometryRenderer *renderer, const Qt3DCore::Q { m_nodeId = id; if (renderer && renderer->instanceCount() == 1 && isTriangleBased(renderer->primitiveType())) { - Visitor::visitPrimitives, + Visitor::visitPrimitives, IndexExecutor, TrianglesVisitor>(m_manager, renderer, this); } } +void TrianglesVisitor::apply(const PickingProxy *proxy, const QNodeId id) +{ + m_nodeId = id; + if (proxy && proxy->instanceCount() == 1 && isTriangleBased(static_cast(proxy->primitiveType()))) { + Visitor::visitPrimitives, + IndexExecutor, TrianglesVisitor>(m_manager, proxy, this); + } +} + bool CoordinateReader::setGeometry(const GeometryRenderer *renderer, const QString &attributeName) { if (renderer == nullptr || renderer->instanceCount() != 1 @@ -493,7 +503,7 @@ bool CoordinateReader::setGeometry(const GeometryRenderer *renderer, const QStri Attribute *attribute = nullptr; const auto attrIds = geom->attributes(); - for (const Qt3DCore::QNodeId attrId : attrIds) { + for (const Qt3DCore::QNodeId &attrId : attrIds) { attribute = m_manager->lookupResource(attrId); if (attribute){ if (attribute->name() == attributeName diff --git a/src/render/backend/trianglesvisitor_p.h b/src/render/backend/trianglesvisitor_p.h index e8ac9bf27..fd8517a02 100644 --- a/src/render/backend/trianglesvisitor_p.h +++ b/src/render/backend/trianglesvisitor_p.h @@ -69,6 +69,7 @@ namespace Qt3DRender { namespace Render { class GeometryRenderer; +class PickingProxy; class NodeManagers; class Attribute; class Buffer; @@ -81,6 +82,7 @@ public: void apply(const Qt3DCore::QEntity *entity); void apply(const GeometryRenderer *renderer, const Qt3DCore::QNodeId id); + void apply(const PickingProxy *proxy, const Qt3DCore::QNodeId id); virtual void visit(uint andx, const Vector3D &a, uint bndx, const Vector3D &b, diff --git a/src/render/backend/visitorutils_p.h b/src/render/backend/visitorutils_p.h index 3ea848c6b..476416ab1 100644 --- a/src/render/backend/visitorutils_p.h +++ b/src/render/backend/visitorutils_p.h @@ -102,8 +102,8 @@ void processBuffer(const BufferInfo &info, Func &f) } } -template -void visitPrimitives(NodeManagers *manager, const GeometryRenderer *renderer, Visitor* visitor) +template +void visitPrimitives(NodeManagers *manager, const GeometryProvider *renderer, Visitor* visitor) { Geometry *geom = manager->lookupResource(renderer->geometryId()); Attribute *positionAttribute = nullptr; @@ -154,7 +154,7 @@ void visitPrimitives(NodeManagers *manager, const GeometryRenderer *renderer, Vi IndexExecutor executor; executor.m_vertexBufferInfo = vertexBufferInfo; - executor.m_primitiveType = renderer->primitiveType(); + executor.m_primitiveType = static_cast(renderer->primitiveType()); executor.m_visitor = visitor; return processBuffer(indexBufferInfo, executor); @@ -163,7 +163,7 @@ void visitPrimitives(NodeManagers *manager, const GeometryRenderer *renderer, Vi // Check into which type the buffer needs to be casted VertexExecutor executor; - executor.m_primitiveType = renderer->primitiveType(); + executor.m_primitiveType = static_cast(renderer->primitiveType()); executor.m_visitor = visitor; return processBuffer(vertexBufferInfo, executor); diff --git a/src/render/frontend/qrenderaspect.cpp b/src/render/frontend/qrenderaspect.cpp index dff7f3640..9412d3526 100644 --- a/src/render/frontend/qrenderaspect.cpp +++ b/src/render/frontend/qrenderaspect.cpp @@ -92,6 +92,7 @@ #include #include #include +#include #include #include #include @@ -361,6 +362,7 @@ void QRenderAspectPrivate::registerBackendTypes() q->registerBackendType(QSharedPointer >::create(m_renderer)); q->registerBackendType(QSharedPointer >::create(m_renderer)); q->registerBackendType(QSharedPointer::create(m_renderer, m_nodeManagers->geometryRendererManager())); + q->registerBackendType(QSharedPointer::create(m_renderer, m_nodeManagers->pickingProxyManager())); q->registerBackendType(QSharedPointer>::create(m_renderer)); q->registerBackendType(QSharedPointer::create(m_renderer, m_nodeManagers->skeletonManager(), m_nodeManagers->jointManager())); q->registerBackendType(QSharedPointer::create(m_renderer, m_nodeManagers->jointManager(), m_nodeManagers->skeletonManager())); @@ -441,6 +443,7 @@ void QRenderAspectPrivate::unregisterBackendTypes() unregisterBackendType(); unregisterBackendType(); unregisterBackendType(); + unregisterBackendType(); unregisterBackendType(); unregisterBackendType(); unregisterBackendType(); diff --git a/src/render/geometry/geometry.pri b/src/render/geometry/geometry.pri index 475f406d5..15143c6d3 100644 --- a/src/render/geometry/geometry.pri +++ b/src/render/geometry/geometry.pri @@ -15,7 +15,10 @@ HEADERS += \ $$PWD/skeleton_p.h \ $$PWD/gltfskeletonloader_p.h \ $$PWD/skeletondata_p.h \ - $$PWD/joint_p.h + $$PWD/joint_p.h \ + $$PWD/qpickingproxy.h \ + $$PWD/qpickingproxy_p.h \ + $$PWD/pickingproxy_p.h SOURCES += \ $$PWD/attribute.cpp \ @@ -30,5 +33,6 @@ SOURCES += \ $$PWD/skeleton.cpp \ $$PWD/gltfskeletonloader.cpp \ $$PWD/skeletondata.cpp \ - $$PWD/joint.cpp - + $$PWD/joint.cpp \ + $$PWD/qpickingproxy.cpp \ + $$PWD/pickingproxy.cpp diff --git a/src/render/geometry/pickingproxy.cpp b/src/render/geometry/pickingproxy.cpp new file mode 100644 index 000000000..3e7b53cb6 --- /dev/null +++ b/src/render/geometry/pickingproxy.cpp @@ -0,0 +1,178 @@ +/**************************************************************************** +** +** Copyright (C) 2020 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 "pickingproxy_p.h" +#include +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +using namespace Qt3DCore; + +namespace Qt3DRender { +namespace Render { + +PickingProxy::PickingProxy() + : BackendNode(ReadWrite) + , m_instanceCount(0) + , m_vertexCount(0) + , m_indexOffset(0) + , m_firstInstance(0) + , m_firstVertex(0) + , m_indexBufferByteOffset(0) + , m_restartIndexValue(-1) + , m_verticesPerPatch(0) + , m_primitiveRestartEnabled(false) + , m_dirty(false) + , m_valid(false) + , m_primitiveType(Qt3DCore::QGeometryView::Triangles) + , m_manager(nullptr) +{ +} + +PickingProxy::~PickingProxy() +{ +} + +void PickingProxy::cleanup() +{ + BackendNode::setEnabled(false); + m_instanceCount = 0; + m_vertexCount = 0; + m_indexOffset = 0; + m_firstInstance = 0; + m_firstVertex = 0; + m_indexBufferByteOffset = 0; + m_restartIndexValue = -1; + m_verticesPerPatch = 0; + m_primitiveRestartEnabled = false; + m_primitiveType = QGeometryView::Triangles; + m_geometryId = Qt3DCore::QNodeId(); + m_dirty = false; + m_valid = false; +} + +void PickingProxy::setManager(PickingProxyManager *manager) +{ + m_manager = manager; +} + +void PickingProxy::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) +{ + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + const QPickingProxy *node = qobject_cast(frontEnd); + if (!node) + return; + + auto propertyUpdater = [this](const auto *node) { + m_dirty |= m_instanceCount != node->instanceCount(); + m_instanceCount = node->instanceCount(); + m_dirty |= m_vertexCount != node->vertexCount(); + m_vertexCount = node->vertexCount(); + m_dirty |= m_indexOffset != node->indexOffset(); + m_indexOffset = node->indexOffset(); + m_dirty |= m_firstInstance != node->firstInstance(); + m_firstInstance = node->firstInstance(); + m_dirty |= m_firstVertex != node->firstVertex(); + m_firstVertex = node->firstVertex(); + m_dirty |= m_indexBufferByteOffset != node->indexBufferByteOffset(); + m_indexBufferByteOffset = node->indexBufferByteOffset(); + m_dirty |= m_restartIndexValue != node->restartIndexValue(); + m_restartIndexValue = node->restartIndexValue(); + m_dirty |= m_verticesPerPatch != node->verticesPerPatch(); + m_verticesPerPatch = node->verticesPerPatch(); + m_dirty |= m_primitiveRestartEnabled != node->primitiveRestartEnabled(); + m_primitiveRestartEnabled = node->primitiveRestartEnabled(); + m_dirty |= m_primitiveType != static_cast(node->primitiveType()); + m_primitiveType = static_cast(node->primitiveType()); + m_dirty |= (node->geometry() && m_geometryId != node->geometry()->id()) || (!node->geometry() && !m_geometryId.isNull()); + m_geometryId = node->geometry() ? node->geometry()->id() : Qt3DCore::QNodeId(); + }; + + m_dirty = false; + + if (!node->view()) { + m_dirty |= m_valid; + m_valid = false; + } else { + m_dirty |= !m_valid; + m_valid = true; + propertyUpdater(node->view()); + } + + markDirty(AbstractRenderer::GeometryDirty); +} + +void PickingProxy::unsetDirty() +{ + m_dirty = false; +} + +PickingProxyFunctor::PickingProxyFunctor(AbstractRenderer *renderer, PickingProxyManager *manager) + : m_manager(manager) + , m_renderer(renderer) +{ +} + +Qt3DCore::QBackendNode *PickingProxyFunctor::create(Qt3DCore::QNodeId id) const +{ + PickingProxy *node = m_manager->getOrCreateResource(id); + node->setManager(m_manager); + node->setRenderer(m_renderer); + return node; +} + +Qt3DCore::QBackendNode *PickingProxyFunctor::get(Qt3DCore::QNodeId id) const +{ + return m_manager->lookupResource(id); +} + +void PickingProxyFunctor::destroy(Qt3DCore::QNodeId id) const +{ + m_manager->releaseResource(id); +} + +} // namespace Render +} // namespace Qt3DRender + +QT_END_NAMESPACE diff --git a/src/render/geometry/pickingproxy_p.h b/src/render/geometry/pickingproxy_p.h new file mode 100644 index 000000000..6612d27e3 --- /dev/null +++ b/src/render/geometry/pickingproxy_p.h @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Copyright (C) 2020 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_PICKINGPROXY_H +#define QT3DRENDER_RENDER_PICKINGPROXY_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 +#include + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { +namespace Render { + +class PickingProxyManager; + +class Q_3DRENDERSHARED_PRIVATE_EXPORT PickingProxy : public BackendNode +{ +public: + PickingProxy(); + ~PickingProxy(); + + void cleanup(); + void setManager(PickingProxyManager *manager); + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; + + inline Qt3DCore::QNodeId geometryId() const { return m_geometryId; } + inline int instanceCount() const { return m_instanceCount; } + inline int vertexCount() const { return m_vertexCount; } + inline int indexOffset() const { return m_indexOffset; } + inline int firstInstance() const { return m_firstInstance; } + inline int firstVertex() const { return m_firstVertex; } + inline int indexBufferByteOffset() const { return m_indexBufferByteOffset; } + inline int restartIndexValue() const { return m_restartIndexValue; } + inline int verticesPerPatch() const { return m_verticesPerPatch; } + inline bool primitiveRestartEnabled() const { return m_primitiveRestartEnabled; } + inline Qt3DCore::QGeometryView::PrimitiveType primitiveType() const { return m_primitiveType; } + inline bool isValid() const { return m_valid; } + inline bool isDirty() const { return m_dirty; } + void unsetDirty(); + +private: + Qt3DCore::QNodeId m_geometryId; + int m_instanceCount; + int m_vertexCount; + int m_indexOffset; + int m_firstInstance; + int m_firstVertex; + int m_indexBufferByteOffset; + int m_restartIndexValue; + int m_verticesPerPatch; + bool m_primitiveRestartEnabled; + bool m_dirty; + bool m_valid; + Qt3DCore::QGeometryView::PrimitiveType m_primitiveType; + PickingProxyManager *m_manager; +}; + +class PickingProxyFunctor : public Qt3DCore::QBackendNodeMapper +{ +public: + explicit PickingProxyFunctor(AbstractRenderer *renderer, PickingProxyManager *manager); + Qt3DCore::QBackendNode *create(Qt3DCore::QNodeId id) const override; + Qt3DCore::QBackendNode *get(Qt3DCore::QNodeId id) const override; + void destroy(Qt3DCore::QNodeId id) const override; +private: + PickingProxyManager *m_manager; + AbstractRenderer *m_renderer; +}; + +} // namespace Render + +} // namespace Qt3DRender + +QT_END_NAMESPACE + +#endif // QT3DRENDER_RENDER_PICKINGPROXY_H diff --git a/src/render/geometry/qpickingproxy.cpp b/src/render/geometry/qpickingproxy.cpp new file mode 100644 index 000000000..d9c2d264e --- /dev/null +++ b/src/render/geometry/qpickingproxy.cpp @@ -0,0 +1,156 @@ +/**************************************************************************** +** +** Copyright (C) 2020 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 "qpickingproxy.h" +#include "qpickingproxy_p.h" + +#include + +QT_BEGIN_NAMESPACE + +using namespace Qt3DCore; + +namespace Qt3DRender { + +QPickingProxyPrivate::QPickingProxyPrivate() + : Qt3DCore::QBoundingVolumePrivate() +{ + m_primaryProvider = false; +} + +QPickingProxyPrivate::~QPickingProxyPrivate() +{ +} + +void QPickingProxyPrivate::setView(QGeometryView *view) +{ + Q_Q(QPickingProxy); + if (m_view == view) + return; + + if (m_view) + m_view->disconnect(q); + + QBoundingVolumePrivate::setView(view); + + // Ensures proper bookkeeping + if (m_view) { + QObject::connect(view, &QGeometryView::instanceCountChanged, q, [this]() { update(); }); + QObject::connect(view, &QGeometryView::vertexCountChanged, q, [this]() { update(); }); + QObject::connect(view, &QGeometryView::indexOffsetChanged, q, [this]() { update(); }); + QObject::connect(view, &QGeometryView::firstInstanceChanged, q, [this]() { update(); }); + QObject::connect(view, &QGeometryView::firstVertexChanged, q, [this]() { update(); }); + QObject::connect(view, &QGeometryView::indexBufferByteOffsetChanged, q, [this]() { update(); }); + QObject::connect(view, &QGeometryView::restartIndexValueChanged, q, [this]() { update(); }); + QObject::connect(view, &QGeometryView::verticesPerPatchChanged, q, [this]() { update(); }); + QObject::connect(view, &QGeometryView::primitiveRestartEnabledChanged, q, [this]() { update(); }); + QObject::connect(view, &QGeometryView::geometryChanged, q, [this]() { update(); }); + QObject::connect(view, &QGeometryView::primitiveTypeChanged, q, [this]() { update(); }); + } +} + +/*! + \qmltype PickingProxy + \instantiates Qt3DRender::QPickingProxy + \inqmlmodule Qt3D.Render + \inherits Component3D + \since 2.16 + \brief Can be used to provide an alternate GeometryView used only for picking. + + Picking can be an expensive operation, especially if the mesh has a lot of vertices. + PickProxy can be used to provide an alternative geometry, usually with fewer primitives, + which will be used for picking, while the GeometryRenderer instance will be used + for rendering. + + \note Do not use a PickingProxy if the application requires picking coordinates + to match the rendered mesh. + + \note The picking algorithm uses a bounding volume hierarchy to optimize out + entities who's bounding volume does not intersect the picking ray. For that hierarchy, + the bounding volume of the renderered entity is used (or one explicitly set using a + BoundingVolume component) will be used rather than the one of the proxy. + */ + +/*! + \class Qt3DRender::QPickingProxy + \inmodule Qt3DRender + \since 6.0 + \brief Can be used to provide an alternate QGeometryView used only for picking. + + Picking can be an expensive operation, especially if the mesh has a lot of vertices. + QPickProxy can be used to provide an alternative geometry, usually with fewer primitives, + which will be used for picking, while the GeometryRenderer instance will be used + for rendering. + + \note Do not use a QPickingProxy if the application requires picking coordinates + to match the rendered mesh. + + \note The picking algorithm uses a bounding volume hierarchy to optimize out + entities who's bounding volume does not intersect the picking ray. For that hierarchy, + the bounding volume of the renderered entity is used (or one explicitly set using a + QBoundingVolume component) will be used rather than the one of the proxy. + */ + + +/*! + Constructs a new QPickingProxy with \a parent. + */ +QPickingProxy::QPickingProxy(QNode *parent) + : Qt3DCore::QBoundingVolume(*new QPickingProxyPrivate(), parent) +{ +} + +/*! + \internal + */ +QPickingProxy::~QPickingProxy() +{ +} + +/*! + \internal + */ +QPickingProxy::QPickingProxy(QPickingProxyPrivate &dd, QNode *parent) + : Qt3DCore::QBoundingVolume(dd, parent) +{ +} + +} // namespace Qt3DRender + +QT_END_NAMESPACE diff --git a/src/render/geometry/qpickingproxy.h b/src/render/geometry/qpickingproxy.h new file mode 100644 index 000000000..ce697e31e --- /dev/null +++ b/src/render/geometry/qpickingproxy.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2020 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_QPICKINGPROXY_H +#define QT3DRENDER_QPICKINGPROXY_H + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class QPickingProxyPrivate; + +class Q_3DRENDERSHARED_EXPORT QPickingProxy : public Qt3DCore::QBoundingVolume +{ + Q_OBJECT +public: + explicit QPickingProxy(Qt3DCore::QNode *parent = nullptr); + ~QPickingProxy(); + +protected: + explicit QPickingProxy(QPickingProxyPrivate &dd, Qt3DCore::QNode *parent = nullptr); + +private: + Q_DECLARE_PRIVATE(QPickingProxy) +}; + +} // namespace Qt3DRender + +QT_END_NAMESPACE + +#endif // QT3DRENDER_QPICKINGPROXY_H diff --git a/src/render/geometry/qpickingproxy_p.h b/src/render/geometry/qpickingproxy_p.h new file mode 100644 index 000000000..2e7ebc5a5 --- /dev/null +++ b/src/render/geometry/qpickingproxy_p.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2020 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_QPICKINGPROXY_P_H +#define QT3DRENDER_QPICKINGPROXY_P_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 +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class Q_3DRENDERSHARED_PRIVATE_EXPORT QPickingProxyPrivate : public Qt3DCore::QBoundingVolumePrivate +{ +public: + QPickingProxyPrivate(); + ~QPickingProxyPrivate(); + + Q_DECLARE_PUBLIC(QPickingProxy) + + void setView(Qt3DCore::QGeometryView *view) override; +}; + +} // namespace Qt3DRender + +QT_END_NAMESPACE + + +#endif // QT3DRENDER_QPICKINGPROXY_P_H + diff --git a/src/render/jobs/pickboundingvolumeutils.cpp b/src/render/jobs/pickboundingvolumeutils.cpp index 1d22e8645..187b73954 100644 --- a/src/render/jobs/pickboundingvolumeutils.cpp +++ b/src/render/jobs/pickboundingvolumeutils.cpp @@ -587,16 +587,27 @@ HitList TriangleCollisionGathererFunctor::pick(const Entity *entity) const { HitList result; - GeometryRenderer *gRenderer = entity->renderComponent(); - if (!gRenderer) - return result; + PickingProxy *proxy = entity->renderComponent(); + if (proxy && proxy->isEnabled() && proxy->isValid()) { + if (rayHitsEntity(entity)) { + TriangleCollisionVisitor visitor(m_manager, entity, m_ray, m_frontFaceRequested, m_backFaceRequested); + visitor.apply(proxy, entity->peerId()); + result = visitor.hits; + + sortHits(result); + } + } else { + GeometryRenderer *gRenderer = entity->renderComponent(); + if (!gRenderer || !gRenderer->isEnabled()) + return result; - if (rayHitsEntity(entity)) { - TriangleCollisionVisitor visitor(m_manager, entity, m_ray, m_frontFaceRequested, m_backFaceRequested); - visitor.apply(gRenderer, entity->peerId()); - result = visitor.hits; + if (rayHitsEntity(entity)) { + TriangleCollisionVisitor visitor(m_manager, entity, m_ray, m_frontFaceRequested, m_backFaceRequested); + visitor.apply(gRenderer, entity->peerId()); + result = visitor.hits; - sortHits(result); + sortHits(result); + } } return result; @@ -634,15 +645,26 @@ HitList LineCollisionGathererFunctor::pick(const Entity *entity) const { HitList result; - GeometryRenderer *gRenderer = entity->renderComponent(); - if (!gRenderer) - return result; + PickingProxy *proxy = entity->renderComponent(); + if (proxy && proxy->isEnabled() && proxy->isValid()) { + if (rayHitsEntity(entity)) { + LineCollisionVisitor visitor(m_manager, entity, m_ray, m_pickWorldSpaceTolerance); + visitor.apply(proxy, entity->peerId()); + result = visitor.hits; - if (rayHitsEntity(entity)) { - LineCollisionVisitor visitor(m_manager, entity, m_ray, m_pickWorldSpaceTolerance); - visitor.apply(gRenderer, entity->peerId()); - result = visitor.hits; - sortHits(result); + sortHits(result); + } + } else { + GeometryRenderer *gRenderer = entity->renderComponent(); + if (!gRenderer) + return result; + + if (rayHitsEntity(entity)) { + LineCollisionVisitor visitor(m_manager, entity, m_ray, m_pickWorldSpaceTolerance); + visitor.apply(gRenderer, entity->peerId()); + result = visitor.hits; + sortHits(result); + } } return result; @@ -680,18 +702,29 @@ HitList PointCollisionGathererFunctor::pick(const Entity *entity) const { HitList result; - GeometryRenderer *gRenderer = entity->renderComponent(); - if (!gRenderer) - return result; - - if (gRenderer->primitiveType() != Qt3DRender::QGeometryRenderer::Points) - return result; + PickingProxy *proxy = entity->renderComponent(); + if (proxy && proxy->isEnabled() && proxy->isValid() && proxy->primitiveType() != Qt3DCore::QGeometryView::Points) { + if (rayHitsEntity(entity)) { + PointCollisionVisitor visitor(m_manager, entity, m_ray, m_pickWorldSpaceTolerance); + visitor.apply(proxy, entity->peerId()); + result = visitor.hits; - if (rayHitsEntity(entity)) { - PointCollisionVisitor visitor(m_manager, entity, m_ray, m_pickWorldSpaceTolerance); - visitor.apply(gRenderer, entity->peerId()); - result = visitor.hits; - sortHits(result); + sortHits(result); + } + } else { + GeometryRenderer *gRenderer = entity->renderComponent(); + if (!gRenderer) + return result; + + if (gRenderer->primitiveType() != Qt3DRender::QGeometryRenderer::Points) + return result; + + if (rayHitsEntity(entity)) { + PointCollisionVisitor visitor(m_manager, entity, m_ray, m_pickWorldSpaceTolerance); + visitor.apply(gRenderer, entity->peerId()); + result = visitor.hits; + sortHits(result); + } } return result; diff --git a/tests/manual/picking-qml/main.qml b/tests/manual/picking-qml/main.qml index 40bb8721c..8de39a66f 100644 --- a/tests/manual/picking-qml/main.qml +++ b/tests/manual/picking-qml/main.qml @@ -49,7 +49,7 @@ ****************************************************************************/ import Qt3D.Core 2.0 -import Qt3D.Render 2.0 +import Qt3D.Render 2.16 import Qt3D.Input 2.0 import Qt3D.Extras 2.0 @@ -146,6 +146,8 @@ Entity { } } } + + pickingSettings.pickMethod: PickingSettings.TrianglePicking }, InputSettings {} ] @@ -237,4 +239,57 @@ Entity { components: [cubeMesh, transform, material, sceneRoot.contentLayer] } } + + Entity { + id: sphere1 + property bool toggled: false + property real scaleFactor: toggled ? 2.0 : 1.0 + QQ2.Behavior on scaleFactor { QQ2.NumberAnimation { duration: 200; easing.type: QQ2.Easing.InQuad } } + + readonly property ObjectPicker objectPicker: ObjectPicker { + hoverEnabled: true + onPressed: sphere1.toggled = !sphere1.toggled + onClicked: console.log("Clicked sphere1") + onEntered: sphere1.material.diffuse = "white" + onExited: sphere1.material.diffuse = "yellow" + } + + readonly property Transform transform: Transform { + scale: sphere1.scaleFactor + translation: Qt.vector3d(3, 6, 0) + } + readonly property PhongMaterial material: PhongMaterial { diffuse: "yellow" } + + readonly property GeometryRenderer sphereMesh: GeometryRenderer { view: SphereMesh { } } + + components: [sphereMesh, transform, material, sceneRoot.contentLayer, objectPicker] + } + + Entity { + id: sphere2 + property bool toggled: false + property real scaleFactor: toggled ? 2.0 : 1.0 + QQ2.Behavior on scaleFactor { QQ2.NumberAnimation { duration: 200; easing.type: QQ2.Easing.InQuad } } + + readonly property ObjectPicker objectPicker: ObjectPicker { + hoverEnabled: true + onPressed: sphere2.toggled = !sphere2.toggled + onClicked: console.log("Clicked sphere2") + onEntered: sphere2.material.diffuse = "white" + onExited: sphere2.material.diffuse = "green" + } + readonly property PickingProxy pickingProxy: PickingProxy { + view: CuboidMesh { xExtent: 2; yExtent: 2; zExtent: 2 } + } + + readonly property Transform transform: Transform { + scale: sphere2.scaleFactor + translation: Qt.vector3d(-3, 6, 0) + } + readonly property PhongMaterial material: PhongMaterial { diffuse: "green" } + + readonly property GeometryRenderer sphereMesh: GeometryRenderer { view: SphereMesh { } } + + components: [sphereMesh, transform, material, sceneRoot.contentLayer, objectPicker, pickingProxy] + } } -- cgit v1.2.3