1/****************************************************************************
2**
3** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt3D module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
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 Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qcamera.h"
41#include "qcamera_p.h"
42
43#include <QtMath>
44
45QT_BEGIN_NAMESPACE
46
47namespace Qt3DRender {
48
49/*!
50 * \internal
51 */
52QCameraPrivate::QCameraPrivate()
53 : Qt3DCore::QEntityPrivate()
54 , m_position(0.0f, 0.0f, 0.0f)
55 , m_viewCenter(0.0f, 0.0f, -100.0f)
56 , m_upVector(0.0f, 1.0f, 0.0f)
57 , m_cameraToCenter(m_viewCenter - m_position)
58 , m_viewMatrixDirty(false)
59 , m_lens(new QCameraLens())
60 , m_transform(new Qt3DCore::QTransform())
61{
62 updateViewMatrixAndTransform(doEmit: false);
63}
64
65void QCameraPrivate::updateViewMatrixAndTransform(bool doEmit)
66{
67 Q_Q(QCamera);
68
69 const QVector3D viewDirection = (m_viewCenter - m_position).normalized();
70
71 QMatrix4x4 transformMatrix;
72 transformMatrix.translate(vector: m_position);
73
74 // Negative viewDirection because OpenGL convention is looking down -Z
75 transformMatrix.rotate(quaternion: QQuaternion::fromDirection(direction: -viewDirection, up: m_upVector.normalized()));
76
77 m_transform->setMatrix(transformMatrix);
78
79 QMatrix4x4 viewMatrix;
80 viewMatrix.lookAt(eye: m_position, center: m_viewCenter, up: m_upVector);
81 m_viewMatrix = viewMatrix;
82 if (doEmit)
83 emit q->viewMatrixChanged();
84}
85
86/*!
87 * \class Qt3DRender::QCamera
88 * \inheaderfile Qt3DRender/QCamera
89 * \brief The QCamera class defines a view point through which the scene will be
90 * rendered.
91 * \inmodule Qt3DRender
92 * \since 5.5
93 */
94
95/*!
96 * \qmltype Camera
97 * \instantiates Qt3DRender::QCamera
98 * \inherits Entity
99 * \inqmlmodule Qt3D.Render
100 * \since 5.5
101 * \brief Defines a view point through which the scene will be rendered.
102 */
103
104/*!
105 * \enum Qt3DRender::QCamera::CameraTranslationOption
106 *
107 * This enum specifies how camera view center is translated
108 * \value TranslateViewCenter Translate the view center causing the view direction to remain the same
109 * \value DontTranslateViewCenter Don't translate the view center causing the view direction to change
110 */
111
112/*!
113 * \qmlmethod quaternion Qt3D.Render::Camera::tiltRotation(real angle)
114 *
115 * Returns the calculated tilt rotation in relation to the \a angle in degrees taken in
116 * to adjust the camera's tilt or up/down rotation on the X axis.
117 */
118
119/*!
120 * \qmlmethod quaternion Qt3D.Render::Camera::panRotation(real angle)
121 *
122 * Returns the calculated pan rotation in relation to the \a angle in degrees taken in
123 * to adjust the camera's pan or left/right rotation on the Y axis.
124 */
125
126/*!
127 * \qmlmethod quaternion Qt3D.Render::Camera::rollRotation(real angle)
128 *
129 * Returns the calculated roll rotation in relation to the \a angle in degrees taken in
130 * to adjust the camera's roll or lean left/right rotation on the Z axis.
131 */
132
133/*!
134 * \qmlmethod quaternion Qt3D.Render::Camera::rotation(real angle, vector3d axis)
135 *
136 * Returns the calculated rotation in relation to the \a angle in degrees and
137 * chosen \a axis taken in.
138 */
139
140/*!
141 * \qmlmethod void Qt3D.Render::Camera::translate(vector3d vLocal, enumeration option)
142 *
143 * Translates the camera's position and its view vector by \a vLocal in local coordinates.
144 * The \a option allows for toggling whether the view center should be translated.
145 * \list
146 * \li Camera.TranslateViewCenter
147 * \li Camera.DontTranslateViewCenter
148 * \endlist
149 * \sa Qt3DRender::QCamera::CameraTranslationOption
150 */
151
152/*!
153 * \qmlmethod void Qt3D.Render::Camera::translateWorld(vector3d vWorld, enumeration option)
154 *
155 * Translates the camera's position and its view vector by \a vWorld in world coordinates.
156 * The \a option allows for toggling whether the view center should be translated.
157 * \list
158 * \li Camera.TranslateViewCenter
159 * \li Camera.DontTranslateViewCenter
160 * \endlist
161 * \sa Qt3DRender::QCamera::CameraTranslationOption
162 */
163
164/*!
165 * \qmlmethod void Qt3D.Render::Camera::tilt(real angle)
166 *
167 * Adjusts the tilt angle of the camera by \a angle in degrees.
168 */
169
170/*!
171 * \qmlmethod void Qt3D.Render::Camera::pan(real angle)
172 *
173 * Adjusts the pan angle of the camera by \a angle in degrees.
174 */
175
176/*!
177 * \qmlmethod void Qt3D.Render::Camera::pan(real angle, vector3d axis)
178 *
179 * Adjusts the camera pan about view center by \a angle in degrees on \a axis.
180 */
181
182/*!
183 * \qmlmethod void Qt3D.Render::Camera::roll(real angle)
184 *
185 * Adjusts the camera roll by \a angle in degrees.
186 */
187
188/*!
189 * \qmlmethod void Qt3D.Render::Camera::tiltAboutViewCenter(real angle)
190 *
191 * Adjusts the camera tilt about view center by \a angle in degrees.
192 */
193
194/*!
195 * \qmlmethod void Qt3D.Render::Camera::panAboutViewCenter(real angle)
196 *
197 * Adjusts the camera pan about view center by \a angle in degrees.
198 */
199
200/*!
201 * \qmlmethod void Qt3D.Render::Camera::panAboutViewCenter(real angle, vector3d axis)
202 *
203 * Adjusts the camera pan about view center by \a angle in degrees on \a axis.
204 */
205
206/*!
207 * \qmlmethod void Qt3D.Render::Camera::rollAboutViewCenter(real angle)
208 *
209 * Adjusts the camera roll about view center by \a angle in degrees.
210 */
211
212/*!
213 * \qmlmethod void Qt3D.Render::Camera::rotate(quaternion q)
214 *
215 * Rotates the camera with the use of a Quaternion in \a q.
216 */
217
218/*!
219 * \qmlmethod void Qt3D.Render::Camera::rotateAboutViewCenter(quaternion q)
220 *
221 * Rotates the camera about the view center with the use of a Quaternion in \a q.
222 */
223
224/*!
225 * \qmlmethod void Qt3D.Render::Camera::viewAll()
226 *
227 * Rotates and moves the camera so that it's viewCenter is the center of the scene's bounding volume
228 * and the entire scene fits in the view port.
229 *
230 * \note Only works if the lens is in perspective or orthographic projection mode.
231 * \sa Qt3D.Render::Camera::projectionType
232 */
233
234/*!
235 * \qmlmethod void Qt3D.Render::Camera::viewEntity(Entity entity)
236 *
237 * Rotates and moves the camera so that it's viewCenter is the center of the entity's bounding volume
238 * and the entire \a entity fits in the view port.
239 *
240 * \note Only works if the lens is in perspective or orthographic projection mode.
241 * \sa Qt3D.Render::Camera::projectionType
242 */
243
244/*!
245 * \qmlmethod void Qt3D.Render::Camera::viewSphere(vector3d center, real radius)
246 *
247 * Rotates and moves the camera so that it's viewCenter is \a center
248 * and a sphere of \a radius fits in the view port.
249 *
250 * \note Only works if the lens is in perspective or orthographic projection mode.
251 * \sa Qt3D.Render::Camera::projectionType
252 */
253
254/*!
255 * \qmlproperty enumeration Qt3D.Render::Camera::projectionType
256 *
257 * Holds the type of the camera projection. The default value is
258 * CameraLens.PerspectiveProjection.
259 *
260 * \list
261 * \li CameraLens.OrthographicProjection - Parallel lines appear parallel. Objects appear
262 * the same size regardless of distance.
263 * \li CameraLens.PerspectiveProjection - Parallel lines appear to meet in the distance.
264 * Objects appear to shrink the farther they are from the camera.
265 * \li CameraLens.FrustumProjection
266 * \li CameraLens.CustomProjection
267 * \endlist
268 * \sa Qt3DRender::QCameraLens::ProjectionType
269 */
270
271/*!
272 * \qmlproperty real Qt3D.Render::Camera::nearPlane
273 * Holds the current camera near plane of the camera. Objects that
274 * are closer to the camera than the nearPlane will not be rendered.
275 */
276
277/*!
278 * \qmlproperty real Qt3D.Render::Camera::farPlane
279 * Holds the current camera far plane of the camera. Objects that
280 * are farther from the camera than the farPlane will not be rendered.
281 */
282
283/*!
284 * \qmlproperty Qt3DRender::QCameraLens QCamera::lens
285 * Holds the CameraLens component of the camera.
286 * \since 5.14
287 */
288
289/*!
290 * \qmlproperty Qt3DCore::QTransform QCamera::transform
291 * Holds the Transform component of the camera.
292 * \since 5.14
293 */
294
295/*!
296 * \qmlproperty real Qt3D.Render::Camera::fieldOfView
297 * Holds the current vertical field of view of the camera in degrees.
298 *
299 * Along with \l aspectRatio, this property determines how much of
300 * the scene is visible to the camera. In that respect you might
301 * think of it as analogous to choosing a wide angle (wide horizontal
302 * field of view) or telephoto (narrow horizontal field of view) lens,
303 * depending on how much of a scene you want to capture.
304 *
305 * fieldOfView is only relevant when \l projectionType is
306 * CameraLens.PerspectiveProjection.
307 */
308
309/*!
310 * \qmlproperty real Qt3D.Render::Camera::aspectRatio
311 * Holds the current aspect ratio of the camera.
312 */
313
314/*!
315 *\qmlproperty real Qt3D.Render::Camera::left
316 * Holds the current left of the camera.
317 *
318 * This property is only relevant when \l projectionType is
319 * CameraLens.OrthographicProjection.
320 */
321
322/*!
323 * \qmlproperty real Qt3D.Render::Camera::right
324 * Holds the current right of the camera.
325 *
326 * This property is only relevant when \l projectionType is
327 * CameraLens.OrthographicProjection.
328 */
329
330/*!
331 * \qmlproperty real Qt3D.Render::Camera::bottom
332 * Holds the current bottom of the camera.
333 *
334 * This property is only relevant when \l projectionType is
335 * CameraLens.OrthographicProjection.
336 */
337
338/*!
339 * \qmlproperty real Qt3D.Render::Camera::top
340 * Holds the current top of the camera.
341 *
342 * This property is only relevant when \l projectionType is
343 * CameraLens.OrthographicProjection.
344 */
345
346/*!
347 * \qmlproperty matrix4x4 Qt3D.Render::Camera::projectionMatrix
348 * Holds the current projection matrix of the camera.
349 */
350
351/*!
352 * \qmlproperty real Qt3D.Render::Camera::exposure
353 * Holds the current exposure of the camera.
354 *
355 * The default value is 0.0.
356 *
357 * The MetalRoughMaterial in Qt 3D Extras is currently the only provided
358 * material that makes use of camera exposure. Negative values will cause
359 * the material to be darker, and positive values will cause it to be lighter.
360 *
361 * Custom materials may choose to interpret the value differently.
362 */
363
364/*!
365 * \qmlproperty vector3d Qt3D.Render::Camera::position
366 * Holds the current position of the camera in coordinates relative to
367 * the parent entity.
368 */
369
370/*!
371 * \qmlproperty vector3d Qt3D.Render::Camera::upVector
372 * Holds the current up vector of the camera in coordinates relative to
373 * the parent entity.
374 *
375 * The up vector indicates which direction the top of the camera is
376 * facing. Think of taking a picture: after positioning yourself
377 * and pointing the camera at your target, you might rotate the camera
378 * left or right, giving you a portrait or landscape (or angled!)
379 * shot. upVector allows you to control this type of movement.
380 */
381
382/*!
383 * \qmlproperty vector3d Qt3D.Render::Camera::viewCenter
384 * Holds the current view center of the camera in coordinates relative to
385 * the parent entity.
386 *
387 * Intuitively, the viewCenter is the location the camera is pointing at.
388 */
389
390/*!
391 * \qmlproperty vector3d Qt3D.Render::Camera::viewVector
392 * Holds the camera's view vector in coordinates relative to
393 * the parent entity.
394 *
395 * This vector decribes the displacement from the camera (\l position)
396 * to its target (\l viewCenter).
397 * \readonly
398 */
399
400/*!
401 * \qmlproperty matrix4x4 Qt3D.Render::Camera::viewMatrix
402 * \deprecated
403 * Holds the camera's view matrix in coordinates relative
404 * to the parent entity.
405 * \readonly
406 */
407
408/*!
409 * \property QCamera::projectionType
410 *
411 * Holds the type of the camera projection. The default value is
412 * QCameraLens::PerspectiveProjection.
413 *
414 * \list
415 * \li QCameraLens::OrthographicProjection - Parallel lines appear parallel. Objects appear
416 * the same size regardless of distance.
417 * \li QCameraLens::PerspectiveProjection - Parallel lines appear to meet in the distance.
418 * Objects appear to shrink the farther they are from the camera.
419 * \li QCameraLens::FrustumProjection
420 * \li QCameraLens::CustomProjection
421 * \endlist
422 * \sa Qt3DRender::QCameraLens::ProjectionType
423 */
424
425/*!
426 * \property QCamera::nearPlane
427 * Holds the current camera near plane. Objects that are closer to the
428 * camera than the nearPlane will not be rendered.
429 */
430
431/*!
432 * \property QCamera::farPlane
433 * Holds the current camera far plane. Objects that are farther from the
434 * camera than the farPlane will not be rendered.
435 */
436
437/*!
438 * \property QCamera::lens
439 * Holds the Qt3DRender::QCameraLens component of the camera.
440 * \since 5.14
441 */
442
443/*!
444 * \property QCamera::transform
445 * Holds the Qt3DCore::QTransform component of the camera.
446 * \since 5.14
447 */
448
449/*!
450 * \property QCamera::fieldOfView
451 * Holds the current vertical field of view in degrees.
452 *
453 * Along with \l aspectRatio, this property determines how much of
454 * the scene is visible to the camera. In that respect you might
455 * think of it as analogous to choosing a wide angle (wide horizontal
456 * field of view) or telephoto (narrow horizontal field of view) lens
457 * depending on how much of a scene you want to capture.
458 *
459 * fieldOfView is only relevant when \l projectionType is
460 * QCameraLens::PerspectiveProjection.
461 */
462
463/*!
464 * \property QCamera::aspectRatio
465 * Holds the current aspect ratio.
466 */
467
468/*!
469 *\property QCamera::left
470 * Holds the current left of the camera.
471 *
472 * This property is only relevant when \l projectionType is
473 * QCameraLens::OrthographicProjection.
474 */
475
476/*!
477 * \property QCamera::right
478 * Holds the current right of the camera.
479 *
480 * This property is only relevant when \l projectionType is
481 * QCameraLens::OrthographicProjection.
482 */
483
484/*!
485 * \property QCamera::bottom
486 * Holds the current bottom of the camera.
487 *
488 * This property is only relevant when \l projectionType is
489 * QCameraLens::OrthographicProjection.
490 */
491
492/*!
493 * \property QCamera::top
494 * Holds the current top of the camera.
495 *
496 * This property is only relevant when \l projectionType is
497 * QCameraLens::OrthographicProjection.
498 */
499
500/*!
501 * \property QCamera::projectionMatrix
502 * Holds the current projection matrix of the camera.
503 */
504
505/*!
506 * \property QCamera::exposure
507 * Holds the current exposure of the camera.
508 *
509 * The default value is 0.0.
510 *
511 * The MetalRoughMaterial in Qt 3D Extras is currently the only provided
512 * material that makes use of camera exposure. Negative values will cause
513 * the material to be darker, and positive values will cause it to be lighter.
514 *
515 * Custom materials may choose to interpret the value differently.
516 */
517
518/*!
519 * \property QCamera::position
520 * Holds the camera's position in coordinates relative to
521 * the parent entity.
522 */
523
524/*!
525 * \property QCamera::upVector
526 * Holds the camera's up vector in coordinates relative to
527 * the parent entity.
528 *
529 * The up vector indicates which direction the top of the camera is
530 * facing. Think of taking a picture: after positioning yourself
531 * and pointing the camera at your target, you might rotate the camera
532 * left or right, giving you a portrait or landscape (or angled!)
533 * shot. upVector allows you to control this type of movement.
534 */
535
536/*!
537 * \property QCamera::viewCenter
538 * Holds the camera's view center in coordinates relative to
539 * the parent entity.
540 *
541 * Intuitively, the viewCenter is the location the camera is pointing at.
542 */
543
544/*!
545 * \property QCamera::viewVector
546 * Holds the camera's view vector in coordinates relative to
547 * the parent entity.
548 *
549 * This vector decribes the displacement from the camera (\l position)
550 * to its target (\l viewCenter).
551 */
552
553/*!
554 * \property QCamera::viewMatrix
555 * \deprecated
556 * Holds the camera's view matrix in coordinates relative to
557 * the parent entity.
558 */
559
560/*!
561 * Creates a new QCamera instance with the
562 * specified \a parent.
563 */
564QCamera::QCamera(Qt3DCore::QNode *parent)
565 : Qt3DCore::QEntity(*new QCameraPrivate, parent)
566{
567 QObject::connect(sender: d_func()->m_lens, SIGNAL(projectionTypeChanged(QCameraLens::ProjectionType)), receiver: this, SIGNAL(projectionTypeChanged(QCameraLens::ProjectionType)));
568 QObject::connect(sender: d_func()->m_lens, SIGNAL(nearPlaneChanged(float)), receiver: this, SIGNAL(nearPlaneChanged(float)));
569 QObject::connect(sender: d_func()->m_lens, SIGNAL(farPlaneChanged(float)), receiver: this, SIGNAL(farPlaneChanged(float)));
570 QObject::connect(sender: d_func()->m_lens, SIGNAL(fieldOfViewChanged(float)), receiver: this, SIGNAL(fieldOfViewChanged(float)));
571 QObject::connect(sender: d_func()->m_lens, SIGNAL(aspectRatioChanged(float)), receiver: this, SIGNAL(aspectRatioChanged(float)));
572 QObject::connect(sender: d_func()->m_lens, SIGNAL(leftChanged(float)), receiver: this, SIGNAL(leftChanged(float)));
573 QObject::connect(sender: d_func()->m_lens, SIGNAL(rightChanged(float)), receiver: this, SIGNAL(rightChanged(float)));
574 QObject::connect(sender: d_func()->m_lens, SIGNAL(bottomChanged(float)), receiver: this, SIGNAL(bottomChanged(float)));
575 QObject::connect(sender: d_func()->m_lens, SIGNAL(topChanged(float)), receiver: this, SIGNAL(topChanged(float)));
576 QObject::connect(sender: d_func()->m_lens, SIGNAL(projectionMatrixChanged(const QMatrix4x4 &)), receiver: this, SIGNAL(projectionMatrixChanged(const QMatrix4x4 &)));
577 QObject::connect(sender: d_func()->m_lens, SIGNAL(exposureChanged(float)), receiver: this, SIGNAL(exposureChanged(float)));
578 QObject::connect(sender: d_func()->m_lens, signal: &QCameraLens::viewSphere, receiver: this, slot: &QCamera::viewSphere);
579
580 addComponent(comp: d_func()->m_lens);
581 addComponent(comp: d_func()->m_transform);
582}
583
584/*!
585 * \internal
586 */
587QCamera::~QCamera()
588{
589}
590
591/*!
592 * \internal
593 */
594QCamera::QCamera(QCameraPrivate &dd, Qt3DCore::QNode *parent)
595 : Qt3DCore::QEntity(dd, parent)
596{
597 QObject::connect(sender: d_func()->m_lens, SIGNAL(projectionTypeChanged(QCameraLens::ProjectionType)), receiver: this, SIGNAL(projectionTypeChanged(QCameraLens::ProjectionType)));
598 QObject::connect(sender: d_func()->m_lens, SIGNAL(nearPlaneChanged(float)), receiver: this, SIGNAL(nearPlaneChanged(float)));
599 QObject::connect(sender: d_func()->m_lens, SIGNAL(farPlaneChanged(float)), receiver: this, SIGNAL(farPlaneChanged(float)));
600 QObject::connect(sender: d_func()->m_lens, SIGNAL(fieldOfViewChanged(float)), receiver: this, SIGNAL(fieldOfViewChanged(float)));
601 QObject::connect(sender: d_func()->m_lens, SIGNAL(aspectRatioChanged(float)), receiver: this, SIGNAL(aspectRatioChanged(float)));
602 QObject::connect(sender: d_func()->m_lens, SIGNAL(leftChanged(float)), receiver: this, SIGNAL(leftChanged(float)));
603 QObject::connect(sender: d_func()->m_lens, SIGNAL(rightChanged(float)), receiver: this, SIGNAL(rightChanged(float)));
604 QObject::connect(sender: d_func()->m_lens, SIGNAL(bottomChanged(float)), receiver: this, SIGNAL(bottomChanged(float)));
605 QObject::connect(sender: d_func()->m_lens, SIGNAL(topChanged(float)), receiver: this, SIGNAL(topChanged(float)));
606 QObject::connect(sender: d_func()->m_lens, SIGNAL(projectionMatrixChanged(const QMatrix4x4 &)), receiver: this, SIGNAL(projectionMatrixChanged(const QMatrix4x4 &)));
607 QObject::connect(sender: d_func()->m_lens, signal: &QCameraLens::viewSphere, receiver: this, slot: &QCamera::viewSphere);
608
609 addComponent(comp: d_func()->m_lens);
610 addComponent(comp: d_func()->m_transform);
611}
612
613/*!
614 * Returns the current lens.
615 */
616QCameraLens *QCamera::lens() const
617{
618 Q_D(const QCamera);
619 return d->m_lens;
620}
621
622/*!
623 * Returns the camera's position via transform.
624 */
625Qt3DCore::QTransform *QCamera::transform() const
626{
627 Q_D(const QCamera);
628 return d->m_transform;
629}
630
631/*!
632 * Translates the camera's position and its view vector by \a vLocal in local coordinates.
633 * The \a option allows for toggling whether the view center should be translated.
634 */
635void QCamera::translate(const QVector3D &vLocal, CameraTranslationOption option)
636{
637 QVector3D viewVector = viewCenter() - position(); // From "camera" position to view center
638
639 // Calculate the amount to move by in world coordinates
640 QVector3D vWorld;
641 if (!qFuzzyIsNull(f: vLocal.x())) {
642 // Calculate the vector for the local x axis
643 const QVector3D x = QVector3D::crossProduct(v1: viewVector, v2: upVector()).normalized();
644 vWorld += vLocal.x() * x;
645 }
646
647 if (!qFuzzyIsNull(f: vLocal.y()))
648 vWorld += vLocal.y() * upVector();
649
650 if (!qFuzzyIsNull(f: vLocal.z()))
651 vWorld += vLocal.z() * viewVector.normalized();
652
653 // Update the camera position using the calculated world vector
654 setPosition(position() + vWorld);
655
656 // May be also update the view center coordinates
657 if (option == TranslateViewCenter)
658 setViewCenter(viewCenter() + vWorld);
659
660 // Refresh the camera -> view center vector
661 viewVector = viewCenter() - position();
662
663 // Calculate a new up vector. We do this by:
664 // 1) Calculate a new local x-direction vector from the cross product of the new
665 // camera to view center vector and the old up vector.
666 // 2) The local x vector is the normal to the plane in which the new up vector
667 // must lay. So we can take the cross product of this normal and the new
668 // x vector. The new normal vector forms the last part of the orthonormal basis
669 const QVector3D x = QVector3D::crossProduct(v1: viewVector, v2: upVector()).normalized();
670 setUpVector(QVector3D::crossProduct(v1: x, v2: viewVector).normalized());
671}
672
673/*!
674 * Translates the camera's position and its view vector by \a vWorld in world coordinates.
675 * The \a option allows for toggling whether the view center should be translated.
676 */
677void QCamera::translateWorld(const QVector3D &vWorld, CameraTranslationOption option)
678{
679 // Update the camera position using the calculated world vector
680 setPosition(position() + vWorld);
681
682 // May be also update the view center coordinates
683 if (option == TranslateViewCenter)
684 setViewCenter(viewCenter() + vWorld);
685}
686
687/*!
688 * Returns the calculated tilt rotation in relation to the \a angle in degrees taken in
689 * to adjust the camera's tilt or up/down rotation on the X axis.
690 */
691QQuaternion QCamera::tiltRotation(float angle) const
692{
693 const QVector3D viewVector = viewCenter() - position();
694 const QVector3D xBasis = QVector3D::crossProduct(v1: upVector(), v2: viewVector.normalized()).normalized();
695 return QQuaternion::fromAxisAndAngle(axis: xBasis, angle: -angle);
696}
697
698/*!
699 * Returns the calculated pan rotation in relation to the \a angle in degrees taken in
700 * to adjust the camera's pan or left/right rotation on the Y axis.
701 */
702QQuaternion QCamera::panRotation(float angle) const
703{
704 return QQuaternion::fromAxisAndAngle(axis: upVector(), angle);
705}
706
707/*!
708 * Returns the calculated roll rotation in relation to the \a angle in degrees taken in
709 * to adjust the camera's roll or lean left/right rotation on the Z axis.
710 */
711QQuaternion QCamera::rollRotation(float angle) const
712{
713 QVector3D viewVector = viewCenter() - position();
714 return QQuaternion::fromAxisAndAngle(axis: viewVector, angle: -angle);
715}
716
717/*!
718 * Returns the calculated rotation in relation to the \a angle in degrees and
719 * chosen \a axis taken in.
720 */
721QQuaternion QCamera::rotation(float angle, const QVector3D &axis) const
722{
723 return QQuaternion::fromAxisAndAngle(axis, angle);
724}
725
726/*!
727 * Adjusts the tilt angle of the camera by \a angle in degrees.
728 */
729void QCamera::tilt(float angle)
730{
731 QQuaternion q = tiltRotation(angle);
732 rotate(q);
733}
734
735/*!
736 * Adjusts the pan angle of the camera by \a angle in degrees.
737 */
738void QCamera::pan(float angle)
739{
740 QQuaternion q = panRotation(angle: -angle);
741 rotate(q);
742}
743
744/*!
745 * Adjusts the pan angle of the camera by \a angle in degrees on a chosen \a axis.
746 */
747void QCamera::pan(float angle, const QVector3D &axis)
748{
749 QQuaternion q = rotation(angle: -angle, axis);
750 rotate(q);
751}
752
753/*!
754 * Adjusts the camera roll by \a angle in degrees.
755 */
756void QCamera::roll(float angle)
757{
758 QQuaternion q = rollRotation(angle: -angle);
759 rotate(q);
760}
761
762/*!
763 * Adjusts the camera tilt about view center by \a angle in degrees.
764 */
765void QCamera::tiltAboutViewCenter(float angle)
766{
767 QQuaternion q = tiltRotation(angle: -angle);
768 rotateAboutViewCenter(q);
769}
770
771/*!
772 * Adjusts the camera pan about view center by \a angle in degrees.
773 */
774void QCamera::panAboutViewCenter(float angle)
775{
776 QQuaternion q = panRotation(angle);
777 rotateAboutViewCenter(q);
778}
779
780/*!
781 * Adjusts the camera pan about view center by \a angle in degrees on \a axis.
782 */
783void QCamera::panAboutViewCenter(float angle, const QVector3D &axis)
784{
785 QQuaternion q = rotation(angle, axis);
786 rotateAboutViewCenter(q);
787}
788
789/*!
790 * Adjusts the camera roll about view center by \a angle in degrees.
791 */
792void QCamera::rollAboutViewCenter(float angle)
793{
794 QQuaternion q = rollRotation(angle);
795 rotateAboutViewCenter(q);
796}
797
798/*!
799 * Rotates the camera with the use of a Quaternion in \a q.
800 */
801void QCamera::rotate(const QQuaternion& q)
802{
803 setUpVector(q * upVector());
804 QVector3D viewVector = viewCenter() - position();
805 QVector3D cameraToCenter = q * viewVector;
806 setViewCenter(position() + cameraToCenter);
807}
808
809/*!
810 * Rotates the camera about the view center with the use of a Quaternion
811 * in \a q.
812 */
813void QCamera::rotateAboutViewCenter(const QQuaternion& q)
814{
815 setUpVector(q * upVector());
816 QVector3D viewVector = viewCenter() - position();
817 QVector3D cameraToCenter = q * viewVector;
818 setPosition(viewCenter() - cameraToCenter);
819 setViewCenter(position() + cameraToCenter);
820}
821
822/*!
823 * Rotates and moves the camera so that it's viewCenter is the center of the scene's bounding volume
824 * and the entire scene fits in the view port.
825 *
826 * \note Only works if the lens is in perspective or orthographic projection mode.
827 * \sa Qt3D.Render::Camera::projectionType
828 */
829void QCamera::viewAll()
830{
831 Q_D(QCamera);
832 d->m_lens->viewAll(cameraId: id());
833}
834
835/*!
836 * Rotates and moves the camera so that it's viewCenter is \a center
837 * and a sphere of \a radius fits in the view port.
838 *
839 * \note Only works if the lens is in perspective or orthographic projection mode.
840 * \sa Qt3D.Render::Camera::projectionType
841 */
842void QCamera::viewSphere(const QVector3D &center, float radius)
843{
844 Q_D(QCamera);
845 if ((d->m_lens->projectionType() != QCameraLens::PerspectiveProjection &&
846 d->m_lens->projectionType() != QCameraLens::OrthographicProjection) ||
847 radius <= 0.f)
848 return;
849
850 // Ensure the sphere fits in the view port even if aspect ratio < 1 (i.e. width < height)
851 float height = (1.05f * radius) / (d->m_lens->aspectRatio() < 1.0f ? d->m_lens->aspectRatio() : 1.0f);
852 float dist = 1.0f;
853 if (d->m_lens->projectionType() == QCameraLens::PerspectiveProjection) {
854 dist = height / std::sin(x: qDegreesToRadians(degrees: d->m_lens->fieldOfView()) / 2.0f);
855 }
856 else if (d->m_lens->projectionType() == QCameraLens::OrthographicProjection) {
857 d->m_lens->setOrthographicProjection(left: -height * d->m_lens->aspectRatio(), right: height * d->m_lens->aspectRatio(), bottom: -height, top: height,
858 nearPlane: nearPlane(), farPlane: farPlane());
859 dist = height / std::sin(x: qDegreesToRadians(degrees: d->m_lens->fieldOfView()) / 2.0f);
860 }
861 else {
862 dist = (d->m_viewCenter - d->m_position).length();
863 }
864 QVector3D dir = (d->m_viewCenter - d->m_position).normalized();
865 QVector3D newPos = center - (dir * dist);
866 setViewCenter(center);
867 setPosition(newPos);
868}
869
870/*!
871 * Rotates and moves the camera so that it's viewCenter is the center of the
872 * \a {entity}'s bounding volume and the entire entity fits in the view port.
873 *
874 * \note Only works if the lens is in perspective or orthographic projection mode.
875 * \sa {Qt3D.Render::Camera::projectionType}{Camera.projectionType}
876 */
877void QCamera::viewEntity(Qt3DCore::QEntity *entity)
878{
879 if (!entity)
880 return;
881
882 Q_D(QCamera);
883 d->m_lens->viewEntity(entityId: entity->id(), cameraId: id());
884}
885
886/*!
887 * Sets the camera's projection type to \a type.
888 */
889void QCamera::setProjectionType(QCameraLens::ProjectionType type)
890{
891 Q_D(QCamera);
892 d->m_lens->setProjectionType(type);
893}
894
895QCameraLens::ProjectionType QCamera::projectionType() const
896{
897 Q_D(const QCamera);
898 return d->m_lens->projectionType();
899}
900
901/*!
902 * Sets the camera's near plane to \a nearPlane.
903 */
904void QCamera::setNearPlane(float nearPlane)
905{
906 Q_D(QCamera);
907 d->m_lens->setNearPlane(nearPlane);
908}
909
910float QCamera::nearPlane() const
911{
912 Q_D(const QCamera);
913 return d->m_lens->nearPlane();
914}
915
916/*!
917 * Sets the camera's far plane to \a farPlane
918 */
919void QCamera::setFarPlane(float farPlane)
920{
921 Q_D(QCamera);
922 d->m_lens->setFarPlane(farPlane);
923}
924
925float QCamera::farPlane() const
926{
927 Q_D(const QCamera);
928 return d->m_lens->farPlane();
929}
930
931/*!
932 * Sets the camera's field of view to \a fieldOfView in degrees.
933 */
934void QCamera::setFieldOfView(float fieldOfView)
935{
936 Q_D(QCamera);
937 d->m_lens->setFieldOfView(fieldOfView);
938}
939
940float QCamera::fieldOfView() const
941{
942 Q_D(const QCamera);
943 return d->m_lens->fieldOfView();
944}
945
946/*!
947 * Sets the camera's aspect ratio to \a aspectRatio.
948 */
949void QCamera::setAspectRatio(float aspectRatio)
950{
951 Q_D(QCamera);
952 d->m_lens->setAspectRatio(aspectRatio);
953}
954
955float QCamera::aspectRatio() const
956{
957 Q_D(const QCamera);
958 return d->m_lens->aspectRatio();
959}
960
961/*!
962 * Sets the left of the camera to \a left.
963 */
964void QCamera::setLeft(float left)
965{
966 Q_D(QCamera);
967 d->m_lens->setLeft(left);
968}
969
970float QCamera::left() const
971{
972 Q_D(const QCamera);
973 return d->m_lens->left();
974}
975
976/*!
977 * Sets the right of the camera to \a right.
978 */
979void QCamera::setRight(float right)
980{
981 Q_D(QCamera);
982 d->m_lens->setRight(right);
983}
984
985float QCamera::right() const
986{
987 Q_D(const QCamera);
988 return d->m_lens->right();
989}
990
991/*!
992 * Sets the bottom of the camera to \a bottom.
993 */
994void QCamera::setBottom(float bottom)
995{
996 Q_D(QCamera);
997 d->m_lens->setBottom(bottom);
998}
999
1000float QCamera::bottom() const
1001{
1002 Q_D(const QCamera);
1003 return d->m_lens->bottom();
1004}
1005
1006/*!
1007 * Sets the top of the camera to \a top.
1008 */
1009void QCamera::setTop(float top)
1010{
1011 Q_D(QCamera);
1012 d->m_lens->setTop(top);
1013}
1014
1015float QCamera::top() const
1016{
1017 Q_D(const QCamera);
1018 return d->m_lens->top();
1019}
1020
1021/*!
1022 * Sets the camera's projection matrix to \a projectionMatrix.
1023 */
1024void QCamera::setProjectionMatrix(const QMatrix4x4 &projectionMatrix)
1025{
1026 Q_D(QCamera);
1027 d->m_lens->setProjectionMatrix(projectionMatrix);
1028}
1029
1030/*!
1031 * Sets the camera's exposure to \a exposure.
1032 */
1033void QCamera::setExposure(float exposure)
1034{
1035 Q_D(QCamera);
1036 d->m_lens->setExposure(exposure);
1037}
1038
1039QMatrix4x4 QCamera::projectionMatrix() const
1040{
1041 Q_D(const QCamera);
1042 return d->m_lens->projectionMatrix();
1043}
1044
1045float QCamera::exposure() const
1046{
1047 Q_D(const QCamera);
1048 return d->m_lens->exposure();
1049}
1050
1051/*!
1052 * Sets the camera's position in 3D space to \a position.
1053 */
1054void QCamera::setPosition(const QVector3D &position)
1055{
1056 Q_D(QCamera);
1057 if (!qFuzzyCompare(v1: d->m_position, v2: position)) {
1058 d->m_position = position;
1059 d->m_cameraToCenter = d->m_viewCenter - position;
1060 d->m_viewMatrixDirty = true;
1061 emit positionChanged(position);
1062 emit viewVectorChanged(viewVector: d->m_cameraToCenter);
1063 d->updateViewMatrixAndTransform();
1064 }
1065}
1066
1067QVector3D QCamera::position() const
1068{
1069 Q_D(const QCamera);
1070 return d->m_position;
1071}
1072
1073/*!
1074 * Sets the camera's up vector to \a upVector.
1075 */
1076void QCamera::setUpVector(const QVector3D &upVector)
1077{
1078 Q_D(QCamera);
1079 if (!qFuzzyCompare(v1: d->m_upVector, v2: upVector)) {
1080 d->m_upVector = upVector;
1081 d->m_viewMatrixDirty = true;
1082 emit upVectorChanged(upVector);
1083 d->updateViewMatrixAndTransform();
1084 }
1085}
1086
1087QVector3D QCamera::upVector() const
1088{
1089 Q_D(const QCamera);
1090 return d->m_upVector;
1091}
1092
1093/*!
1094 * Sets the camera's view center to \a viewCenter.
1095 */
1096void QCamera::setViewCenter(const QVector3D &viewCenter)
1097{
1098 Q_D(QCamera);
1099 if (!qFuzzyCompare(v1: d->m_viewCenter, v2: viewCenter)) {
1100 d->m_viewCenter = viewCenter;
1101 d->m_cameraToCenter = viewCenter - d->m_position;
1102 d->m_viewMatrixDirty = true;
1103 emit viewCenterChanged(viewCenter);
1104 emit viewVectorChanged(viewVector: d->m_cameraToCenter);
1105 d->updateViewMatrixAndTransform();
1106 }
1107}
1108
1109QVector3D QCamera::viewCenter() const
1110{
1111 Q_D(const QCamera);
1112 return d->m_viewCenter;
1113}
1114
1115QVector3D QCamera::viewVector() const
1116{
1117 Q_D(const QCamera);
1118 return d->m_cameraToCenter;
1119}
1120
1121QMatrix4x4 QCamera::viewMatrix() const
1122{
1123 Q_D(const QCamera);
1124 return d->m_viewMatrix;
1125}
1126
1127} // Qt3DRender
1128
1129QT_END_NAMESPACE
1130

source code of qt3d/src/render/frontend/qcamera.cpp