summaryrefslogtreecommitdiffstats
path: root/src/render/jobs/pickboundingvolumeutils.cpp
diff options
context:
space:
mode:
authorMike Krus <mike.krus@kdab.com>2017-08-08 19:47:20 +0100
committerMike Krus <mike.krus@kdab.com>2017-08-09 08:54:59 +0000
commit49e03adc771b5ee471588e5a7e95ba10c86eee90 (patch)
tree7ef731143529d4cbf2ab804efd437ff56a22aa09 /src/render/jobs/pickboundingvolumeutils.cpp
parent60ea37949ce746919b32c774320478b856aaee4d (diff)
Add point picking
Most API was present but not the picking backend. Also missing was QPickPoint event. Task-number: QTBUG-58071 Change-Id: I768afaf64507ea4835772d4201be031f9f0a43b4 Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
Diffstat (limited to 'src/render/jobs/pickboundingvolumeutils.cpp')
-rw-r--r--src/render/jobs/pickboundingvolumeutils.cpp80
1 files changed, 80 insertions, 0 deletions
diff --git a/src/render/jobs/pickboundingvolumeutils.cpp b/src/render/jobs/pickboundingvolumeutils.cpp
index 80825e6e1..22b92a3f2 100644
--- a/src/render/jobs/pickboundingvolumeutils.cpp
+++ b/src/render/jobs/pickboundingvolumeutils.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "pickboundingvolumeutils_p.h"
+#include <Qt3DRender/private/geometryrenderer_p.h>
#include <Qt3DRender/private/framegraphnode_p.h>
#include <Qt3DRender/private/cameralens_p.h>
#include <Qt3DRender/private/cameraselectornode_p.h>
@@ -49,6 +50,7 @@
#include <Qt3DRender/private/entity_p.h>
#include <Qt3DRender/private/trianglesvisitor_p.h>
#include <Qt3DRender/private/segmentsvisitor_p.h>
+#include <Qt3DRender/private/pointsvisitor_p.h>
QT_BEGIN_NAMESPACE
@@ -336,6 +338,57 @@ bool LineCollisionVisitor::rayToLineSegment(const QVector3D& lineStart,const QVe
return false;
}
+class PointCollisionVisitor : public PointsVisitor
+{
+public:
+ HitList hits;
+
+ PointCollisionVisitor(NodeManagers* manager, const Entity *root, const RayCasting::QRay3D& ray,
+ float pickWorldSpaceTolerance)
+ : PointsVisitor(manager), m_root(root), m_ray(ray)
+ , m_pointIndex(0), m_pickWorldSpaceTolerance(pickWorldSpaceTolerance)
+ {
+ }
+
+private:
+ const Entity *m_root;
+ RayCasting::QRay3D m_ray;
+ uint m_pointIndex;
+ float m_pickWorldSpaceTolerance;
+
+ void visit(uint ndx, const QVector3D &p) Q_DECL_OVERRIDE;
+
+ double pointToRayDistance(const QVector3D &a, QVector3D &p)
+ {
+ const QVector3D v = a - m_ray.origin();
+ const double t = QVector3D::dotProduct(v, m_ray.direction());
+ p = m_ray.origin() + t * m_ray.direction();
+ return (p - a).length();
+ }
+};
+
+
+void PointCollisionVisitor::visit(uint ndx, const QVector3D &p)
+{
+ const QMatrix4x4 &mat = *m_root->worldTransform();
+ const QVector3D tP = mat * p;
+ QVector3D intersection;
+
+ float d = pointToRayDistance(tP, intersection);
+ if (d < m_pickWorldSpaceTolerance) {
+ QCollisionQueryResult::Hit queryResult;
+ queryResult.m_type = QCollisionQueryResult::Hit::Point;
+ queryResult.m_entityId = m_root->peerId();
+ queryResult.m_primitiveIndex = m_pointIndex;
+ queryResult.m_vertexIndex[0] = ndx;
+ queryResult.m_intersection = intersection;
+ queryResult.m_distance = d;
+ hits.push_back(queryResult);
+ }
+
+ m_pointIndex++;
+}
+
HitList reduceToFirstHit(HitList &result, const HitList &intermediate)
{
if (!intermediate.empty()) {
@@ -473,6 +526,33 @@ HitList LineCollisionGathererFunctor::pick(const Entity *entity) const
return result;
}
+HitList PointCollisionGathererFunctor::computeHits(const QVector<Entity *> &entities, bool allHitsRequested)
+{
+ const auto reducerOp = allHitsRequested ? PickingUtils::reduceToAllHits : PickingUtils::reduceToFirstHit;
+ return QtConcurrent::blockingMappedReduced<HitList>(entities, *this, reducerOp);
+}
+
+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;
+
+ if (rayHitsEntity(entity)) {
+ PointCollisionVisitor visitor(m_manager, entity, m_ray, m_pickWorldSpaceTolerance);
+ visitor.apply(gRenderer, entity->peerId());
+ result = visitor.hits;
+ sortHits(result);
+ }
+
+ return result;
+}
+
HierarchicalEntityPicker::HierarchicalEntityPicker(const QRay3D &ray)
: m_ray(ray)
{