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 ¢er, 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