diff options
Diffstat (limited to 'src/render/jobs/pickboundingvolumejob.cpp')
-rw-r--r-- | src/render/jobs/pickboundingvolumejob.cpp | 75 |
1 files changed, 42 insertions, 33 deletions
diff --git a/src/render/jobs/pickboundingvolumejob.cpp b/src/render/jobs/pickboundingvolumejob.cpp index 6b8b93647..f9c7a390c 100644 --- a/src/render/jobs/pickboundingvolumejob.cpp +++ b/src/render/jobs/pickboundingvolumejob.cpp @@ -49,6 +49,7 @@ #include <Qt3DRender/private/rendersettings_p.h> #include <Qt3DRender/qgeometryrenderer.h> #include <Qt3DRender/private/job_common_p.h> +#include <Qt3DRender/private/qpickevent_p.h> QT_BEGIN_NAMESPACE @@ -59,6 +60,8 @@ namespace Render { namespace { +typedef PickingUtils::AbstractCollisionGathererFunctor::result_type HitList; + void setEventButtonAndModifiers(const QMouseEvent &event, QPickEvent::Buttons &eventButton, int &eventButtons, int &eventModifiers) { switch (event.button()) { @@ -120,6 +123,11 @@ void PickBoundingVolumeJob::setMouseEvents(const QList<QMouseEvent> &pendingEven m_pendingMouseEvents = pendingEvents; } +void PickBoundingVolumeJob::setKeyEvents(const QList<QKeyEvent> &pendingEvents) +{ + m_pendingKeyEvents = pendingEvents; +} + void PickBoundingVolumeJob::setFrameGraphRoot(FrameGraphNode *frameGraphRoot) { m_frameGraphRoot = frameGraphRoot; @@ -159,7 +167,8 @@ bool PickBoundingVolumeJob::runHelper() m_oneEnabledAtLeast = false; m_oneHoverAtLeast = false; - for (auto handle : m_manager->objectPickerManager()->activeHandles()) { + const auto activeHandles = m_manager->objectPickerManager()->activeHandles(); + for (auto handle : activeHandles) { auto picker = m_manager->objectPickerManager()->data(handle); m_oneEnabledAtLeast |= picker->isEnabled(); m_oneHoverAtLeast |= picker->isHoverEnabled(); @@ -214,11 +223,6 @@ bool PickBoundingVolumeJob::runHelper() // If we have move or hover move events that someone cares about, we try to avoid expensive computations // by compressing them into a single one - // Gather the entities for the frame - // TO DO: We could skip doing that every frame and only do it when we know for sure - // that the tree structure has changed - PickingUtils::EntityGatherer entitiesGatherer(m_node); - // Store the reducer function which varies depending on the picking settings set on the renderer using ReducerFunction = PickingUtils::CollisionVisitor::HitList (*)(PickingUtils::CollisionVisitor::HitList &results, const PickingUtils::CollisionVisitor::HitList &intermediate); @@ -244,25 +248,30 @@ bool PickBoundingVolumeJob::runHelper() // For each triplet of Viewport / Camera and Area for (const PickingUtils::ViewportCameraAreaTriplet &vca : vcaTriplets) { - typedef PickingUtils::AbstractCollisionGathererFunctor::result_type HitList; HitList sphereHits; QRay3D ray = rayForViewportAndCamera(vca.area, event.pos(), vca.viewport, vca.cameraId); - if (trianglePickingRequested) { - PickingUtils::TriangleCollisionGathererFunctor gathererFunctor; - gathererFunctor.m_frontFaceRequested = frontFaceRequested; - gathererFunctor.m_backFaceRequested = backFaceRequested; - gathererFunctor.m_manager = m_manager; - gathererFunctor.m_ray = ray; - sphereHits = QtConcurrent::blockingMappedReduced<HitList>(entitiesGatherer.entities(), gathererFunctor, reducerOp); - } else { - PickingUtils::EntityCollisionGathererFunctor gathererFunctor; - gathererFunctor.m_manager = m_manager; - gathererFunctor.m_ray = ray; - sphereHits = QtConcurrent::blockingMappedReduced<HitList>(entitiesGatherer.entities(), gathererFunctor, reducerOp); + + PickingUtils::HierarchicalEntityPicker entityPicker(ray); + if (entityPicker.collectHits(m_node)) { + if (trianglePickingRequested) { + PickingUtils::TriangleCollisionGathererFunctor gathererFunctor; + gathererFunctor.m_frontFaceRequested = frontFaceRequested; + gathererFunctor.m_backFaceRequested = backFaceRequested; + gathererFunctor.m_manager = m_manager; + gathererFunctor.m_ray = ray; + sphereHits = QtConcurrent::blockingMappedReduced<HitList>(entityPicker.entities(), + gathererFunctor, reducerOp); + } else { + sphereHits = entityPicker.hits(); + PickingUtils::AbstractCollisionGathererFunctor::sortHits(sphereHits); + if (!allHitsRequested) + sphereHits = { sphereHits.front() }; + } } // Dispatch events based on hit results - dispatchPickEvents(event, sphereHits, eventButton, eventButtons, eventModifiers, trianglePickingRequested, allHitsRequested); + dispatchPickEvents(event, sphereHits, eventButton, eventButtons, eventModifiers, + trianglePickingRequested, allHitsRequested); } } @@ -331,17 +340,18 @@ void PickBoundingVolumeJob::dispatchPickEvents(const QMouseEvent &event, // Send the corresponding event QVector3D localIntersection = hit.m_intersection; if (entity && entity->worldTransform()) - localIntersection = hit.m_intersection * entity->worldTransform()->inverted(); + localIntersection = entity->worldTransform()->inverted() * hit.m_intersection; QPickEventPtr pickEvent; - if (trianglePickingRequested) + if (trianglePickingRequested) { pickEvent.reset(new QPickTriangleEvent(event.localPos(), hit.m_intersection, localIntersection, hit.m_distance, hit.m_triangleIndex, hit.m_vertexIndex[0], hit.m_vertexIndex[1], hit.m_vertexIndex[2], - eventButton, eventButtons, eventModifiers)); - else + eventButton, eventButtons, eventModifiers, hit.m_uvw)); + QPickEventPrivate::get(pickEvent.data())->m_entity = hit.m_entityId; + } else { pickEvent.reset(new QPickEvent(event.localPos(), hit.m_intersection, localIntersection, hit.m_distance, eventButton, eventButtons, eventModifiers)); - + } switch (event.type()) { case QEvent::MouseButtonPress: { // Store pressed object handle @@ -352,24 +362,23 @@ void PickBoundingVolumeJob::dispatchPickEvents(const QMouseEvent &event, } case QEvent::MouseButtonRelease: { - if (lastCurrentPicker != nullptr && m_currentPicker == objectPickerHandle) - m_currentPicker = HObjectPicker(); // Only send the release event if it was pressed - if (objectPicker->isPressed()) { - if (lastCurrentPicker == objectPicker) - objectPicker->onClicked(pickEvent); + if (objectPicker->isPressed()) objectPicker->onReleased(pickEvent); + if (lastCurrentPicker != nullptr && m_currentPicker == objectPickerHandle) { + objectPicker->onClicked(pickEvent); + m_currentPicker = HObjectPicker(); } break; } - +#if QT_CONFIG(gestures) case Qt::TapGesture: { objectPicker->onClicked(pickEvent); break; } - +#endif case QEvent::MouseMove: { - if (objectPicker->isPressed() && objectPicker->isDragEnabled()) { + if ((objectPicker->isPressed() || objectPicker->isHoverEnabled()) && objectPicker->isDragEnabled()) { objectPicker->onMoved(pickEvent); } // fallthrough |