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

source code of qtdatavis3d/src/datavisualization/utils/camerahelper.cpp