summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Krus <mike.krus@kdab.com>2020-03-11 15:58:38 +0000
committerMike Krus <mike.krus@kdab.com>2020-04-23 21:24:15 +0100
commit6eedeff84f8e518028342aa63dca479db3b0654e (patch)
tree93a15b3d1bcd42b8248aebb29a464f57d1961921
parent9a2ab2f1c0dc7ffe83f3e22aa97951de216b4ef7 (diff)
Introduce QPickingProxy
Lets user provide a separate mesh for picking. Change-Id: I30a61920e1673d8bc3473ca85046b236bad0a2af Reviewed-by: Paul Lemire <paul.lemire@kdab.com>
-rw-r--r--src/quick3d/imports/render/qt3dquick3drenderplugin.cpp2
-rw-r--r--src/render/backend/entity.cpp8
-rw-r--r--src/render/backend/entity_p.h2
-rw-r--r--src/render/backend/handle_types_p.h2
-rw-r--r--src/render/backend/managers_p.h9
-rw-r--r--src/render/backend/nodemanagers.cpp7
-rw-r--r--src/render/backend/nodemanagers_p.h7
-rw-r--r--src/render/backend/pointsvisitor.cpp13
-rw-r--r--src/render/backend/pointsvisitor_p.h2
-rw-r--r--src/render/backend/segmentsvisitor.cpp13
-rw-r--r--src/render/backend/segmentsvisitor_p.h2
-rw-r--r--src/render/backend/trianglesvisitor.cpp14
-rw-r--r--src/render/backend/trianglesvisitor_p.h2
-rw-r--r--src/render/backend/visitorutils_p.h8
-rw-r--r--src/render/frontend/qrenderaspect.cpp3
-rw-r--r--src/render/geometry/geometry.pri10
-rw-r--r--src/render/geometry/pickingproxy.cpp178
-rw-r--r--src/render/geometry/pickingproxy_p.h124
-rw-r--r--src/render/geometry/qpickingproxy.cpp156
-rw-r--r--src/render/geometry/qpickingproxy.h72
-rw-r--r--src/render/geometry/qpickingproxy_p.h81
-rw-r--r--src/render/jobs/pickboundingvolumeutils.cpp87
-rw-r--r--tests/manual/picking-qml/main.qml57
23 files changed, 818 insertions, 41 deletions
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 <Qt3DRender/qnodepthmask.h>
#include <Qt3DRender/qnodraw.h>
#include <Qt3DRender/qobjectpicker.h>
+#include <Qt3DRender/qpickingproxy.h>
#include <Qt3DRender/qraycaster.h>
#include <Qt3DRender/qparameter.h>
#include <Qt3DRender/qpickevent.h>
@@ -235,6 +236,7 @@ void Qt3DQuick3DRenderPlugin::registerTypes(const char *uri)
qmlRegisterUncreatableType<Qt3DRender::QPickEvent, 14>(uri, 2, 14, "PickEvent", QStringLiteral("Events cannot be created"));
qmlRegisterType<Qt3DRender::Render::Quick::Quick3DRayCaster>(uri, 2, 11, "RayCaster");
qmlRegisterType<Qt3DRender::Render::Quick::Quick3DScreenRayCaster>(uri, 2, 11, "ScreenRayCaster");
+ qmlRegisterType<Qt3DRender::QPickingProxy>(uri, 2, 16, "PickingProxy");
// Compute Job
qmlRegisterType<Qt3DRender::QComputeCommand>(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 <Qt3DRender/private/sphere_p.h>
#include <Qt3DRender/qshaderdata.h>
#include <Qt3DRender/qgeometryrenderer.h>
+#include <Qt3DRender/qpickingproxy.h>
#include <Qt3DRender/qobjectpicker.h>
#include <Qt3DRender/qcomputecommand.h>
#include <Qt3DRender/private/geometryrenderermanager_p.h>
@@ -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<Qt3DCore::QNodeId> m_lightComponents;
QVector<Qt3DCore::QNodeId> 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<Buffer> HBuffer;
typedef Qt3DCore::QHandle<Attribute> HAttribute;
typedef Qt3DCore::QHandle<Geometry> HGeometry;
typedef Qt3DCore::QHandle<GeometryRenderer> HGeometryRenderer;
+typedef Qt3DCore::QHandle<PickingProxy> HPickingProxy;
typedef Qt3DCore::QHandle<ObjectPicker> HObjectPicker;
typedef Qt3DCore::QHandle<RayCaster> HRayCaster;
typedef Qt3DCore::QHandle<BoundingVolumeDebug> 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 <Qt3DRender/private/skeleton_p.h>
#include <Qt3DRender/private/joint_p.h>
#include <Qt3DRender/private/shaderimage_p.h>
+#include <Qt3DRender/private/pickingproxy_p.h>
QT_BEGIN_NAMESPACE
@@ -486,6 +487,13 @@ private:
QVector<HJoint> 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())
{
}
@@ -294,6 +295,12 @@ ObjectPickerManager *NodeManagers::manager<ObjectPicker>() const noexcept
}
template<>
+PickingProxyManager *NodeManagers::manager<PickingProxy>() const noexcept
+{
+ return m_pickingProxyManager;
+}
+
+template<>
RayCasterManager *NodeManagers::manager<RayCaster>() const noexcept
{
return m_rayCasterManager;
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<Joint>() con
template<>
Q_3DRENDERSHARED_PRIVATE_EXPORT ShaderImageManager *NodeManagers::manager<ShaderImage>() const noexcept;
+template<>
+Q_3DRENDERSHARED_PRIVATE_EXPORT PickingProxyManager *NodeManagers::manager<PickingProxy>() 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<VertexExecutor<PointsVisitor>,
- IndexExecutor<PointsVisitor>, PointsVisitor>(m_manager, renderer, this);
+ Visitor::visitPrimitives<GeometryRenderer, VertexExecutor<PointsVisitor>,
+ IndexExecutor<PointsVisitor>, 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<PickingProxy, VertexExecutor<PointsVisitor>,
+ IndexExecutor<PointsVisitor>, 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<VertexExecutor<SegmentsVisitor>,
- IndexExecutor<SegmentsVisitor>, SegmentsVisitor>(m_manager, renderer, this);
+ Visitor::visitPrimitives<GeometryRenderer, VertexExecutor<SegmentsVisitor>,
+ IndexExecutor<SegmentsVisitor>, 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<Qt3DRender::QGeometryRenderer::PrimitiveType>(proxy->primitiveType()))) {
+ Visitor::visitPrimitives<PickingProxy, VertexExecutor<SegmentsVisitor>,
+ IndexExecutor<SegmentsVisitor>, 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 <Qt3DRender/private/managers_p.h>
#include <Qt3DRender/private/nodemanagers_p.h>
#include <Qt3DRender/private/buffermanager_p.h>
+#include <Qt3DRender/private/pickingproxy_p.h>
#include <Qt3DRender/private/geometryrenderer_p.h>
#include <Qt3DRender/private/geometryrenderermanager_p.h>
#include <Qt3DRender/private/geometry_p.h>
@@ -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<VertexExecutor<TrianglesVisitor>,
+ Visitor::visitPrimitives<GeometryRenderer, VertexExecutor<TrianglesVisitor>,
IndexExecutor<TrianglesVisitor>, 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<Qt3DRender::QGeometryRenderer::PrimitiveType>(proxy->primitiveType()))) {
+ Visitor::visitPrimitives<PickingProxy, VertexExecutor<TrianglesVisitor>,
+ IndexExecutor<TrianglesVisitor>, 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<Attribute, AttributeManager>(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<typename VertexExecutor, typename IndexExecutor, typename Visitor>
-void visitPrimitives(NodeManagers *manager, const GeometryRenderer *renderer, Visitor* visitor)
+template<typename GeometryProvider, typename VertexExecutor, typename IndexExecutor, typename Visitor>
+void visitPrimitives(NodeManagers *manager, const GeometryProvider *renderer, Visitor* visitor)
{
Geometry *geom = manager->lookupResource<Geometry, GeometryManager>(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<Qt3DRender::QGeometryRenderer::PrimitiveType>(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<Qt3DRender::QGeometryRenderer::PrimitiveType>(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 <Qt3DRender/qshaderimage.h>
#include <Qt3DRender/qsubtreeenabler.h>
#include <Qt3DRender/qdebugoverlay.h>
+#include <Qt3DRender/qpickingproxy.h>
#include <Qt3DCore/qarmature.h>
#include <Qt3DCore/qjoint.h>
#include <Qt3DCore/qskeletonloader.h>
@@ -361,6 +362,7 @@ void QRenderAspectPrivate::registerBackendTypes()
q->registerBackendType<QComputeCommand>(QSharedPointer<Render::NodeFunctor<Render::ComputeCommand, Render::ComputeCommandManager> >::create(m_renderer));
q->registerBackendType<QGeometry>(QSharedPointer<Render::NodeFunctor<Render::Geometry, Render::GeometryManager> >::create(m_renderer));
q->registerBackendType<QGeometryRenderer>(QSharedPointer<Render::GeometryRendererFunctor>::create(m_renderer, m_nodeManagers->geometryRendererManager()));
+ q->registerBackendType<QPickingProxy>(QSharedPointer<Render::PickingProxyFunctor>::create(m_renderer, m_nodeManagers->pickingProxyManager()));
q->registerBackendType<Qt3DCore::QArmature>(QSharedPointer<Render::NodeFunctor<Render::Armature, Render::ArmatureManager>>::create(m_renderer));
q->registerBackendType<Qt3DCore::QAbstractSkeleton>(QSharedPointer<Render::SkeletonFunctor>::create(m_renderer, m_nodeManagers->skeletonManager(), m_nodeManagers->jointManager()));
q->registerBackendType<Qt3DCore::QJoint>(QSharedPointer<Render::JointFunctor>::create(m_renderer, m_nodeManagers->jointManager(), m_nodeManagers->skeletonManager()));
@@ -441,6 +443,7 @@ void QRenderAspectPrivate::unregisterBackendTypes()
unregisterBackendType<QComputeCommand>();
unregisterBackendType<QGeometry>();
unregisterBackendType<QGeometryRenderer>();
+ unregisterBackendType<QPickingProxy>();
unregisterBackendType<Qt3DCore::QArmature>();
unregisterBackendType<Qt3DCore::QAbstractSkeleton>();
unregisterBackendType<Qt3DCore::QJoint>();
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 <Qt3DRender/private/managers_p.h>
+#include <Qt3DRender/private/qpickingproxy_p.h>
+#include <Qt3DCore/private/qgeometryview_p.h>
+#include <Qt3DCore/private/qnode_p.h>
+
+#include <memory>
+
+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<const QPickingProxy *>(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<QGeometryView::PrimitiveType>(node->primitiveType());
+ m_primitiveType = static_cast<QGeometryView::PrimitiveType>(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 <Qt3DRender/private/backendnode_p.h>
+#include <Qt3DRender/qpickingproxy.h>
+
+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 <private/qcomponent_p.h>
+
+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 <Qt3DCore/qboundingvolume.h>
+#include <Qt3DCore/qgeometry.h>
+#include <Qt3DCore/qgeometryview.h>
+#include <Qt3DRender/qt3drender_global.h>
+
+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 <Qt3DCore/private/qgeometryfactory_p.h>
+#include <Qt3DCore/private/qboundingvolume_p.h>
+#include <Qt3DRender/qpickingproxy.h>
+#include <Qt3DRender/private/qt3drender_global_p.h>
+#include <memory>
+
+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<GeometryRenderer>();
- if (!gRenderer)
- return result;
+ PickingProxy *proxy = entity->renderComponent<PickingProxy>();
+ 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<GeometryRenderer>();
+ 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<GeometryRenderer>();
- if (!gRenderer)
- return result;
+ PickingProxy *proxy = entity->renderComponent<PickingProxy>();
+ 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<GeometryRenderer>();
+ 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<GeometryRenderer>();
- if (!gRenderer)
- return result;
-
- if (gRenderer->primitiveType() != Qt3DRender::QGeometryRenderer::Points)
- return result;
+ PickingProxy *proxy = entity->renderComponent<PickingProxy>();
+ 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<GeometryRenderer>();
+ 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]
+ }
}