summaryrefslogtreecommitdiffstats
path: root/src/render/jobs/pickboundingvolumejob.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/render/jobs/pickboundingvolumejob.cpp')
-rw-r--r--src/render/jobs/pickboundingvolumejob.cpp75
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