/****************************************************************************
**
** Copyright (C) 2016 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 "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>
#include <Qt3DRender/private/viewportnode_p.h>
#include <Qt3DRender/private/rendersurfaceselector_p.h>
#include <Qt3DRender/private/triangleboundingvolume_p.h>
#include <Qt3DRender/private/nodemanagers_p.h>
#include <Qt3DRender/private/sphere_p.h>
#include <Qt3DRender/private/entity_p.h>
#include <Qt3DRender/private/trianglesvisitor_p.h>
#include <Qt3DRender/private/segmentsvisitor_p.h>
#include <Qt3DRender/private/pointsvisitor_p.h>
#include <Qt3DRender/private/layer_p.h>

#include <vector>
#include <algorithm>
#include <functional>

QT_BEGIN_NAMESPACE

namespace Qt3DRender {
using namespace Qt3DRender::RayCasting;

namespace Render {

namespace PickingUtils {

void ViewportCameraAreaGatherer::visit(FrameGraphNode *node)
{
    const auto children = node->children();
    for (Render::FrameGraphNode *n : children)
        visit(n);
    if (node->childrenIds().empty())
        m_leaves.push_back(node);
}

ViewportCameraAreaDetails ViewportCameraAreaGatherer::gatherUpViewportCameraAreas(Render::FrameGraphNode *node) const
{
    ViewportCameraAreaDetails vca;
    vca.viewport = QRectF(0.0f, 0.0f, 1.0f, 1.0f);

    while (node) {
        if (node->isEnabled()) {
            switch (node->nodeType()) {
            case FrameGraphNode::CameraSelector:
                vca.cameraId = static_cast<const CameraSelector *>(node)->cameraUuid();
                break;
            case FrameGraphNode::Viewport: {
                auto vnode = static_cast<const ViewportNode *>(node);
                // we want the leaf viewport so if we have a viewport node already don't override it with its parent
                if (!vca.viewportNodeId)
                    vca.viewportNodeId = vnode->peerId();
                vca.viewport = ViewportNode::computeViewport(vca.viewport, vnode);
                break;
            }
            case FrameGraphNode::Surface: {
                auto selector = static_cast<const RenderSurfaceSelector *>(node);
                vca.area = selector->renderTargetSize();
                vca.surface = selector->surface();
                break;
            }
            case FrameGraphNode::NoPicking: {
                // Return an empty/invalid ViewportCameraAreaDetails which will
                // prevent picking in the presence of a NoPicking node
                return {};
            }
            default:
                break;
            }
        }
        node = node->parent();
    }
    return vca;
}

QVector<ViewportCameraAreaDetails> ViewportCameraAreaGatherer::gather(FrameGraphNode *root)
{
    // Retrieve all leaves
    visit(root);
    QVector<ViewportCameraAreaDetails> vcaTriplets;
    vcaTriplets.reserve(m_leaves.count());

    // Find all viewport/camera pairs by traversing from leaf to root
    for (Render::FrameGraphNode *leaf : qAsConst(m_leaves)) {
        ViewportCameraAreaDetails vcaDetails = gatherUpViewportCameraAreas(leaf);
        if (!m_targetCamera.isNull() && vcaDetails.cameraId != m_targetCamera)
            continue;
        if (!vcaDetails.cameraId.isNull() && isUnique(vcaTriplets, vcaDetails))
            vcaTriplets.push_back(vcaDetails);
    }
    return vcaTriplets;
}

bool ViewportCameraAreaGatherer::isUnique(const QVector<ViewportCameraAreaDetails> &vcaList,
                                          const ViewportCameraAreaDetails &vca) const
{
    for (const ViewportCameraAreaDetails &listItem : vcaList) {
        if (vca.cameraId == listItem.cameraId &&
                vca.viewport == listItem.viewport &&
                vca.surface == listItem.surface &&
                vca.area == listItem.area)
            return false;
    }
    return true;
}

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 Vector3D &a,
               uint bndx, const Vector3D &b,
               uint cndx, const Vector3D &c) override;
    bool intersectsSegmentTriangle(uint andx, const Vector3D &a,
                                   uint bndx, const Vector3D &b,
                                   uint cndx, const Vector3D &c);
};

void TriangleCollisionVisitor::visit(uint andx, const Vector3D &a, uint bndx, const Vector3D &b, uint cndx, const Vector3D &c)
{
    const Matrix4x4 &mat = *m_root->worldTransform();
    const Vector3D tA = mat * a;
    const Vector3D tB = mat * b;
    const Vector3D tC = mat * c;

    bool intersected = m_frontFaceRequested &&
            intersectsSegmentTriangle(cndx, tC, bndx, tB, andx, tA);    // front facing
    if (!intersected && m_backFaceRequested) {
        intersected = intersectsSegmentTriangle(andx, tA, bndx, tB, cndx, tC);    // back facing
    }

    m_triangleIndex++;
}


bool TriangleCollisionVisitor::intersectsSegmentTriangle(uint andx, const Vector3D &a, uint bndx, const Vector3D &b, uint cndx, const Vector3D &c)
{
    float t = 0.0f;
    Vector3D uvw;
    bool intersected = Render::intersectsSegmentTriangle(m_ray, a, b, c, uvw, t);
    if (intersected) {
        QCollisionQueryResult::Hit queryResult;
        queryResult.m_type = QCollisionQueryResult::Hit::Triangle;
        queryResult.m_entityId = m_root->peerId();
        queryResult.m_primitiveIndex = m_triangleIndex;
        queryResult.m_vertexIndex[0] = andx;
        queryResult.m_vertexIndex[1] = bndx;
        queryResult.m_vertexIndex[2] = cndx;
        queryResult.m_uvw = uvw;
        queryResult.m_intersection = m_ray.point(t * m_ray.distance());
        queryResult.m_distance = m_ray.projectedDistance(queryResult.m_intersection);
        hits.push_back(queryResult);
    }
    return intersected;
}

class LineCollisionVisitor : public SegmentsVisitor
{
public:
    HitList hits;

    LineCollisionVisitor(NodeManagers* manager, const Entity *root, const RayCasting::QRay3D& ray,
                         float pickWorldSpaceTolerance)
        : SegmentsVisitor(manager), m_root(root), m_ray(ray)
        , m_segmentIndex(0), m_pickWorldSpaceTolerance(pickWorldSpaceTolerance)
    {
    }

private:
    const Entity *m_root;
    RayCasting::QRay3D m_ray;
    uint m_segmentIndex;
    float m_pickWorldSpaceTolerance;

    void visit(uint andx, const Vector3D &a,
               uint bndx, const Vector3D &b) override;
    bool intersectsSegmentSegment(uint andx, const Vector3D &a,
                                  uint bndx, const Vector3D &b);
    bool rayToLineSegment(const Vector3D& lineStart,const Vector3D& lineEnd,
                          float &distance, Vector3D &intersection) const;
};

void LineCollisionVisitor::visit(uint andx, const Vector3D &a, uint bndx, const Vector3D &b)
{
    const Matrix4x4 &mat = *m_root->worldTransform();
    const Vector3D tA = mat * a;
    const Vector3D tB = mat * b;

    intersectsSegmentSegment(andx, tA, bndx, tB);

    m_segmentIndex++;
}

bool LineCollisionVisitor::intersectsSegmentSegment(uint andx, const Vector3D &a,
                                                    uint bndx, const Vector3D &b)
{
    float distance = 0.f;
    Vector3D intersection;
    bool res = rayToLineSegment(a, b, distance, intersection);
    if (res) {
        QCollisionQueryResult::Hit queryResult;
        queryResult.m_type = QCollisionQueryResult::Hit::Edge;
        queryResult.m_entityId = m_root->peerId();
        queryResult.m_primitiveIndex = m_segmentIndex;
        queryResult.m_vertexIndex[0] = andx;
        queryResult.m_vertexIndex[1] = bndx;
        queryResult.m_intersection = intersection;
        queryResult.m_distance = m_ray.projectedDistance(queryResult.m_intersection);
        hits.push_back(queryResult);
        return true;
    }
    return false;
}

bool LineCollisionVisitor::rayToLineSegment(const Vector3D& lineStart,const Vector3D& lineEnd,
                                            float &distance, Vector3D &intersection) const
{
    const float epsilon = 0.00000001f;

    const Vector3D u = m_ray.direction() * m_ray.distance();
    const Vector3D v = lineEnd - lineStart;
    const Vector3D w = m_ray.origin() - lineStart;
    const float a = Vector3D::dotProduct(u, u);
    const float b = Vector3D::dotProduct(u, v);
    const float c = Vector3D::dotProduct(v, v);
    const float d = Vector3D::dotProduct(u, w);
    const float e = Vector3D::dotProduct(v, w);
    const float D = a * c - b * b;
    float sc, sN, sD = D;
    float tc, tN, tD = D;

    if (D < epsilon) {
        sN = 0.0;
        sD = 1.0;
        tN = e;
        tD = c;
    } else {
        sN = (b * e - c * d);
        tN = (a * e - b * d);
        if (sN < 0.0) {
            sN = 0.0;
            tN = e;
            tD = c;
        }
    }

    if (tN < 0.0) {
        tN = 0.0;
        if (-d < 0.0)
            sN = 0.0;
        else {
            sN = -d;
            sD = a;
        }
    } else if (tN > tD) {
        tN = tD;
        if ((-d + b) < 0.0)
            sN = 0;
        else {
            sN = (-d + b);
            sD = a;
        }
    }

    sc = (qAbs(sN) < epsilon ? 0.0f : sN / sD);
    tc = (qAbs(tN) < epsilon ? 0.0f : tN / tD);

    const Vector3D dP = w + (sc * u) - (tc * v);
    const float f = dP.length();
    if (f < m_pickWorldSpaceTolerance) {
        distance = sc * u.length();
        intersection = lineStart + v * tc;
        return true;
    }
    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 Vector3D &p) override;

    double pointToRayDistance(const Vector3D &a, Vector3D &p)
    {
        const Vector3D v = a - m_ray.origin();
        const double t = Vector3D::dotProduct(v, m_ray.direction());
        p = m_ray.origin() + t * m_ray.direction();
        return (p - a).length();
    }
};


void PointCollisionVisitor::visit(uint ndx, const Vector3D &p)
{
    const Matrix4x4 &mat = *m_root->worldTransform();
    const Vector3D tP = mat * p;
    Vector3D 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()) {
        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;
}


struct HighestPriorityHitReducer
{
    // No need to protect this from concurrent access as the table
    // is read only
    const QHash<Qt3DCore::QNodeId, int> entityToPriorityTable;

    HitList operator()(HitList &result, const HitList &intermediate)
    {
        // Sort by priority first
        // If we have equal priorities, we then sort by distance

        if (!intermediate.empty()) {
            if (result.empty())
                result.push_back(intermediate.front());
            int currentPriority = entityToPriorityTable.value(result.front().m_entityId, 0);
            float closest = result.front().m_distance;

            for (const auto &v : intermediate) {
                const int newEntryPriority = entityToPriorityTable.value(v.m_entityId, 0);
                if (newEntryPriority > currentPriority) {
                    result.push_front(v);
                    currentPriority = newEntryPriority;
                    closest = v.m_distance;
                } else if (newEntryPriority == currentPriority) {
                    if (v.m_distance < closest) {
                        result.push_front(v);
                        closest = v.m_distance;
                        currentPriority = newEntryPriority;
                    }
                }
            }

            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)
{ }

AbstractCollisionGathererFunctor::~AbstractCollisionGathererFunctor()
{ }

HitList AbstractCollisionGathererFunctor::operator ()(const Entity *entity) const
{
    if (m_objectPickersRequired) {
        HObjectPicker objectPickerHandle = entity->componentHandle<ObjectPicker>();

        // If the Entity which actually received the hit doesn't have
        // an object picker component, we need to check the parent if it has one ...
        auto parentEntity = entity;
        while (objectPickerHandle.isNull() && parentEntity != nullptr) {
            parentEntity = parentEntity->parent();
            if (parentEntity != nullptr)
                objectPickerHandle = parentEntity->componentHandle<ObjectPicker>();
        }

        ObjectPicker *objectPicker = m_manager->objectPickerManager()->data(objectPickerHandle);
        if (objectPicker == nullptr || !objectPicker->isEnabled())
            return {};   // don't bother picking entities that don't
                         // have an object picker, or if it's disabled
    }

    return pick(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(HitList &results)
{
    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);
}

namespace {

// Workaround to avoid passing *this into the blockMappedReduce calls for the
// mapFunctor which would cause an SSE alignment error on Windows Also note
// that a lambda doesn't work since we need the typedef result_type defined to
// work with QtConcurrent
struct MapFunctorHolder
{
    MapFunctorHolder(const AbstractCollisionGathererFunctor *gatherer)
        : m_gatherer(gatherer)
    {}

    // This define is required to work with QtConcurrent
    typedef HitList result_type;
    HitList operator ()(const Entity *e) const { return m_gatherer->operator ()(e); }

    const AbstractCollisionGathererFunctor *m_gatherer;
};

} // anonymous

HitList EntityCollisionGathererFunctor::computeHits(const QVector<Entity *> &entities,
                                                    Qt3DRender::QPickingSettings::PickResultMode mode)
{
    std::function<HitList (HitList &, const HitList &)> reducerOp;
    switch (mode) {
    case QPickingSettings::AllPicks:
        reducerOp = PickingUtils::reduceToAllHits;
        break;
    case QPickingSettings::NearestPriorityPick:
        reducerOp = HighestPriorityHitReducer{ m_entityToPriorityTable };
        break;
    case QPickingSettings::NearestPick:
        reducerOp = PickingUtils::reduceToFirstHit;
        break;
    }

    const MapFunctorHolder holder(this);
#if QT_CONFIG(concurrent)
    return QtConcurrent::blockingMappedReduced<HitList>(entities, holder, reducerOp);
#else
    HitList sphereHits;
    QVector<PickingUtils::EntityCollisionGathererFunctor::result_type> results;
    for (const Entity *entity : entities)
        sphereHits = reducerOp(sphereHits, holder(entity));
    return sphereHits;
#endif
}

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;
}

HitList TriangleCollisionGathererFunctor::computeHits(const QVector<Entity *> &entities,
                                                      Qt3DRender::QPickingSettings::PickResultMode mode)
{
    std::function<HitList (HitList &, const HitList &)> reducerOp;
    switch (mode) {
    case QPickingSettings::AllPicks:
        reducerOp = PickingUtils::reduceToAllHits;
        break;
    case QPickingSettings::NearestPriorityPick:
        reducerOp = HighestPriorityHitReducer { m_entityToPriorityTable };
        break;
    case QPickingSettings::NearestPick:
        reducerOp = PickingUtils::reduceToFirstHit;
        break;
    }

    const MapFunctorHolder holder(this);
#if QT_CONFIG(concurrent)
    return QtConcurrent::blockingMappedReduced<HitList>(entities, holder, reducerOp);
#else
    HitList sphereHits;
    QVector<PickingUtils::TriangleCollisionGathererFunctor::result_type> results;
    for (const Entity *entity : entities)
        sphereHits = reducerOp(sphereHits, holder(entity));
        return sphereHits;
#endif
}

HitList TriangleCollisionGathererFunctor::pick(const Entity *entity) const
{
    HitList result;

    GeometryRenderer *gRenderer = entity->renderComponent<GeometryRenderer>();
    if (!gRenderer)
        return result;

    if (rayHitsEntity(entity)) {
        TriangleCollisionVisitor visitor(m_manager, entity, m_ray, m_frontFaceRequested, m_backFaceRequested);
        visitor.apply(gRenderer, entity->peerId());
        result = visitor.hits;

        sortHits(result);
    }

    return result;
}

HitList LineCollisionGathererFunctor::computeHits(const QVector<Entity *> &entities,
                                                  Qt3DRender::QPickingSettings::PickResultMode mode)
{
    std::function<HitList (HitList &, const HitList &)> reducerOp;
    switch (mode) {
    case QPickingSettings::AllPicks:
        reducerOp = PickingUtils::reduceToAllHits;
        break;
    case QPickingSettings::NearestPriorityPick:
        reducerOp = HighestPriorityHitReducer { m_entityToPriorityTable };
        break;
    case QPickingSettings::NearestPick:
        reducerOp = PickingUtils::reduceToFirstHit;
        break;
    }

    const MapFunctorHolder holder(this);
#if QT_CONFIG(concurrent)
    return QtConcurrent::blockingMappedReduced<HitList>(entities, holder, reducerOp);
#else
    HitList sphereHits;
    QVector<PickingUtils::LineCollisionGathererFunctor::result_type> results;
    for (const Entity *entity : entities)
        sphereHits = reducerOp(sphereHits, holder(entity));
    return sphereHits;
#endif
}

HitList LineCollisionGathererFunctor::pick(const Entity *entity) const
{
    HitList result;

    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;
}

HitList PointCollisionGathererFunctor::computeHits(const QVector<Entity *> &entities,
                                                   Qt3DRender::QPickingSettings::PickResultMode mode)
{
    std::function<HitList (HitList &, const HitList &)> reducerOp;
    switch (mode) {
    case QPickingSettings::AllPicks:
        reducerOp = PickingUtils::reduceToAllHits;
        break;
    case QPickingSettings::NearestPriorityPick:
        reducerOp = HighestPriorityHitReducer { m_entityToPriorityTable };
        break;
    case QPickingSettings::NearestPick:
        reducerOp = PickingUtils::reduceToFirstHit;
        break;
    }

    const MapFunctorHolder holder(this);
#if QT_CONFIG(concurrent)
    return QtConcurrent::blockingMappedReduced<HitList>(entities, holder, reducerOp);
#else
    HitList sphereHits;
    QVector<PickingUtils::PointCollisionGathererFunctor::result_type> results;
    for (const Entity *entity : entities)
        sphereHits = reducerOp(sphereHits, holder(entity));
    return sphereHits;
#endif
}

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, bool requireObjectPicker)
    : m_ray(ray)
    , m_objectPickersRequired(requireObjectPicker)
    , m_filterMode(QAbstractRayCaster::AcceptAnyMatchingLayers)
{

}

void HierarchicalEntityPicker::setFilterLayers(const Qt3DCore::QNodeIdVector &layerIds, QAbstractRayCaster::FilterMode mode)
{
    m_filterMode = mode;
    m_layerIds = layerIds;
    std::sort(m_layerIds.begin(), m_layerIds.end());
}

bool HierarchicalEntityPicker::collectHits(NodeManagers *manager, Entity *root)
{
    m_hits.clear();
    m_entities.clear();
    m_entityToPriorityTable.clear();

    QRayCastingService rayCasting;
    struct EntityData {
        Entity* entity;
        bool hasObjectPicker;
        Qt3DCore::QNodeIdVector recursiveLayers;
        int priority;
    };
    std::vector<EntityData> worklist;
    worklist.push_back({root, !root->componentHandle<ObjectPicker>().isNull(), {}, 0});

    LayerManager *layerManager = manager->layerManager();

    while (!worklist.empty()) {
        EntityData current = worklist.back();
        worklist.pop_back();

        bool accepted = true;
        if (m_layerIds.size()) {
            // TODO investigate reusing logic from LayerFilter job
            Qt3DCore::QNodeIdVector filterLayers = current.recursiveLayers + current.entity->componentsUuid<Layer>();

            // remove disabled layers
            filterLayers.erase(std::remove_if(filterLayers.begin(), filterLayers.end(),
                                              [layerManager](const Qt3DCore::QNodeId layerId) {
                Layer *layer = layerManager->lookupResource(layerId);
                return !layer || !layer->isEnabled();
            }), filterLayers.end());

            std::sort(filterLayers.begin(), filterLayers.end());

            Qt3DCore::QNodeIdVector commonIds;
            std::set_intersection(m_layerIds.cbegin(), m_layerIds.cend(),
                                  filterLayers.cbegin(), filterLayers.cend(),
                                  std::back_inserter(commonIds));

            switch (m_filterMode) {
            case QAbstractRayCaster::AcceptAnyMatchingLayers: {
                accepted = !commonIds.empty();
                break;
            }
            case QAbstractRayCaster::AcceptAllMatchingLayers: {
                accepted = commonIds == m_layerIds;
                break;
            }
            case QAbstractRayCaster::DiscardAnyMatchingLayers: {
                accepted = commonIds.empty();
                break;
            }
            case QAbstractRayCaster::DiscardAllMatchingLayers: {
                accepted = !(commonIds == m_layerIds);
                break;
            }
            default:
                Q_UNREACHABLE();
                break;
            }
        }

        // first pick entry sub-scene-graph
        QCollisionQueryResult::Hit queryResult =
                rayCasting.query(m_ray, current.entity->worldBoundingVolumeWithChildren());
        if (queryResult.m_distance < 0.f)
            continue;

        // if we get a hit, we check again for this specific entity
        queryResult = rayCasting.query(m_ray, current.entity->worldBoundingVolume());
        if (accepted && queryResult.m_distance >= 0.f && (current.hasObjectPicker || !m_objectPickersRequired)) {
            m_entities.push_back(current.entity);
            m_hits.push_back(queryResult);
            // Record entry for entity/priority
            m_entityToPriorityTable.insert(current.entity->peerId(), current.priority);
        }

        Qt3DCore::QNodeIdVector recursiveLayers;
        const Qt3DCore::QNodeIdVector entityLayers = current.entity->componentsUuid<Layer>();
        for (const Qt3DCore::QNodeId layerId : entityLayers) {
            Layer *layer = layerManager->lookupResource(layerId);
            if (layer->recursive())
                recursiveLayers << layerId;
        }

        // and pick children
        const auto childrenHandles = current.entity->childrenHandles();
        for (const HEntity &handle : childrenHandles) {
            Entity *child = manager->renderNodesManager()->data(handle);
            if (child) {
                ObjectPicker *childPicker = child->renderComponent<ObjectPicker>();
                worklist.push_back({child, current.hasObjectPicker || childPicker,
                                    current.recursiveLayers + recursiveLayers,
                                    (childPicker ? childPicker->priority() : current.priority)});
            }
        }
    }

    return !m_hits.empty();
}

} // PickingUtils

} // Render

} // Qt3DRender

QT_END_NAMESPACE
