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 
45 QT_BEGIN_NAMESPACE
46 
47 namespace Qt3DRender {
48 
49 /*!
50  * \internal
51  */
QCameraPrivate()52 QCameraPrivate::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(false);
63 }
64 
updateViewMatrixAndTransform(bool doEmit)65 void 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(m_position);
73 
74     // Negative viewDirection because OpenGL convention is looking down -Z
75     transformMatrix.rotate(QQuaternion::fromDirection(-viewDirection, m_upVector.normalized()));
76 
77     m_transform->setMatrix(transformMatrix);
78 
79     QMatrix4x4 viewMatrix;
80     viewMatrix.lookAt(m_position, m_viewCenter, 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  */
QCamera(Qt3DCore::QNode * parent)564 QCamera::QCamera(Qt3DCore::QNode *parent)
565     : Qt3DCore::QEntity(*new QCameraPrivate, parent)
566 {
567     QObject::connect(d_func()->m_lens, SIGNAL(projectionTypeChanged(QCameraLens::ProjectionType)), this, SIGNAL(projectionTypeChanged(QCameraLens::ProjectionType)));
568     QObject::connect(d_func()->m_lens, SIGNAL(nearPlaneChanged(float)), this, SIGNAL(nearPlaneChanged(float)));
569     QObject::connect(d_func()->m_lens, SIGNAL(farPlaneChanged(float)), this, SIGNAL(farPlaneChanged(float)));
570     QObject::connect(d_func()->m_lens, SIGNAL(fieldOfViewChanged(float)), this, SIGNAL(fieldOfViewChanged(float)));
571     QObject::connect(d_func()->m_lens, SIGNAL(aspectRatioChanged(float)), this, SIGNAL(aspectRatioChanged(float)));
572     QObject::connect(d_func()->m_lens, SIGNAL(leftChanged(float)), this, SIGNAL(leftChanged(float)));
573     QObject::connect(d_func()->m_lens, SIGNAL(rightChanged(float)), this, SIGNAL(rightChanged(float)));
574     QObject::connect(d_func()->m_lens, SIGNAL(bottomChanged(float)), this, SIGNAL(bottomChanged(float)));
575     QObject::connect(d_func()->m_lens, SIGNAL(topChanged(float)), this, SIGNAL(topChanged(float)));
576     QObject::connect(d_func()->m_lens, SIGNAL(projectionMatrixChanged(const QMatrix4x4 &)), this, SIGNAL(projectionMatrixChanged(const QMatrix4x4 &)));
577     QObject::connect(d_func()->m_lens, SIGNAL(exposureChanged(float)), this, SIGNAL(exposureChanged(float)));
578     QObject::connect(d_func()->m_lens, &QCameraLens::viewSphere, this, &QCamera::viewSphere);
579 
580     addComponent(d_func()->m_lens);
581     addComponent(d_func()->m_transform);
582 }
583 
584 /*!
585  * \internal
586  */
~QCamera()587 QCamera::~QCamera()
588 {
589 }
590 
591 /*!
592  * \internal
593  */
QCamera(QCameraPrivate & dd,Qt3DCore::QNode * parent)594 QCamera::QCamera(QCameraPrivate &dd, Qt3DCore::QNode *parent)
595     : Qt3DCore::QEntity(dd, parent)
596 {
597     QObject::connect(d_func()->m_lens, SIGNAL(projectionTypeChanged(QCameraLens::ProjectionType)), this, SIGNAL(projectionTypeChanged(QCameraLens::ProjectionType)));
598     QObject::connect(d_func()->m_lens, SIGNAL(nearPlaneChanged(float)), this, SIGNAL(nearPlaneChanged(float)));
599     QObject::connect(d_func()->m_lens, SIGNAL(farPlaneChanged(float)), this, SIGNAL(farPlaneChanged(float)));
600     QObject::connect(d_func()->m_lens, SIGNAL(fieldOfViewChanged(float)), this, SIGNAL(fieldOfViewChanged(float)));
601     QObject::connect(d_func()->m_lens, SIGNAL(aspectRatioChanged(float)), this, SIGNAL(aspectRatioChanged(float)));
602     QObject::connect(d_func()->m_lens, SIGNAL(leftChanged(float)), this, SIGNAL(leftChanged(float)));
603     QObject::connect(d_func()->m_lens, SIGNAL(rightChanged(float)), this, SIGNAL(rightChanged(float)));
604     QObject::connect(d_func()->m_lens, SIGNAL(bottomChanged(float)), this, SIGNAL(bottomChanged(float)));
605     QObject::connect(d_func()->m_lens, SIGNAL(topChanged(float)), this, SIGNAL(topChanged(float)));
606     QObject::connect(d_func()->m_lens, SIGNAL(projectionMatrixChanged(const QMatrix4x4 &)), this, SIGNAL(projectionMatrixChanged(const QMatrix4x4 &)));
607     QObject::connect(d_func()->m_lens, &QCameraLens::viewSphere, this, &QCamera::viewSphere);
608 
609     addComponent(d_func()->m_lens);
610     addComponent(d_func()->m_transform);
611 }
612 
613 /*!
614  * Returns the current lens.
615  */
lens() const616 QCameraLens *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  */
transform() const625 Qt3DCore::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  */
translate(const QVector3D & vLocal,CameraTranslationOption option)635 void 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(vLocal.x())) {
642         // Calculate the vector for the local x axis
643         const QVector3D x = QVector3D::crossProduct(viewVector, upVector()).normalized();
644         vWorld += vLocal.x() * x;
645     }
646 
647     if (!qFuzzyIsNull(vLocal.y()))
648         vWorld += vLocal.y() * upVector();
649 
650     if (!qFuzzyIsNull(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(viewVector, upVector()).normalized();
670     setUpVector(QVector3D::crossProduct(x, 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  */
translateWorld(const QVector3D & vWorld,CameraTranslationOption option)677 void 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  */
tiltRotation(float angle) const691 QQuaternion QCamera::tiltRotation(float angle) const
692 {
693     const QVector3D viewVector = viewCenter() - position();
694     const QVector3D xBasis = QVector3D::crossProduct(upVector(), viewVector.normalized()).normalized();
695     return QQuaternion::fromAxisAndAngle(xBasis, -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  */
panRotation(float angle) const702 QQuaternion QCamera::panRotation(float angle) const
703 {
704     return QQuaternion::fromAxisAndAngle(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  */
rollRotation(float angle) const711 QQuaternion QCamera::rollRotation(float angle) const
712 {
713     QVector3D viewVector = viewCenter() - position();
714     return QQuaternion::fromAxisAndAngle(viewVector, -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  */
rotation(float angle,const QVector3D & axis) const721 QQuaternion 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  */
tilt(float angle)729 void 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  */
pan(float angle)738 void QCamera::pan(float angle)
739 {
740     QQuaternion q = panRotation(-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  */
pan(float angle,const QVector3D & axis)747 void QCamera::pan(float angle, const QVector3D &axis)
748 {
749     QQuaternion q = rotation(-angle, axis);
750     rotate(q);
751 }
752 
753 /*!
754  * Adjusts the camera roll by \a angle in degrees.
755  */
roll(float angle)756 void QCamera::roll(float angle)
757 {
758     QQuaternion q = rollRotation(-angle);
759     rotate(q);
760 }
761 
762 /*!
763  * Adjusts the camera tilt about view center by \a angle in degrees.
764  */
tiltAboutViewCenter(float angle)765 void QCamera::tiltAboutViewCenter(float angle)
766 {
767     QQuaternion q = tiltRotation(-angle);
768     rotateAboutViewCenter(q);
769 }
770 
771 /*!
772  * Adjusts the camera pan about view center by \a angle in degrees.
773  */
panAboutViewCenter(float angle)774 void 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  */
panAboutViewCenter(float angle,const QVector3D & axis)783 void 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  */
rollAboutViewCenter(float angle)792 void 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  */
rotate(const QQuaternion & q)801 void 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  */
rotateAboutViewCenter(const QQuaternion & q)813 void 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  */
viewAll()829 void QCamera::viewAll()
830 {
831     Q_D(QCamera);
832     d->m_lens->viewAll(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  */
viewSphere(const QVector3D & center,float radius)842 void 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(qDegreesToRadians(d->m_lens->fieldOfView()) / 2.0f);
855     }
856     else if (d->m_lens->projectionType() == QCameraLens::OrthographicProjection) {
857         d->m_lens->setOrthographicProjection(-height * d->m_lens->aspectRatio(), height * d->m_lens->aspectRatio(), -height, height,
858             nearPlane(), farPlane());
859         dist = height / std::sin(qDegreesToRadians(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  */
viewEntity(Qt3DCore::QEntity * entity)877 void QCamera::viewEntity(Qt3DCore::QEntity *entity)
878 {
879     if (!entity)
880         return;
881 
882     Q_D(QCamera);
883     d->m_lens->viewEntity(entity->id(), id());
884 }
885 
886 /*!
887  * Sets the camera's projection type to \a type.
888  */
setProjectionType(QCameraLens::ProjectionType type)889 void QCamera::setProjectionType(QCameraLens::ProjectionType type)
890 {
891     Q_D(QCamera);
892     d->m_lens->setProjectionType(type);
893 }
894 
projectionType() const895 QCameraLens::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  */
setNearPlane(float nearPlane)904 void QCamera::setNearPlane(float nearPlane)
905 {
906     Q_D(QCamera);
907     d->m_lens->setNearPlane(nearPlane);
908 }
909 
nearPlane() const910 float 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  */
setFarPlane(float farPlane)919 void QCamera::setFarPlane(float farPlane)
920 {
921     Q_D(QCamera);
922     d->m_lens->setFarPlane(farPlane);
923 }
924 
farPlane() const925 float 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  */
setFieldOfView(float fieldOfView)934 void QCamera::setFieldOfView(float fieldOfView)
935 {
936     Q_D(QCamera);
937     d->m_lens->setFieldOfView(fieldOfView);
938 }
939 
fieldOfView() const940 float 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  */
setAspectRatio(float aspectRatio)949 void QCamera::setAspectRatio(float aspectRatio)
950 {
951     Q_D(QCamera);
952     d->m_lens->setAspectRatio(aspectRatio);
953 }
954 
aspectRatio() const955 float 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  */
setLeft(float left)964 void QCamera::setLeft(float left)
965 {
966     Q_D(QCamera);
967     d->m_lens->setLeft(left);
968 }
969 
left() const970 float 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  */
setRight(float right)979 void QCamera::setRight(float right)
980 {
981     Q_D(QCamera);
982     d->m_lens->setRight(right);
983 }
984 
right() const985 float 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  */
setBottom(float bottom)994 void QCamera::setBottom(float bottom)
995 {
996     Q_D(QCamera);
997     d->m_lens->setBottom(bottom);
998 }
999 
bottom() const1000 float 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  */
setTop(float top)1009 void QCamera::setTop(float top)
1010 {
1011     Q_D(QCamera);
1012     d->m_lens->setTop(top);
1013 }
1014 
top() const1015 float 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  */
setProjectionMatrix(const QMatrix4x4 & projectionMatrix)1024 void 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  */
setExposure(float exposure)1033 void QCamera::setExposure(float exposure)
1034 {
1035     Q_D(QCamera);
1036     d->m_lens->setExposure(exposure);
1037 }
1038 
projectionMatrix() const1039 QMatrix4x4 QCamera::projectionMatrix() const
1040 {
1041     Q_D(const QCamera);
1042     return d->m_lens->projectionMatrix();
1043 }
1044 
exposure() const1045 float 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  */
setPosition(const QVector3D & position)1054 void QCamera::setPosition(const QVector3D &position)
1055 {
1056     Q_D(QCamera);
1057     if (!qFuzzyCompare(d->m_position, 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(d->m_cameraToCenter);
1063         d->updateViewMatrixAndTransform();
1064     }
1065 }
1066 
position() const1067 QVector3D 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  */
setUpVector(const QVector3D & upVector)1076 void QCamera::setUpVector(const QVector3D &upVector)
1077 {
1078     Q_D(QCamera);
1079     if (!qFuzzyCompare(d->m_upVector, upVector)) {
1080         d->m_upVector = upVector;
1081         d->m_viewMatrixDirty = true;
1082         emit upVectorChanged(upVector);
1083         d->updateViewMatrixAndTransform();
1084     }
1085 }
1086 
upVector() const1087 QVector3D 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  */
setViewCenter(const QVector3D & viewCenter)1096 void QCamera::setViewCenter(const QVector3D &viewCenter)
1097 {
1098     Q_D(QCamera);
1099     if (!qFuzzyCompare(d->m_viewCenter, 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(d->m_cameraToCenter);
1105         d->updateViewMatrixAndTransform();
1106     }
1107 }
1108 
viewCenter() const1109 QVector3D QCamera::viewCenter() const
1110 {
1111     Q_D(const QCamera);
1112     return d->m_viewCenter;
1113 }
1114 
viewVector() const1115 QVector3D QCamera::viewVector() const
1116 {
1117     Q_D(const QCamera);
1118     return d->m_cameraToCenter;
1119 }
1120 
viewMatrix() const1121 QMatrix4x4 QCamera::viewMatrix() const
1122 {
1123     Q_D(const QCamera);
1124     return d->m_viewMatrix;
1125 }
1126 
1127 } // Qt3DRender
1128 
1129 QT_END_NAMESPACE
1130