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 "camerahelper_p.h" |
31 | |
32 | #include <QtCore/qmath.h> |
33 | #include <QtGui/QMatrix4x4> |
34 | |
35 | QT_BEGIN_NAMESPACE_DATAVISUALIZATION |
36 | |
37 | CameraHelper::CameraHelper(QObject *parent) : |
38 | QObject(parent), |
39 | m_position(0, 0.25, 3), |
40 | m_target(0, 0, 0), |
41 | m_up(0, 1, 0), |
42 | m_previousMousePos(0,0), |
43 | m_xRotation(0), |
44 | m_yRotation(0), |
45 | m_defaultXRotation(0), |
46 | m_defaultYRotation(0), |
47 | m_rotationSpeed(100) |
48 | { |
49 | } |
50 | |
51 | CameraHelper::~CameraHelper() |
52 | { |
53 | } |
54 | |
55 | void CameraHelper::setRotationSpeed(int speed) |
56 | { |
57 | // increase for faster rotation |
58 | m_rotationSpeed = speed; |
59 | } |
60 | |
61 | void CameraHelper::setCameraRotation(const QPointF &rotation) |
62 | { |
63 | m_xRotation = rotation.x(); |
64 | m_defaultXRotation = m_xRotation; |
65 | m_yRotation = rotation.y(); |
66 | m_defaultYRotation = m_yRotation; |
67 | } |
68 | |
69 | void CameraHelper::setDefaultCameraOrientation(const QVector3D &defaultPosition, |
70 | const QVector3D &defaultTarget, |
71 | const QVector3D &defaultUp) |
72 | { |
73 | m_position = defaultPosition; |
74 | m_target = defaultTarget; |
75 | m_up = defaultUp; |
76 | } |
77 | |
78 | QMatrix4x4 CameraHelper::calculateViewMatrix(const QPoint &mousePos, int zoom, |
79 | int screenWidth, int screenHeight, bool showUnder) |
80 | { |
81 | QMatrix4x4 viewMatrix; |
82 | GLfloat lowerLimit = 0.0f; |
83 | |
84 | if (showUnder) |
85 | lowerLimit = -90.0f; |
86 | |
87 | // Calculate mouse movement since last frame |
88 | GLfloat mouseMoveX = GLfloat(m_previousMousePos.x() - mousePos.x()) |
89 | / (screenWidth / m_rotationSpeed); |
90 | GLfloat mouseMoveY = GLfloat(m_previousMousePos.y() - mousePos.y()) |
91 | / (screenHeight / m_rotationSpeed); |
92 | // Apply to rotations |
93 | m_xRotation -= mouseMoveX; |
94 | m_yRotation -= mouseMoveY; |
95 | // Reset at 360 in x and limit to 0...90 in y |
96 | if (qAbs(t: m_xRotation) >= 360.0f) |
97 | m_xRotation = 0.0f; |
98 | if (m_yRotation >= 90.0f) |
99 | m_yRotation = 90.0f; |
100 | else if (m_yRotation <= lowerLimit) |
101 | m_yRotation = lowerLimit; |
102 | |
103 | // Apply to view matrix |
104 | viewMatrix.lookAt(eye: m_position, center: m_target, up: m_up); |
105 | // Compensate for translation (if m_target is off origin) |
106 | viewMatrix.translate(x: m_target.x(), y: m_target.y(), z: m_target.z()); |
107 | // Apply rotations |
108 | // Handle x and z rotation when y -angle is other than 0 |
109 | viewMatrix.rotate(angle: m_xRotation, x: 0, y: qCos(v: qDegreesToRadians(degrees: m_yRotation)), |
110 | z: qSin(v: qDegreesToRadians(degrees: m_yRotation))); |
111 | // y rotation is always "clean" |
112 | viewMatrix.rotate(angle: m_yRotation, x: 1.0f, y: 0.0f, z: 0.0f); |
113 | // handle zoom by scaling |
114 | viewMatrix.scale(factor: (GLfloat)zoom / 100.0f); |
115 | // Compensate for translation (if m_target is off origin) |
116 | viewMatrix.translate(x: -m_target.x(), y: -m_target.y(), z: -m_target.z()); |
117 | |
118 | m_previousMousePos = mousePos; |
119 | return viewMatrix; |
120 | } |
121 | |
122 | QVector3D CameraHelper::calculateLightPosition(const QVector3D &lightPosition, |
123 | GLfloat fixedRotation, GLfloat distanceModifier) |
124 | { |
125 | // Move light with camera |
126 | QVector3D newLightPosition; |
127 | GLfloat radiusFactor = lightPosition.z() * (1.5f + distanceModifier); // for making sure light is outside the scene at its lowest point |
128 | GLfloat xAngle; |
129 | GLfloat yAngle; |
130 | if (!fixedRotation) { |
131 | xAngle = qDegreesToRadians(degrees: m_xRotation); |
132 | yAngle = qDegreesToRadians(degrees: m_yRotation); |
133 | } else { |
134 | xAngle = qDegreesToRadians(degrees: fixedRotation); |
135 | yAngle = 0; |
136 | } |
137 | GLfloat radius = (radiusFactor + lightPosition.y()); // set radius to match the highest height of the light |
138 | GLfloat zPos = radius * qCos(v: xAngle) * qCos(v: yAngle); |
139 | GLfloat xPos = radius * qSin(v: xAngle) * qCos(v: yAngle); |
140 | GLfloat yPos = (radiusFactor + lightPosition.y()) * qSin(v: yAngle); |
141 | // Keep light in the set position in relation to camera |
142 | newLightPosition = QVector3D(-xPos + lightPosition.x(), |
143 | yPos + lightPosition.y(), |
144 | zPos + lightPosition.z()); |
145 | return newLightPosition; |
146 | } |
147 | |
148 | void CameraHelper::updateMousePos(const QPoint &mousePos) |
149 | { |
150 | m_previousMousePos = mousePos; |
151 | // if mouse position is set to (0, 0), reset rotations |
152 | if (QPoint(0, 0) == mousePos) { |
153 | m_xRotation = m_defaultXRotation; |
154 | m_yRotation = m_defaultYRotation; |
155 | } |
156 | } |
157 | |
158 | QPointF CameraHelper::getCameraRotations() |
159 | { |
160 | QPointF rotations(m_xRotation, m_yRotation); |
161 | return rotations; |
162 | } |
163 | |
164 | void CameraHelper::setCameraPreset(Q3DCamera::CameraPreset preset) |
165 | { |
166 | switch (preset) { |
167 | case Q3DCamera::CameraPresetFrontLow: { |
168 | CameraHelper::setCameraRotation(QPointF(0.0f, 0.0f)); |
169 | break; |
170 | } |
171 | case Q3DCamera::CameraPresetFront: { |
172 | CameraHelper::setCameraRotation(QPointF(0.0f, 22.5f)); |
173 | break; |
174 | } |
175 | case Q3DCamera::CameraPresetFrontHigh: { |
176 | CameraHelper::setCameraRotation(QPointF(0.0f, 45.0f)); |
177 | break; |
178 | } |
179 | case Q3DCamera::CameraPresetLeftLow: { |
180 | CameraHelper::setCameraRotation(QPointF(90.0f, 0.0f)); |
181 | break; |
182 | } |
183 | case Q3DCamera::CameraPresetLeft: { |
184 | CameraHelper::setCameraRotation(QPointF(90.0f, 22.5f)); |
185 | break; |
186 | } |
187 | case Q3DCamera::CameraPresetLeftHigh: { |
188 | CameraHelper::setCameraRotation(QPointF(90.0f, 45.0f)); |
189 | break; |
190 | } |
191 | case Q3DCamera::CameraPresetRightLow: { |
192 | CameraHelper::setCameraRotation(QPointF(-90.0f, 0.0f)); |
193 | break; |
194 | } |
195 | case Q3DCamera::CameraPresetRight: { |
196 | CameraHelper::setCameraRotation(QPointF(-90.0f, 22.5f)); |
197 | break; |
198 | } |
199 | case Q3DCamera::CameraPresetRightHigh: { |
200 | CameraHelper::setCameraRotation(QPointF(-90.0f, 45.0f)); |
201 | break; |
202 | } |
203 | case Q3DCamera::CameraPresetBehindLow: { |
204 | CameraHelper::setCameraRotation(QPointF(180.0f, 0.0f)); |
205 | break; |
206 | } |
207 | case Q3DCamera::CameraPresetBehind: { |
208 | CameraHelper::setCameraRotation(QPointF(180.0f, 22.5f)); |
209 | break; |
210 | } |
211 | case Q3DCamera::CameraPresetBehindHigh: { |
212 | CameraHelper::setCameraRotation(QPointF(180.0f, 45.0f)); |
213 | break; |
214 | } |
215 | case Q3DCamera::CameraPresetIsometricLeft: { |
216 | CameraHelper::setCameraRotation(QPointF(45.0f, 22.5f)); |
217 | break; |
218 | } |
219 | case Q3DCamera::CameraPresetIsometricLeftHigh: { |
220 | CameraHelper::setCameraRotation(QPointF(45.0f, 45.0f)); |
221 | break; |
222 | } |
223 | case Q3DCamera::CameraPresetIsometricRight: { |
224 | CameraHelper::setCameraRotation(QPointF(-45.0f, 22.5f)); |
225 | break; |
226 | } |
227 | case Q3DCamera::CameraPresetIsometricRightHigh: { |
228 | CameraHelper::setCameraRotation(QPointF(-45.0f, 45.0f)); |
229 | break; |
230 | } |
231 | case Q3DCamera::CameraPresetDirectlyAbove: { |
232 | CameraHelper::setCameraRotation(QPointF(0.0f, 90.0f)); |
233 | break; |
234 | } |
235 | case Q3DCamera::CameraPresetDirectlyAboveCW45: { |
236 | CameraHelper::setCameraRotation(QPointF(-45.0f, 90.0f)); |
237 | break; |
238 | } |
239 | case Q3DCamera::CameraPresetDirectlyAboveCCW45: { |
240 | CameraHelper::setCameraRotation(QPointF(45.0f, 90.0f)); |
241 | break; |
242 | } |
243 | case Q3DCamera::CameraPresetFrontBelow: { |
244 | CameraHelper::setCameraRotation(QPointF(0.0f, -45.0f)); |
245 | break; |
246 | } |
247 | case Q3DCamera::CameraPresetLeftBelow: { |
248 | CameraHelper::setCameraRotation(QPointF(90.0f, -45.0f)); |
249 | break; |
250 | } |
251 | case Q3DCamera::CameraPresetRightBelow: { |
252 | CameraHelper::setCameraRotation(QPointF(-90.0f, -45.0f)); |
253 | break; |
254 | } |
255 | case Q3DCamera::CameraPresetBehindBelow: { |
256 | CameraHelper::setCameraRotation(QPointF(180.0f, -45.0f)); |
257 | break; |
258 | } |
259 | case Q3DCamera::CameraPresetDirectlyBelow: { |
260 | CameraHelper::setCameraRotation(QPointF(0.0f, -90.0f)); |
261 | break; |
262 | } |
263 | default: |
264 | break; |
265 | } |
266 | } |
267 | |
268 | QT_END_NAMESPACE_DATAVISUALIZATION |
269 | |