diff options
author | Mike Krus <mike.krus@kdab.com> | 2017-02-17 23:11:55 +0000 |
---|---|---|
committer | Mike Krus <mike.krus@kdab.com> | 2017-05-26 09:58:32 +0000 |
commit | a441bd7d3d83284f68f1d8addedc93989a18cfeb (patch) | |
tree | e84f875ea9efa2e6cf5c20070e8a19daac1c1c70 /src/render/jobs/pickboundingvolumeutils.cpp | |
parent | 498a2b1c90616c559aa696757685ac624899783e (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.cpp | 141 |
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) { |