summaryrefslogtreecommitdiffstats
path: root/src/render/jobs/pickboundingvolumeutils.cpp
diff options
context:
space:
mode:
authorMike Krus <mike.krus@kdab.com>2017-02-17 23:11:55 +0000
committerMike Krus <mike.krus@kdab.com>2017-05-26 09:58:32 +0000
commita441bd7d3d83284f68f1d8addedc93989a18cfeb (patch)
treee84f875ea9efa2e6cf5c20070e8a19daac1c1c70 /src/render/jobs/pickboundingvolumeutils.cpp
parent498a2b1c90616c559aa696757685ac624899783e (diff)
Refactor job to prepare for line and point picking
This moves much of the job utils into private code, simplifies the various class types, clarifies names to avoid clashes and simplifies some APIs. Introduces changes in headers requiring extra includes in various files. Task-number: QTBUG-58071 Change-Id: I20a8251abcef140d9d71b372a66282e242a21ad2 Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
Diffstat (limited to 'src/render/jobs/pickboundingvolumeutils.cpp')
-rw-r--r--src/render/jobs/pickboundingvolumeutils.cpp141
1 files changed, 91 insertions, 50 deletions
diff --git a/src/render/jobs/pickboundingvolumeutils.cpp b/src/render/jobs/pickboundingvolumeutils.cpp
index f08398a5a..a8367dc20 100644
--- a/src/render/jobs/pickboundingvolumeutils.cpp
+++ b/src/render/jobs/pickboundingvolumeutils.cpp
@@ -110,7 +110,8 @@ QVector<ViewportCameraAreaTriplet> ViewportCameraAreaGatherer::gather(FrameGraph
return vcaTriplets;
}
-bool PickingUtils::ViewportCameraAreaGatherer::isUnique(const QVector<ViewportCameraAreaTriplet> &vcaTriplets, const ViewportCameraAreaTriplet &vca) const
+bool ViewportCameraAreaGatherer::isUnique(const QVector<ViewportCameraAreaTriplet> &vcaTriplets,
+ const ViewportCameraAreaTriplet &vca) const
{
for (const ViewportCameraAreaTriplet &triplet : vcaTriplets) {
if (vca.cameraId == triplet.cameraId && vca.viewport == triplet.viewport && vca.area == triplet.area)
@@ -147,7 +148,35 @@ QVector<Entity *> EntityGatherer::entities() const
return m_entities;
}
-void CollisionVisitor::visit(uint andx, const QVector3D &a, uint bndx, const QVector3D &b, uint cndx, const QVector3D &c)
+
+class TriangleCollisionVisitor : public TrianglesVisitor
+{
+public:
+ HitList hits;
+
+ TriangleCollisionVisitor(NodeManagers* manager, const Entity *root, const RayCasting::QRay3D& ray,
+ bool frontFaceRequested, bool backFaceRequested)
+ : TrianglesVisitor(manager), m_root(root), m_ray(ray), m_triangleIndex(0)
+ , m_frontFaceRequested(frontFaceRequested), m_backFaceRequested(backFaceRequested)
+ {
+ }
+
+private:
+ const Entity *m_root;
+ RayCasting::QRay3D m_ray;
+ uint m_triangleIndex;
+ bool m_frontFaceRequested;
+ bool m_backFaceRequested;
+
+ void visit(uint andx, const QVector3D &a,
+ uint bndx, const QVector3D &b,
+ uint cndx, const QVector3D &c) Q_DECL_OVERRIDE;
+ bool intersectsSegmentTriangle(uint andx, const QVector3D &a,
+ uint bndx, const QVector3D &b,
+ uint cndx, const QVector3D &c);
+};
+
+void TriangleCollisionVisitor::visit(uint andx, const QVector3D &a, uint bndx, const QVector3D &b, uint cndx, const QVector3D &c)
{
const QMatrix4x4 &mat = *m_root->worldTransform();
const QVector3D tA = mat * a;
@@ -163,7 +192,7 @@ void CollisionVisitor::visit(uint andx, const QVector3D &a, uint bndx, const QVe
m_triangleIndex++;
}
-bool CollisionVisitor::intersectsSegmentTriangle(uint andx, const QVector3D &a, uint bndx, const QVector3D &b, uint cndx, const QVector3D &c)
+bool TriangleCollisionVisitor::intersectsSegmentTriangle(uint andx, const QVector3D &a, uint bndx, const QVector3D &b, uint cndx, const QVector3D &c)
{
float t = 0.0f;
QVector3D uvw;
@@ -183,6 +212,32 @@ bool CollisionVisitor::intersectsSegmentTriangle(uint andx, const QVector3D &a,
return intersected;
}
+HitList reduceToFirstHit(HitList &result, const HitList &intermediate)
+{
+ if (!intermediate.empty()) {
+ if (result.empty())
+ result.push_back(intermediate.front());
+ float closest = result.front().m_distance;
+ for (const auto &v : intermediate) {
+ if (v.m_distance < closest) {
+ result.push_front(v);
+ closest = v.m_distance;
+ }
+ }
+
+ while (result.size() > 1)
+ result.pop_back();
+ }
+ return result;
+}
+
+HitList reduceToAllHits(HitList &results, const HitList &intermediate)
+{
+ if (!intermediate.empty())
+ results << intermediate;
+ return results;
+}
+
AbstractCollisionGathererFunctor::AbstractCollisionGathererFunctor()
: m_manager(nullptr)
{ }
@@ -190,7 +245,7 @@ AbstractCollisionGathererFunctor::AbstractCollisionGathererFunctor()
AbstractCollisionGathererFunctor::~AbstractCollisionGathererFunctor()
{ }
-AbstractCollisionGathererFunctor::result_type AbstractCollisionGathererFunctor::operator ()(const Entity *entity) const
+HitList AbstractCollisionGathererFunctor::operator ()(const Entity *entity) const
{
HObjectPicker objectPickerHandle = entity->componentHandle<ObjectPicker, 16>();
@@ -205,44 +260,62 @@ AbstractCollisionGathererFunctor::result_type AbstractCollisionGathererFunctor::
ObjectPicker *objectPicker = m_manager->objectPickerManager()->data(objectPickerHandle);
if (objectPicker == nullptr || !objectPicker->isEnabled())
- return result_type(); // don't bother picking entities that don't
- // have an object picker, or if it's disabled
+ return {}; // don't bother picking entities that don't
+ // have an object picker, or if it's disabled
- RayCasting::QRayCastingService rayCasting;
+ return pick(entity);
+}
- return pick(&rayCasting, entity);
+bool AbstractCollisionGathererFunctor::rayHitsEntity(const Entity *entity) const
+{
+ QRayCastingService rayCasting;
+ const QCollisionQueryResult::Hit queryResult = rayCasting.query(m_ray, entity->worldBoundingVolume());
+ return queryResult.m_distance >= 0.f;
}
-void AbstractCollisionGathererFunctor::sortHits(CollisionVisitor::HitList &results)
+void AbstractCollisionGathererFunctor::sortHits(HitList &results)
{
- auto compareHitsDistance = [](const CollisionVisitor::HitList::value_type &a,
- const CollisionVisitor::HitList::value_type &b) {
+ auto compareHitsDistance = [](const HitList::value_type &a,
+ const HitList::value_type &b) {
return a.m_distance < b.m_distance;
};
std::sort(results.begin(), results.end(), compareHitsDistance);
}
-AbstractCollisionGathererFunctor::result_type EntityCollisionGathererFunctor::pick(RayCasting::QAbstractCollisionQueryService *rayCasting, const Entity *entity) const
+HitList EntityCollisionGathererFunctor::computeHits(const QVector<Entity *> &entities, bool allHitsRequested)
{
- result_type result;
+ const auto reducerOp = allHitsRequested ? PickingUtils::reduceToAllHits : PickingUtils::reduceToFirstHit;
+ return QtConcurrent::blockingMappedReduced<HitList>(entities, *this, reducerOp);
+}
- const QCollisionQueryResult::Hit queryResult = rayCasting->query(m_ray, entity->worldBoundingVolume());
+HitList EntityCollisionGathererFunctor::pick(const Entity *entity) const
+{
+ HitList result;
+
+ QRayCastingService rayCasting;
+ const QCollisionQueryResult::Hit queryResult = rayCasting.query(m_ray, entity->worldBoundingVolume());
if (queryResult.m_distance >= 0.f)
result.push_back(queryResult);
return result;
}
-AbstractCollisionGathererFunctor::result_type TriangleCollisionGathererFunctor::pick(RayCasting::QAbstractCollisionQueryService *rayCasting, const Entity *entity) const
+HitList TriangleCollisionGathererFunctor::computeHits(const QVector<Entity *> &entities, bool allHitsRequested)
+{
+ const auto reducerOp = allHitsRequested ? PickingUtils::reduceToAllHits : PickingUtils::reduceToFirstHit;
+ return QtConcurrent::blockingMappedReduced<HitList>(entities, *this, reducerOp);
+}
+
+HitList TriangleCollisionGathererFunctor::pick(const Entity *entity) const
{
- result_type result;
+ HitList result;
GeometryRenderer *gRenderer = entity->renderComponent<GeometryRenderer>();
if (!gRenderer)
return result;
- if (rayHitsEntity(rayCasting, entity)) {
- CollisionVisitor visitor(m_manager, entity, m_ray, m_frontFaceRequested, m_backFaceRequested);
+ if (rayHitsEntity(entity)) {
+ TriangleCollisionVisitor visitor(m_manager, entity, m_ray, m_frontFaceRequested, m_backFaceRequested);
visitor.apply(gRenderer, entity->peerId());
result = visitor.hits;
@@ -252,38 +325,6 @@ AbstractCollisionGathererFunctor::result_type TriangleCollisionGathererFunctor::
return result;
}
-bool TriangleCollisionGathererFunctor::rayHitsEntity(RayCasting::QAbstractCollisionQueryService *rayCasting, const Entity *entity) const
-{
- const QCollisionQueryResult::Hit queryResult = rayCasting->query(m_ray, entity->worldBoundingVolume());
- return queryResult.m_distance >= 0.f;
-}
-
-CollisionVisitor::HitList reduceToFirstHit(CollisionVisitor::HitList &result, const CollisionVisitor::HitList &intermediate)
-{
- if (!intermediate.empty()) {
- if (result.empty())
- result.push_back(intermediate.front());
- float closest = result.front().m_distance;
- for (const auto &v : intermediate) {
- if (v.m_distance < closest) {
- result.push_front(v);
- closest = v.m_distance;
- }
- }
-
- while (result.size() > 1)
- result.pop_back();
- }
- return result;
-}
-
-CollisionVisitor::HitList reduceToAllHits(CollisionVisitor::HitList &results, const CollisionVisitor::HitList &intermediate)
-{
- if (!intermediate.empty())
- results << intermediate;
- return results;
-}
-
HierarchicalEntityPicker::HierarchicalEntityPicker(const QRay3D &ray)
: m_ray(ray)
{