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

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