1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt Data Visualization module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL$
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 General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 or (at your option) any later version
20** approved by the KDE Free Qt Foundation. The licenses are as published by
21** the Free Software Foundation and appearing in the file LICENSE.GPL3
22** included in the packaging of this file. Please review the following
23** information to ensure the GNU General Public License requirements will
24** be met: https://www.gnu.org/licenses/gpl-3.0.html.
25**
26** $QT_END_LICENSE$
27**
28****************************************************************************/
29
30#include "selectionpointer_p.h"
31#include "shaderhelper_p.h"
32#include "objecthelper_p.h"
33#include "texturehelper_p.h"
34#include "q3dcamera_p.h"
35#include "utils_p.h"
36
37QT_BEGIN_NAMESPACE_DATAVISUALIZATION
38
39const GLfloat sliceUnits = 2.5;
40
41SelectionPointer::SelectionPointer(Drawer *drawer)
42 : QObject(0),
43 m_labelShader(0),
44 m_pointShader(0),
45 m_labelObj(0),
46 m_pointObj(0),
47 m_textureHelper(0),
48 m_cachedTheme(drawer->theme()),
49 m_labelBackground(false),
50 m_drawer(drawer),
51 m_cachedScene(0)
52{
53 initializeOpenGL();
54
55 QObject::connect(sender: m_drawer, signal: &Drawer::drawerChanged,
56 receiver: this, slot: &SelectionPointer::handleDrawerChange);
57}
58
59SelectionPointer::~SelectionPointer()
60{
61 delete m_labelShader;
62 delete m_pointShader;
63 delete m_textureHelper;
64}
65
66void SelectionPointer::initializeOpenGL()
67{
68 initializeOpenGLFunctions();
69
70 m_textureHelper = new TextureHelper();
71 m_drawer->initializeOpenGL();
72
73 initShaders();
74}
75
76void SelectionPointer::updateScene(Q3DScene *scene)
77{
78 m_cachedScene = scene;
79}
80
81void SelectionPointer::renderSelectionPointer(GLuint defaultFboHandle, bool useOrtho)
82{
83 Q_UNUSED(defaultFboHandle)
84
85 glViewport(x: m_mainViewPort.x(), y: m_mainViewPort.y(),
86 width: m_mainViewPort.width(), height: m_mainViewPort.height());
87
88 Q3DCamera *camera = m_cachedScene->activeCamera();
89
90 QMatrix4x4 itModelMatrix;
91
92 // Get view matrix
93 QMatrix4x4 viewMatrix;
94 QMatrix4x4 projectionMatrix;
95 GLfloat viewPortRatio = (GLfloat)m_mainViewPort.width() / (GLfloat)m_mainViewPort.height();
96 if (m_cachedIsSlicingActivated) {
97 GLfloat sliceUnitsScaled = sliceUnits / m_autoScaleAdjustment;
98 viewMatrix.lookAt(eye: QVector3D(0.0f, 0.0f, 1.0f), center: zeroVector, up: upVector);
99 projectionMatrix.ortho(left: -sliceUnitsScaled * viewPortRatio, right: sliceUnitsScaled * viewPortRatio,
100 bottom: -sliceUnitsScaled, top: sliceUnitsScaled,
101 nearPlane: -1.0f, farPlane: 4.0f);
102 } else if (useOrtho) {
103 viewMatrix = camera->d_ptr->viewMatrix();
104 GLfloat orthoRatio = 2.0f;
105 projectionMatrix.ortho(left: -viewPortRatio * orthoRatio, right: viewPortRatio * orthoRatio,
106 bottom: -orthoRatio, top: orthoRatio,
107 nearPlane: 0.0f, farPlane: 100.0f);
108 } else {
109 viewMatrix = camera->d_ptr->viewMatrix();
110 projectionMatrix.perspective(verticalAngle: 45.0f, aspectRatio: viewPortRatio, nearPlane: 0.1f, farPlane: 100.0f);
111 }
112
113 QMatrix4x4 modelMatrix;
114 QMatrix4x4 MVPMatrix;
115
116 // Position the pointer ball
117 modelMatrix.translate(vector: m_position);
118
119 if (!m_rotation.isIdentity()) {
120 modelMatrix.rotate(quaternion: m_rotation);
121 itModelMatrix.rotate(quaternion: m_rotation);
122 }
123
124 // Scale the point with fixed values (at this point)
125 QVector3D scaleVector(0.05f, 0.05f, 0.05f);
126 modelMatrix.scale(vector: scaleVector);
127 itModelMatrix.scale(vector: scaleVector);
128
129 MVPMatrix = projectionMatrix * viewMatrix * modelMatrix;
130
131 QVector3D lightPos = m_cachedScene->activeLight()->position();
132
133 //
134 // Draw the point
135 //
136 m_pointShader->bind();
137 m_pointShader->setUniformValue(uniform: m_pointShader->lightP(), value: lightPos);
138 m_pointShader->setUniformValue(uniform: m_pointShader->view(), value: viewMatrix);
139 m_pointShader->setUniformValue(uniform: m_pointShader->model(), value: modelMatrix);
140 m_pointShader->setUniformValue(uniform: m_pointShader->nModel(), value: itModelMatrix.inverted().transposed());
141 m_pointShader->setUniformValue(uniform: m_pointShader->color(), value: m_highlightColor);
142 m_pointShader->setUniformValue(uniform: m_pointShader->MVP(), value: MVPMatrix);
143 m_pointShader->setUniformValue(uniform: m_pointShader->ambientS(),
144 value: m_cachedTheme->ambientLightStrength());
145 m_pointShader->setUniformValue(uniform: m_pointShader->lightS(), value: m_cachedTheme->lightStrength() * 2.0f);
146 m_pointShader->setUniformValue(uniform: m_pointShader->lightColor(),
147 value: Utils::vectorFromColor(color: m_cachedTheme->lightColor()));
148
149 m_drawer->drawObject(shader: m_pointShader, object: m_pointObj);
150}
151
152void SelectionPointer::renderSelectionLabel(GLuint defaultFboHandle, bool useOrtho)
153{
154 Q_UNUSED(defaultFboHandle)
155
156 glViewport(x: m_mainViewPort.x(), y: m_mainViewPort.y(),
157 width: m_mainViewPort.width(), height: m_mainViewPort.height());
158
159 Q3DCamera *camera = m_cachedScene->activeCamera();
160
161 // Get view matrix
162 QMatrix4x4 viewMatrix;
163 QMatrix4x4 modelMatrixLabel;
164 QMatrix4x4 projectionMatrix;
165 GLfloat viewPortRatio = (GLfloat)m_mainViewPort.width() / (GLfloat)m_mainViewPort.height();
166 if (m_cachedIsSlicingActivated) {
167 GLfloat sliceUnitsScaled = sliceUnits / m_autoScaleAdjustment;
168 viewMatrix.lookAt(eye: QVector3D(0.0f, 0.0f, 1.0f), center: zeroVector, up: upVector);
169 projectionMatrix.ortho(left: -sliceUnitsScaled * viewPortRatio, right: sliceUnitsScaled * viewPortRatio,
170 bottom: -sliceUnitsScaled, top: sliceUnitsScaled,
171 nearPlane: -1.0f, farPlane: 4.0f);
172 } else if (useOrtho) {
173 viewMatrix = camera->d_ptr->viewMatrix();
174 GLfloat orthoRatio = 2.0f;
175 projectionMatrix.ortho(left: -viewPortRatio * orthoRatio, right: viewPortRatio * orthoRatio,
176 bottom: -orthoRatio, top: orthoRatio,
177 nearPlane: 0.0f, farPlane: 100.0f);
178 } else {
179 viewMatrix = camera->d_ptr->viewMatrix();
180 projectionMatrix.perspective(verticalAngle: 45.0f, aspectRatio: viewPortRatio, nearPlane: 0.1f, farPlane: 100.0f);
181 }
182
183 QSize textureSize = m_labelItem.size();
184
185 // Calculate scale factor to get uniform font size
186 GLfloat scaledFontSize = 0.05f + m_drawer->font().pointSizeF() / 500.0f;
187 GLfloat scaleFactor = scaledFontSize / (GLfloat)textureSize.height();
188
189 // Position label
190 QVector3D labelAlign(0.0f, 1.0f * scaledFontSize + 0.05f, 0.0f);
191 modelMatrixLabel.translate(vector: m_position + labelAlign);
192
193 // Position the label towards the camera
194 float camRotationsX = camera->xRotation();
195 float camRotationsY = camera->yRotation();
196 if (!m_cachedIsSlicingActivated) {
197 modelMatrixLabel.rotate(angle: -camRotationsX, x: 0.0f, y: 1.0f, z: 0.0f);
198 modelMatrixLabel.rotate(angle: -camRotationsY, x: 1.0f, y: 0.0f, z: 0.0f);
199 }
200
201 // Scale label based on text size
202 modelMatrixLabel.scale(vector: QVector3D((GLfloat)textureSize.width() * scaleFactor,
203 scaledFontSize,
204 0.0f));
205
206 // Make label to be always on top
207 glDisable(GL_DEPTH_TEST);
208
209 // Make label transparent
210 glEnable(GL_BLEND);
211 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
212
213 m_labelShader->bind();
214
215 QMatrix4x4 MVPMatrix;
216
217 // Set shader bindings
218 MVPMatrix = projectionMatrix * viewMatrix * modelMatrixLabel;
219 m_labelShader->setUniformValue(uniform: m_labelShader->MVP(), value: MVPMatrix);
220
221 // Draw the object
222 m_drawer->drawObject(shader: m_labelShader, object: m_labelObj, textureId: m_labelItem.textureId());
223
224 // Release shader
225 glUseProgram(program: 0);
226
227 // Disable transparency
228 glDisable(GL_BLEND);
229
230 // Depth test back to normal
231 glEnable(GL_DEPTH_TEST);
232}
233
234void SelectionPointer::setPosition(const QVector3D &position)
235{
236 m_position = position;
237}
238
239void SelectionPointer::updateSliceData(bool sliceActivated, GLfloat autoScaleAdjustment)
240{
241 m_cachedIsSlicingActivated = sliceActivated;
242 m_autoScaleAdjustment = autoScaleAdjustment;
243}
244
245void SelectionPointer::setHighlightColor(const QVector4D &colorVector)
246{
247 m_highlightColor = colorVector;
248}
249
250void SelectionPointer::setRotation(const QQuaternion &rotation)
251{
252 m_rotation = rotation;
253}
254
255void SelectionPointer::setLabel(const QString &label, bool themeChange)
256{
257 if (themeChange || m_label != label) {
258 m_label = label;
259 m_drawer->generateLabelItem(item&: m_labelItem, text: m_label);
260 }
261}
262
263void SelectionPointer::setPointerObject(ObjectHelper *object)
264{
265 m_pointObj = object;
266}
267
268void SelectionPointer::setLabelObject(ObjectHelper *object)
269{
270 m_labelObj = object;
271}
272
273void SelectionPointer::handleDrawerChange()
274{
275 m_cachedTheme = m_drawer->theme();
276 setLabel(label: m_label, themeChange: true);
277}
278
279void SelectionPointer::updateBoundingRect(const QRect &rect)
280{
281 m_mainViewPort = rect;
282}
283
284void SelectionPointer::initShaders()
285{
286 // The shader for printing the text label
287 if (m_labelShader)
288 delete m_labelShader;
289 m_labelShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexLabel"),
290 QStringLiteral(":/shaders/fragmentLabel"));
291 m_labelShader->initialize();
292
293 // The shader for the small point ball
294 if (m_pointShader)
295 delete m_pointShader;
296
297 if (Utils::isOpenGLES()) {
298 m_pointShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"),
299 QStringLiteral(":/shaders/fragmentES2"));
300 } else {
301 m_pointShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"),
302 QStringLiteral(":/shaders/fragment"));
303 }
304
305 m_pointShader->initialize();
306}
307
308QT_END_NAMESPACE_DATAVISUALIZATION
309

source code of qtdatavis3d/src/datavisualization/engine/selectionpointer.cpp