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
37 QT_BEGIN_NAMESPACE_DATAVISUALIZATION
38
39 const GLfloat sliceUnits = 2.5;
40
SelectionPointer(Drawer * drawer)41 SelectionPointer::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(m_drawer, &Drawer::drawerChanged,
56 this, &SelectionPointer::handleDrawerChange);
57 }
58
~SelectionPointer()59 SelectionPointer::~SelectionPointer()
60 {
61 delete m_labelShader;
62 delete m_pointShader;
63 delete m_textureHelper;
64 }
65
initializeOpenGL()66 void SelectionPointer::initializeOpenGL()
67 {
68 initializeOpenGLFunctions();
69
70 m_textureHelper = new TextureHelper();
71 m_drawer->initializeOpenGL();
72
73 initShaders();
74 }
75
updateScene(Q3DScene * scene)76 void SelectionPointer::updateScene(Q3DScene *scene)
77 {
78 m_cachedScene = scene;
79 }
80
renderSelectionPointer(GLuint defaultFboHandle,bool useOrtho)81 void SelectionPointer::renderSelectionPointer(GLuint defaultFboHandle, bool useOrtho)
82 {
83 Q_UNUSED(defaultFboHandle)
84
85 glViewport(m_mainViewPort.x(), m_mainViewPort.y(),
86 m_mainViewPort.width(), 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(QVector3D(0.0f, 0.0f, 1.0f), zeroVector, upVector);
99 projectionMatrix.ortho(-sliceUnitsScaled * viewPortRatio, sliceUnitsScaled * viewPortRatio,
100 -sliceUnitsScaled, sliceUnitsScaled,
101 -1.0f, 4.0f);
102 } else if (useOrtho) {
103 viewMatrix = camera->d_ptr->viewMatrix();
104 GLfloat orthoRatio = 2.0f;
105 projectionMatrix.ortho(-viewPortRatio * orthoRatio, viewPortRatio * orthoRatio,
106 -orthoRatio, orthoRatio,
107 0.0f, 100.0f);
108 } else {
109 viewMatrix = camera->d_ptr->viewMatrix();
110 projectionMatrix.perspective(45.0f, viewPortRatio, 0.1f, 100.0f);
111 }
112
113 QMatrix4x4 modelMatrix;
114 QMatrix4x4 MVPMatrix;
115
116 // Position the pointer ball
117 modelMatrix.translate(m_position);
118
119 if (!m_rotation.isIdentity()) {
120 modelMatrix.rotate(m_rotation);
121 itModelMatrix.rotate(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(scaleVector);
127 itModelMatrix.scale(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(m_pointShader->lightP(), lightPos);
138 m_pointShader->setUniformValue(m_pointShader->view(), viewMatrix);
139 m_pointShader->setUniformValue(m_pointShader->model(), modelMatrix);
140 m_pointShader->setUniformValue(m_pointShader->nModel(), itModelMatrix.inverted().transposed());
141 m_pointShader->setUniformValue(m_pointShader->color(), m_highlightColor);
142 m_pointShader->setUniformValue(m_pointShader->MVP(), MVPMatrix);
143 m_pointShader->setUniformValue(m_pointShader->ambientS(),
144 m_cachedTheme->ambientLightStrength());
145 m_pointShader->setUniformValue(m_pointShader->lightS(), m_cachedTheme->lightStrength() * 2.0f);
146 m_pointShader->setUniformValue(m_pointShader->lightColor(),
147 Utils::vectorFromColor(m_cachedTheme->lightColor()));
148
149 m_drawer->drawObject(m_pointShader, m_pointObj);
150 }
151
renderSelectionLabel(GLuint defaultFboHandle,bool useOrtho)152 void SelectionPointer::renderSelectionLabel(GLuint defaultFboHandle, bool useOrtho)
153 {
154 Q_UNUSED(defaultFboHandle)
155
156 glViewport(m_mainViewPort.x(), m_mainViewPort.y(),
157 m_mainViewPort.width(), 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(QVector3D(0.0f, 0.0f, 1.0f), zeroVector, upVector);
169 projectionMatrix.ortho(-sliceUnitsScaled * viewPortRatio, sliceUnitsScaled * viewPortRatio,
170 -sliceUnitsScaled, sliceUnitsScaled,
171 -1.0f, 4.0f);
172 } else if (useOrtho) {
173 viewMatrix = camera->d_ptr->viewMatrix();
174 GLfloat orthoRatio = 2.0f;
175 projectionMatrix.ortho(-viewPortRatio * orthoRatio, viewPortRatio * orthoRatio,
176 -orthoRatio, orthoRatio,
177 0.0f, 100.0f);
178 } else {
179 viewMatrix = camera->d_ptr->viewMatrix();
180 projectionMatrix.perspective(45.0f, viewPortRatio, 0.1f, 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(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(-camRotationsX, 0.0f, 1.0f, 0.0f);
198 modelMatrixLabel.rotate(-camRotationsY, 1.0f, 0.0f, 0.0f);
199 }
200
201 // Scale label based on text size
202 modelMatrixLabel.scale(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(m_labelShader->MVP(), MVPMatrix);
220
221 // Draw the object
222 m_drawer->drawObject(m_labelShader, m_labelObj, m_labelItem.textureId());
223
224 // Release shader
225 glUseProgram(0);
226
227 // Disable transparency
228 glDisable(GL_BLEND);
229
230 // Depth test back to normal
231 glEnable(GL_DEPTH_TEST);
232 }
233
setPosition(const QVector3D & position)234 void SelectionPointer::setPosition(const QVector3D &position)
235 {
236 m_position = position;
237 }
238
updateSliceData(bool sliceActivated,GLfloat autoScaleAdjustment)239 void SelectionPointer::updateSliceData(bool sliceActivated, GLfloat autoScaleAdjustment)
240 {
241 m_cachedIsSlicingActivated = sliceActivated;
242 m_autoScaleAdjustment = autoScaleAdjustment;
243 }
244
setHighlightColor(const QVector4D & colorVector)245 void SelectionPointer::setHighlightColor(const QVector4D &colorVector)
246 {
247 m_highlightColor = colorVector;
248 }
249
setRotation(const QQuaternion & rotation)250 void SelectionPointer::setRotation(const QQuaternion &rotation)
251 {
252 m_rotation = rotation;
253 }
254
setLabel(const QString & label,bool themeChange)255 void SelectionPointer::setLabel(const QString &label, bool themeChange)
256 {
257 if (themeChange || m_label != label) {
258 m_label = label;
259 m_drawer->generateLabelItem(m_labelItem, m_label);
260 }
261 }
262
setPointerObject(ObjectHelper * object)263 void SelectionPointer::setPointerObject(ObjectHelper *object)
264 {
265 m_pointObj = object;
266 }
267
setLabelObject(ObjectHelper * object)268 void SelectionPointer::setLabelObject(ObjectHelper *object)
269 {
270 m_labelObj = object;
271 }
272
handleDrawerChange()273 void SelectionPointer::handleDrawerChange()
274 {
275 m_cachedTheme = m_drawer->theme();
276 setLabel(m_label, true);
277 }
278
updateBoundingRect(const QRect & rect)279 void SelectionPointer::updateBoundingRect(const QRect &rect)
280 {
281 m_mainViewPort = rect;
282 }
283
initShaders()284 void 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
308 QT_END_NAMESPACE_DATAVISUALIZATION
309