1/****************************************************************************
2**
3** Copyright (C) 2018 Klaralvdalens Datakonsult AB (KDAB).
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt3D module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "abstractpickingjob_p.h"
41#include <Qt3DRender/qgeometryrenderer.h>
42#include <Qt3DRender/private/nodemanagers_p.h>
43#include <Qt3DRender/private/entity_p.h>
44#include <Qt3DRender/private/objectpicker_p.h>
45#include <Qt3DRender/private/managers_p.h>
46#include <Qt3DRender/private/geometryrenderer_p.h>
47#include <Qt3DRender/private/rendersettings_p.h>
48#include <Qt3DRender/private/trianglesvisitor_p.h>
49#include <Qt3DRender/private/job_common_p.h>
50#include <QtGui/qoffscreensurface.h>
51#include <QtGui/qwindow.h>
52
53QT_BEGIN_NAMESPACE
54
55namespace Qt3DRender {
56
57namespace Render {
58
59AbstractPickingJob::AbstractPickingJob()
60 : Qt3DCore::QAspectJob()
61 , m_manager(nullptr)
62 , m_node(nullptr)
63 , m_frameGraphRoot(nullptr)
64 , m_renderSettings(nullptr)
65 , m_oneEnabledAtLeast(false)
66{
67}
68
69AbstractPickingJob::AbstractPickingJob(Qt3DCore::QAspectJobPrivate &dd)
70 : Qt3DCore::QAspectJob(dd)
71 , m_manager(nullptr)
72 , m_node(nullptr)
73 , m_frameGraphRoot(nullptr)
74 , m_renderSettings(nullptr)
75 , m_oneEnabledAtLeast(false)
76{
77
78}
79
80void AbstractPickingJob::setRoot(Entity *root)
81{
82 m_node = root;
83}
84
85void AbstractPickingJob::setFrameGraphRoot(FrameGraphNode *frameGraphRoot)
86{
87 m_frameGraphRoot = frameGraphRoot;
88}
89
90void AbstractPickingJob::setRenderSettings(RenderSettings *settings)
91{
92 m_renderSettings = settings;
93}
94
95void AbstractPickingJob::setManagers(NodeManagers *manager)
96{
97 m_manager = manager;
98}
99
100void AbstractPickingJob::run()
101{
102 Q_ASSERT(m_frameGraphRoot && m_renderSettings && m_node && m_manager);
103 runHelper();
104}
105
106RayCasting::QRay3D AbstractPickingJob::intersectionRay(const QPoint &pos, const Matrix4x4 &viewMatrix,
107 const Matrix4x4 &projectionMatrix, const QRect &viewport)
108{
109 Vector3D nearPos = Vector3D(pos.x(), pos.y(), 0.0f);
110 nearPos = nearPos.unproject(modelView: viewMatrix, projection: projectionMatrix, viewport);
111 Vector3D farPos = Vector3D(pos.x(), pos.y(), 1.0f);
112 farPos = farPos.unproject(modelView: viewMatrix, projection: projectionMatrix, viewport);
113
114 return RayCasting::QRay3D(nearPos,
115 (farPos - nearPos).normalized(),
116 (farPos - nearPos).length());
117}
118
119QRect AbstractPickingJob::windowViewport(const QSize &area, const QRectF &relativeViewport) const
120{
121 if (area.isValid()) {
122 const int areaWidth = area.width();
123 const int areaHeight = area.height();
124 return QRect(relativeViewport.x() * areaWidth,
125 (1.0 - relativeViewport.y() - relativeViewport.height()) * areaHeight,
126 relativeViewport.width() * areaWidth,
127 relativeViewport.height() * areaHeight);
128 }
129 return relativeViewport.toRect();
130}
131
132RayCasting::QRay3D AbstractPickingJob::rayForViewportAndCamera(const PickingUtils::ViewportCameraAreaDetails &vca,
133 QObject *eventSource,
134 const QPoint &pos) const
135{
136 static RayCasting::QRay3D invalidRay({}, {}, 0.f);
137
138 if (!vca.area.isValid())
139 return invalidRay;
140
141 Matrix4x4 viewMatrix;
142 Matrix4x4 projectionMatrix;
143 Render::CameraLens::viewMatrixForCamera(manager: m_manager->renderNodesManager(),
144 cameraId: vca.cameraId,
145 viewMatrix,
146 projectionMatrix);
147 // Returns viewport rect in GL coordinates (y inverted)
148 const QRect viewport = windowViewport(area: vca.area, relativeViewport: vca.viewport);
149 // In GL the y is inverted compared to Qt
150 const QPoint glCorrectPos = QPoint(pos.x(), vca.area.height() - pos.y());
151
152 if (!viewport.contains(p: glCorrectPos))
153 return invalidRay;
154 if (vca.surface) {
155 QSurface *surface = nullptr;
156 if (eventSource) {
157 QWindow *window = qobject_cast<QWindow *>(o: eventSource);
158 if (window) {
159 surface = static_cast<QSurface *>(window);
160 } else {
161 QOffscreenSurface *offscreen = qobject_cast<QOffscreenSurface *>(object: eventSource);
162 if (offscreen)
163 surface = static_cast<QSurface *>(offscreen);
164 }
165 }
166 if (surface && vca.surface != surface)
167 return invalidRay;
168 }
169
170 const auto ray = intersectionRay(pos: glCorrectPos, viewMatrix, projectionMatrix, viewport);
171 return ray;
172}
173
174} // namespace Render
175
176} // namespace Qt3DRender
177
178QT_END_NAMESPACE
179

source code of qt3d/src/render/jobs/abstractpickingjob.cpp