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

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