1// Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qorbitcameracontroller.h"
5#include "qorbitcameracontroller_p.h"
6
7#include <Qt3DRender/QCamera>
8
9QT_BEGIN_NAMESPACE
10
11namespace Qt3DExtras {
12
13QOrbitCameraControllerPrivate::QOrbitCameraControllerPrivate()
14 : m_zoomInLimit(2.0f)
15 , m_upVector(0.0f, 1.0f, 0.0f)
16 , m_inverseXTranslate(false)
17 , m_inverseYTranslate(false)
18 , m_inversePan(false)
19 , m_inverseTilt(false)
20 , m_zoomTranslateViewCenter(true)
21{}
22
23/*!
24 \class Qt3DExtras::QOrbitCameraController
25 \ingroup qt3d-extras-cameracontrollers
26 \brief The QOrbitCameraController class allows controlling the scene camera along orbital path.
27 \inmodule Qt3DExtras
28 \since 5.7
29 \inherits Qt3DCore::QEntity
30
31 The controls are:
32 \table
33 \header
34 \li Input
35 \li Action
36 \row
37 \li Left mouse button
38 \li While the left mouse button is pressed, mouse movement along x-axis moves the camera
39 left and right and movement along y-axis moves it up and down.
40 \row
41 \li Right mouse button
42 \li While the right mouse button is pressed, mouse movement along x-axis pans the camera
43 around the camera view center and movement along y-axis tilts it around the camera
44 view center.
45 \row
46 \li Both left and right mouse button
47 \li While both the left and the right mouse button are pressed, mouse movement along y-axis
48 zooms the camera in and out without changing the view center.
49 \row
50 \li Mouse scroll wheel
51 \li Zooms the camera in and out without changing the view center.
52 \row
53 \li Arrow keys
54 \li Move the camera vertically and horizontally relative to camera viewport.
55 \row
56 \li Page up and page down keys
57 \li Move the camera forwards and backwards.
58 \row
59 \li Shift key
60 \li Changes the behavior of the up and down arrow keys to zoom the camera in and out
61 without changing the view center. The other movement keys are disabled.
62 \row
63 \li Alt key
64 \li Changes the behovior of the arrow keys to pan and tilt the camera around the view
65 center. Disables the page up and page down keys.
66 \row
67 \li Escape
68 \li Moves the camera so that entire scene is visible in the camera viewport.
69 \endtable
70*/
71
72QOrbitCameraController::QOrbitCameraController(Qt3DCore::QNode *parent)
73 : QOrbitCameraController(*new QOrbitCameraControllerPrivate, parent)
74{
75}
76
77/*! \internal
78 */
79QOrbitCameraController::QOrbitCameraController(QOrbitCameraControllerPrivate &dd, Qt3DCore::QNode *parent)
80 : QAbstractCameraController(dd, parent)
81{
82}
83
84QOrbitCameraController::~QOrbitCameraController()
85{
86}
87
88/*!
89 \property Qt3DExtras::QOrbitCameraController::zoomInLimit
90
91 Holds the current zoom-in limit. The zoom-in limit determines how close to the view center
92 the camera can be zoomed.
93*/
94float QOrbitCameraController::zoomInLimit() const
95{
96 Q_D(const QOrbitCameraController);
97 return d->m_zoomInLimit;
98}
99
100void QOrbitCameraController::setZoomInLimit(float zoomInLimit)
101{
102 Q_D(QOrbitCameraController);
103 if (d->m_zoomInLimit != zoomInLimit) {
104 d->m_zoomInLimit = zoomInLimit;
105 emit zoomInLimitChanged();
106 }
107}
108
109QVector3D QOrbitCameraController::upVector() const {
110 Q_D(const QOrbitCameraController);
111 return d->m_upVector;
112}
113
114void QOrbitCameraController::setUpVector(const QVector3D& upVector)
115{
116 Q_D(QOrbitCameraController);
117 if (d->m_upVector != upVector) {
118 d->m_upVector = upVector;
119 emit upVectorChanged(upVector: d->m_upVector);
120 }
121}
122
123bool QOrbitCameraController::inverseXTranslate() const
124{
125 Q_D(const QOrbitCameraController);
126 return d->m_inverseXTranslate;
127}
128
129void QOrbitCameraController::setInverseXTranslate(bool isInverse)
130{
131 Q_D(QOrbitCameraController);
132 if (d->m_inverseXTranslate != isInverse) {
133 d->m_inverseXTranslate = isInverse;
134 emit inverseXTranslateChanged(isInverse: d->m_inverseXTranslate);
135 }
136}
137
138bool QOrbitCameraController::inverseYTranslate() const
139{
140 Q_D(const QOrbitCameraController);
141 return d->m_inverseYTranslate;
142}
143
144void QOrbitCameraController::setInverseYTranslate(bool isInverse)
145{
146 Q_D(QOrbitCameraController);
147 if (d->m_inverseYTranslate != isInverse) {
148 d->m_inverseYTranslate = isInverse;
149 emit inverseYTranslateChanged(isInverse: d->m_inverseYTranslate);
150 }
151}
152
153bool QOrbitCameraController::inversePan() const
154{
155 Q_D(const QOrbitCameraController);
156 return d->m_inversePan;
157}
158
159void QOrbitCameraController::setInversePan(bool isInverse)
160{
161 Q_D(QOrbitCameraController);
162 if (d->m_inversePan != isInverse) {
163 d->m_inversePan = isInverse;
164 emit inversePanChanged(isInverse: d->m_inversePan);
165 }
166}
167
168bool QOrbitCameraController::inverseTilt() const
169{
170 Q_D(const QOrbitCameraController);
171 return d->m_inverseTilt;
172}
173
174void QOrbitCameraController::setInverseTilt(bool isInverse)
175{
176 Q_D(QOrbitCameraController);
177 if (d->m_inverseTilt != isInverse) {
178 d->m_inverseTilt = isInverse;
179 emit inverseTiltChanged(isInverse: d->m_inverseTilt);
180 }
181}
182
183bool QOrbitCameraController::zoomTranslateViewCenter() const
184{
185 Q_D(const QOrbitCameraController);
186 return d->m_zoomTranslateViewCenter;
187}
188
189void QOrbitCameraController::setZoomTranslateViewCenter(bool isTranslate)
190{
191 Q_D(QOrbitCameraController);
192 if (d->m_zoomTranslateViewCenter != isTranslate) {
193 d->m_zoomTranslateViewCenter = isTranslate;
194 emit zoomTranslateViewCenterChanged(isTranslate: d->m_zoomTranslateViewCenter);
195 }
196}
197
198inline float clampInputs(float input1, float input2)
199{
200 float axisValue = input1 + input2;
201 return (axisValue < -1) ? -1 : (axisValue > 1) ? 1 : axisValue;
202}
203
204inline float zoomDistance(QVector3D firstPoint, QVector3D secondPoint)
205{
206 return (secondPoint - firstPoint).lengthSquared();
207}
208
209void QOrbitCameraController::moveCamera(const QAbstractCameraController::InputState &state, float dt)
210{
211 Q_D(QOrbitCameraController);
212
213 Qt3DRender::QCamera *theCamera = camera();
214
215 if (theCamera == nullptr)
216 return;
217
218 // Mouse input
219 if (state.leftMouseButtonActive) {
220 if (state.rightMouseButtonActive) {
221 if ( zoomDistance(firstPoint: camera()->position(), secondPoint: theCamera->viewCenter()) > d->m_zoomInLimit * d->m_zoomInLimit) {
222 // Dolly up to limit
223 theCamera->translate(vLocal: QVector3D(0, 0, state.ryAxisValue), option: theCamera->DontTranslateViewCenter);
224 } else {
225 theCamera->translate(vLocal: QVector3D(0, 0, -0.5), option: theCamera->DontTranslateViewCenter);
226 }
227 } else {
228 // Translate
229 theCamera->translate(vLocal: QVector3D((d->m_inverseXTranslate ? -1.0f : 1.0f) * clampInputs(input1: state.rxAxisValue, input2: state.txAxisValue) * linearSpeed(),
230 (d->m_inverseYTranslate ? -1.0f : 1.0f) * clampInputs(input1: state.ryAxisValue, input2: state.tyAxisValue) * linearSpeed(),
231 0) * dt);
232 }
233 return;
234 }
235 else if (state.rightMouseButtonActive) {
236 // Orbit
237 theCamera->panAboutViewCenter(angle: (d->m_inversePan ? -1.0f : 1.0f) * (state.rxAxisValue * lookSpeed()) * dt, axis: d->m_upVector);
238 theCamera->tiltAboutViewCenter(angle: (d->m_inverseTilt ? -1.0f : 1.0f) * (state.ryAxisValue * lookSpeed()) * dt);
239 }
240
241 // Keyboard Input
242 if (state.altKeyActive) {
243 // Orbit
244 theCamera->panAboutViewCenter(angle: (state.txAxisValue * lookSpeed()) * dt, axis: d->m_upVector);
245 theCamera->tiltAboutViewCenter(angle: (state.tyAxisValue * lookSpeed()) * dt);
246 } else if (state.shiftKeyActive) {
247 if (zoomDistance(firstPoint: camera()->position(), secondPoint: theCamera->viewCenter()) > d->m_zoomInLimit * d->m_zoomInLimit) {
248 // Dolly
249 theCamera->translate(vLocal: QVector3D(0, 0, state.tzAxisValue * linearSpeed() * dt), option: theCamera->DontTranslateViewCenter);
250 } else {
251 theCamera->translate(vLocal: QVector3D(0, 0, -0.5), option: theCamera->DontTranslateViewCenter);
252 }
253 } else {
254 // Translate
255 theCamera->translate(vLocal: QVector3D(clampInputs(input1: state.leftMouseButtonActive ? state.rxAxisValue : 0, input2: state.txAxisValue) * linearSpeed(),
256 clampInputs(input1: state.leftMouseButtonActive ? state.ryAxisValue : 0, input2: state.tyAxisValue) * linearSpeed(),
257 state.tzAxisValue * linearSpeed()) * dt,
258 option: d->m_zoomTranslateViewCenter ? theCamera->TranslateViewCenter : theCamera->DontTranslateViewCenter);
259 }
260}
261
262} // Qt3DExtras
263
264QT_END_NAMESPACE
265
266#include "moc_qorbitcameracontroller.cpp"
267

source code of qt3d/src/extras/defaults/qorbitcameracontroller.cpp