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 | */ |
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(doEmit: false); |
63 | } |
64 | |
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(vector: m_position); |
73 | |
74 | // Negative viewDirection because OpenGL convention is looking down -Z |
75 | transformMatrix.rotate(quaternion: QQuaternion::fromDirection(direction: -viewDirection, up: m_upVector.normalized())); |
76 | |
77 | m_transform->setMatrix(transformMatrix); |
78 | |
79 | QMatrix4x4 viewMatrix; |
80 | viewMatrix.lookAt(eye: m_position, center: m_viewCenter, up: m_upVector); |
81 | m_viewMatrix = viewMatrix; |
82 | if (doEmit) |
83 | emit q->viewMatrixChanged(); |
84 | } |
85 | |
86 | /*! |
87 | * \class Qt3DRender::QCamera |
88 | * \inheaderfile Qt3DRender/QCamera |
89 | * \brief The QCamera class defines a view point through which the scene will be |
90 | * rendered. |
91 | * \inmodule Qt3DRender |
92 | * \since 5.5 |
93 | */ |
94 | |
95 | /*! |
96 | * \qmltype Camera |
97 | * \instantiates Qt3DRender::QCamera |
98 | * \inherits Entity |
99 | * \inqmlmodule Qt3D.Render |
100 | * \since 5.5 |
101 | * \brief Defines a view point through which the scene will be rendered. |
102 | */ |
103 | |
104 | /*! |
105 | * \enum Qt3DRender::QCamera::CameraTranslationOption |
106 | * |
107 | * This enum specifies how camera view center is translated |
108 | * \value TranslateViewCenter Translate the view center causing the view direction to remain the same |
109 | * \value DontTranslateViewCenter Don't translate the view center causing the view direction to change |
110 | */ |
111 | |
112 | /*! |
113 | * \qmlmethod quaternion Qt3D.Render::Camera::tiltRotation(real angle) |
114 | * |
115 | * Returns the calculated tilt rotation in relation to the \a angle in degrees taken in |
116 | * to adjust the camera's tilt or up/down rotation on the X axis. |
117 | */ |
118 | |
119 | /*! |
120 | * \qmlmethod quaternion Qt3D.Render::Camera::panRotation(real angle) |
121 | * |
122 | * Returns the calculated pan rotation in relation to the \a angle in degrees taken in |
123 | * to adjust the camera's pan or left/right rotation on the Y axis. |
124 | */ |
125 | |
126 | /*! |
127 | * \qmlmethod quaternion Qt3D.Render::Camera::rollRotation(real angle) |
128 | * |
129 | * Returns the calculated roll rotation in relation to the \a angle in degrees taken in |
130 | * to adjust the camera's roll or lean left/right rotation on the Z axis. |
131 | */ |
132 | |
133 | /*! |
134 | * \qmlmethod quaternion Qt3D.Render::Camera::rotation(real angle, vector3d axis) |
135 | * |
136 | * Returns the calculated rotation in relation to the \a angle in degrees and |
137 | * chosen \a axis taken in. |
138 | */ |
139 | |
140 | /*! |
141 | * \qmlmethod void Qt3D.Render::Camera::translate(vector3d vLocal, enumeration option) |
142 | * |
143 | * Translates the camera's position and its view vector by \a vLocal in local coordinates. |
144 | * The \a option allows for toggling whether the view center should be translated. |
145 | * \list |
146 | * \li Camera.TranslateViewCenter |
147 | * \li Camera.DontTranslateViewCenter |
148 | * \endlist |
149 | * \sa Qt3DRender::QCamera::CameraTranslationOption |
150 | */ |
151 | |
152 | /*! |
153 | * \qmlmethod void Qt3D.Render::Camera::translateWorld(vector3d vWorld, enumeration option) |
154 | * |
155 | * Translates the camera's position and its view vector by \a vWorld in world coordinates. |
156 | * The \a option allows for toggling whether the view center should be translated. |
157 | * \list |
158 | * \li Camera.TranslateViewCenter |
159 | * \li Camera.DontTranslateViewCenter |
160 | * \endlist |
161 | * \sa Qt3DRender::QCamera::CameraTranslationOption |
162 | */ |
163 | |
164 | /*! |
165 | * \qmlmethod void Qt3D.Render::Camera::tilt(real angle) |
166 | * |
167 | * Adjusts the tilt angle of the camera by \a angle in degrees. |
168 | */ |
169 | |
170 | /*! |
171 | * \qmlmethod void Qt3D.Render::Camera::pan(real angle) |
172 | * |
173 | * Adjusts the pan angle of the camera by \a angle in degrees. |
174 | */ |
175 | |
176 | /*! |
177 | * \qmlmethod void Qt3D.Render::Camera::pan(real angle, vector3d axis) |
178 | * |
179 | * Adjusts the camera pan about view center by \a angle in degrees on \a axis. |
180 | */ |
181 | |
182 | /*! |
183 | * \qmlmethod void Qt3D.Render::Camera::roll(real angle) |
184 | * |
185 | * Adjusts the camera roll by \a angle in degrees. |
186 | */ |
187 | |
188 | /*! |
189 | * \qmlmethod void Qt3D.Render::Camera::tiltAboutViewCenter(real angle) |
190 | * |
191 | * Adjusts the camera tilt about view center by \a angle in degrees. |
192 | */ |
193 | |
194 | /*! |
195 | * \qmlmethod void Qt3D.Render::Camera::panAboutViewCenter(real angle) |
196 | * |
197 | * Adjusts the camera pan about view center by \a angle in degrees. |
198 | */ |
199 | |
200 | /*! |
201 | * \qmlmethod void Qt3D.Render::Camera::panAboutViewCenter(real angle, vector3d axis) |
202 | * |
203 | * Adjusts the camera pan about view center by \a angle in degrees on \a axis. |
204 | */ |
205 | |
206 | /*! |
207 | * \qmlmethod void Qt3D.Render::Camera::rollAboutViewCenter(real angle) |
208 | * |
209 | * Adjusts the camera roll about view center by \a angle in degrees. |
210 | */ |
211 | |
212 | /*! |
213 | * \qmlmethod void Qt3D.Render::Camera::rotate(quaternion q) |
214 | * |
215 | * Rotates the camera with the use of a Quaternion in \a q. |
216 | */ |
217 | |
218 | /*! |
219 | * \qmlmethod void Qt3D.Render::Camera::rotateAboutViewCenter(quaternion q) |
220 | * |
221 | * Rotates the camera about the view center with the use of a Quaternion in \a q. |
222 | */ |
223 | |
224 | /*! |
225 | * \qmlmethod void Qt3D.Render::Camera::viewAll() |
226 | * |
227 | * Rotates and moves the camera so that it's viewCenter is the center of the scene's bounding volume |
228 | * and the entire scene fits in the view port. |
229 | * |
230 | * \note Only works if the lens is in perspective or orthographic projection mode. |
231 | * \sa Qt3D.Render::Camera::projectionType |
232 | */ |
233 | |
234 | /*! |
235 | * \qmlmethod void Qt3D.Render::Camera::viewEntity(Entity entity) |
236 | * |
237 | * Rotates and moves the camera so that it's viewCenter is the center of the entity's bounding volume |
238 | * and the entire \a entity fits in the view port. |
239 | * |
240 | * \note Only works if the lens is in perspective or orthographic projection mode. |
241 | * \sa Qt3D.Render::Camera::projectionType |
242 | */ |
243 | |
244 | /*! |
245 | * \qmlmethod void Qt3D.Render::Camera::viewSphere(vector3d center, real radius) |
246 | * |
247 | * Rotates and moves the camera so that it's viewCenter is \a center |
248 | * and a sphere of \a radius fits in the view port. |
249 | * |
250 | * \note Only works if the lens is in perspective or orthographic projection mode. |
251 | * \sa Qt3D.Render::Camera::projectionType |
252 | */ |
253 | |
254 | /*! |
255 | * \qmlproperty enumeration Qt3D.Render::Camera::projectionType |
256 | * |
257 | * Holds the type of the camera projection. The default value is |
258 | * CameraLens.PerspectiveProjection. |
259 | * |
260 | * \list |
261 | * \li CameraLens.OrthographicProjection - Parallel lines appear parallel. Objects appear |
262 | * the same size regardless of distance. |
263 | * \li CameraLens.PerspectiveProjection - Parallel lines appear to meet in the distance. |
264 | * Objects appear to shrink the farther they are from the camera. |
265 | * \li CameraLens.FrustumProjection |
266 | * \li CameraLens.CustomProjection |
267 | * \endlist |
268 | * \sa Qt3DRender::QCameraLens::ProjectionType |
269 | */ |
270 | |
271 | /*! |
272 | * \qmlproperty real Qt3D.Render::Camera::nearPlane |
273 | * Holds the current camera near plane of the camera. Objects that |
274 | * are closer to the camera than the nearPlane will not be rendered. |
275 | */ |
276 | |
277 | /*! |
278 | * \qmlproperty real Qt3D.Render::Camera::farPlane |
279 | * Holds the current camera far plane of the camera. Objects that |
280 | * are farther from the camera than the farPlane will not be rendered. |
281 | */ |
282 | |
283 | /*! |
284 | * \qmlproperty Qt3DRender::QCameraLens QCamera::lens |
285 | * Holds the CameraLens component of the camera. |
286 | * \since 5.14 |
287 | */ |
288 | |
289 | /*! |
290 | * \qmlproperty Qt3DCore::QTransform QCamera::transform |
291 | * Holds the Transform component of the camera. |
292 | * \since 5.14 |
293 | */ |
294 | |
295 | /*! |
296 | * \qmlproperty real Qt3D.Render::Camera::fieldOfView |
297 | * Holds the current vertical field of view of the camera in degrees. |
298 | * |
299 | * Along with \l aspectRatio, this property determines how much of |
300 | * the scene is visible to the camera. In that respect you might |
301 | * think of it as analogous to choosing a wide angle (wide horizontal |
302 | * field of view) or telephoto (narrow horizontal field of view) lens, |
303 | * depending on how much of a scene you want to capture. |
304 | * |
305 | * fieldOfView is only relevant when \l projectionType is |
306 | * CameraLens.PerspectiveProjection. |
307 | */ |
308 | |
309 | /*! |
310 | * \qmlproperty real Qt3D.Render::Camera::aspectRatio |
311 | * Holds the current aspect ratio of the camera. |
312 | */ |
313 | |
314 | /*! |
315 | *\qmlproperty real Qt3D.Render::Camera::left |
316 | * Holds the current left of the camera. |
317 | * |
318 | * This property is only relevant when \l projectionType is |
319 | * CameraLens.OrthographicProjection. |
320 | */ |
321 | |
322 | /*! |
323 | * \qmlproperty real Qt3D.Render::Camera::right |
324 | * Holds the current right of the camera. |
325 | * |
326 | * This property is only relevant when \l projectionType is |
327 | * CameraLens.OrthographicProjection. |
328 | */ |
329 | |
330 | /*! |
331 | * \qmlproperty real Qt3D.Render::Camera::bottom |
332 | * Holds the current bottom of the camera. |
333 | * |
334 | * This property is only relevant when \l projectionType is |
335 | * CameraLens.OrthographicProjection. |
336 | */ |
337 | |
338 | /*! |
339 | * \qmlproperty real Qt3D.Render::Camera::top |
340 | * Holds the current top of the camera. |
341 | * |
342 | * This property is only relevant when \l projectionType is |
343 | * CameraLens.OrthographicProjection. |
344 | */ |
345 | |
346 | /*! |
347 | * \qmlproperty matrix4x4 Qt3D.Render::Camera::projectionMatrix |
348 | * Holds the current projection matrix of the camera. |
349 | */ |
350 | |
351 | /*! |
352 | * \qmlproperty real Qt3D.Render::Camera::exposure |
353 | * Holds the current exposure of the camera. |
354 | * |
355 | * The default value is 0.0. |
356 | * |
357 | * The MetalRoughMaterial in Qt 3D Extras is currently the only provided |
358 | * material that makes use of camera exposure. Negative values will cause |
359 | * the material to be darker, and positive values will cause it to be lighter. |
360 | * |
361 | * Custom materials may choose to interpret the value differently. |
362 | */ |
363 | |
364 | /*! |
365 | * \qmlproperty vector3d Qt3D.Render::Camera::position |
366 | * Holds the current position of the camera in coordinates relative to |
367 | * the parent entity. |
368 | */ |
369 | |
370 | /*! |
371 | * \qmlproperty vector3d Qt3D.Render::Camera::upVector |
372 | * Holds the current up vector of the camera in coordinates relative to |
373 | * the parent entity. |
374 | * |
375 | * The up vector indicates which direction the top of the camera is |
376 | * facing. Think of taking a picture: after positioning yourself |
377 | * and pointing the camera at your target, you might rotate the camera |
378 | * left or right, giving you a portrait or landscape (or angled!) |
379 | * shot. upVector allows you to control this type of movement. |
380 | */ |
381 | |
382 | /*! |
383 | * \qmlproperty vector3d Qt3D.Render::Camera::viewCenter |
384 | * Holds the current view center of the camera in coordinates relative to |
385 | * the parent entity. |
386 | * |
387 | * Intuitively, the viewCenter is the location the camera is pointing at. |
388 | */ |
389 | |
390 | /*! |
391 | * \qmlproperty vector3d Qt3D.Render::Camera::viewVector |
392 | * Holds the camera's view vector in coordinates relative to |
393 | * the parent entity. |
394 | * |
395 | * This vector decribes the displacement from the camera (\l position) |
396 | * to its target (\l viewCenter). |
397 | * \readonly |
398 | */ |
399 | |
400 | /*! |
401 | * \qmlproperty matrix4x4 Qt3D.Render::Camera::viewMatrix |
402 | * \deprecated |
403 | * Holds the camera's view matrix in coordinates relative |
404 | * to the parent entity. |
405 | * \readonly |
406 | */ |
407 | |
408 | /*! |
409 | * \property QCamera::projectionType |
410 | * |
411 | * Holds the type of the camera projection. The default value is |
412 | * QCameraLens::PerspectiveProjection. |
413 | * |
414 | * \list |
415 | * \li QCameraLens::OrthographicProjection - Parallel lines appear parallel. Objects appear |
416 | * the same size regardless of distance. |
417 | * \li QCameraLens::PerspectiveProjection - Parallel lines appear to meet in the distance. |
418 | * Objects appear to shrink the farther they are from the camera. |
419 | * \li QCameraLens::FrustumProjection |
420 | * \li QCameraLens::CustomProjection |
421 | * \endlist |
422 | * \sa Qt3DRender::QCameraLens::ProjectionType |
423 | */ |
424 | |
425 | /*! |
426 | * \property QCamera::nearPlane |
427 | * Holds the current camera near plane. Objects that are closer to the |
428 | * camera than the nearPlane will not be rendered. |
429 | */ |
430 | |
431 | /*! |
432 | * \property QCamera::farPlane |
433 | * Holds the current camera far plane. Objects that are farther from the |
434 | * camera than the farPlane will not be rendered. |
435 | */ |
436 | |
437 | /*! |
438 | * \property QCamera::lens |
439 | * Holds the Qt3DRender::QCameraLens component of the camera. |
440 | * \since 5.14 |
441 | */ |
442 | |
443 | /*! |
444 | * \property QCamera::transform |
445 | * Holds the Qt3DCore::QTransform component of the camera. |
446 | * \since 5.14 |
447 | */ |
448 | |
449 | /*! |
450 | * \property QCamera::fieldOfView |
451 | * Holds the current vertical field of view in degrees. |
452 | * |
453 | * Along with \l aspectRatio, this property determines how much of |
454 | * the scene is visible to the camera. In that respect you might |
455 | * think of it as analogous to choosing a wide angle (wide horizontal |
456 | * field of view) or telephoto (narrow horizontal field of view) lens |
457 | * depending on how much of a scene you want to capture. |
458 | * |
459 | * fieldOfView is only relevant when \l projectionType is |
460 | * QCameraLens::PerspectiveProjection. |
461 | */ |
462 | |
463 | /*! |
464 | * \property QCamera::aspectRatio |
465 | * Holds the current aspect ratio. |
466 | */ |
467 | |
468 | /*! |
469 | *\property QCamera::left |
470 | * Holds the current left of the camera. |
471 | * |
472 | * This property is only relevant when \l projectionType is |
473 | * QCameraLens::OrthographicProjection. |
474 | */ |
475 | |
476 | /*! |
477 | * \property QCamera::right |
478 | * Holds the current right of the camera. |
479 | * |
480 | * This property is only relevant when \l projectionType is |
481 | * QCameraLens::OrthographicProjection. |
482 | */ |
483 | |
484 | /*! |
485 | * \property QCamera::bottom |
486 | * Holds the current bottom of the camera. |
487 | * |
488 | * This property is only relevant when \l projectionType is |
489 | * QCameraLens::OrthographicProjection. |
490 | */ |
491 | |
492 | /*! |
493 | * \property QCamera::top |
494 | * Holds the current top of the camera. |
495 | * |
496 | * This property is only relevant when \l projectionType is |
497 | * QCameraLens::OrthographicProjection. |
498 | */ |
499 | |
500 | /*! |
501 | * \property QCamera::projectionMatrix |
502 | * Holds the current projection matrix of the camera. |
503 | */ |
504 | |
505 | /*! |
506 | * \property QCamera::exposure |
507 | * Holds the current exposure of the camera. |
508 | * |
509 | * The default value is 0.0. |
510 | * |
511 | * The MetalRoughMaterial in Qt 3D Extras is currently the only provided |
512 | * material that makes use of camera exposure. Negative values will cause |
513 | * the material to be darker, and positive values will cause it to be lighter. |
514 | * |
515 | * Custom materials may choose to interpret the value differently. |
516 | */ |
517 | |
518 | /*! |
519 | * \property QCamera::position |
520 | * Holds the camera's position in coordinates relative to |
521 | * the parent entity. |
522 | */ |
523 | |
524 | /*! |
525 | * \property QCamera::upVector |
526 | * Holds the camera's up vector in coordinates relative to |
527 | * the parent entity. |
528 | * |
529 | * The up vector indicates which direction the top of the camera is |
530 | * facing. Think of taking a picture: after positioning yourself |
531 | * and pointing the camera at your target, you might rotate the camera |
532 | * left or right, giving you a portrait or landscape (or angled!) |
533 | * shot. upVector allows you to control this type of movement. |
534 | */ |
535 | |
536 | /*! |
537 | * \property QCamera::viewCenter |
538 | * Holds the camera's view center in coordinates relative to |
539 | * the parent entity. |
540 | * |
541 | * Intuitively, the viewCenter is the location the camera is pointing at. |
542 | */ |
543 | |
544 | /*! |
545 | * \property QCamera::viewVector |
546 | * Holds the camera's view vector in coordinates relative to |
547 | * the parent entity. |
548 | * |
549 | * This vector decribes the displacement from the camera (\l position) |
550 | * to its target (\l viewCenter). |
551 | */ |
552 | |
553 | /*! |
554 | * \property QCamera::viewMatrix |
555 | * \deprecated |
556 | * Holds the camera's view matrix in coordinates relative to |
557 | * the parent entity. |
558 | */ |
559 | |
560 | /*! |
561 | * Creates a new QCamera instance with the |
562 | * specified \a parent. |
563 | */ |
564 | QCamera::QCamera(Qt3DCore::QNode *parent) |
565 | : Qt3DCore::QEntity(*new QCameraPrivate, parent) |
566 | { |
567 | QObject::connect(sender: d_func()->m_lens, SIGNAL(projectionTypeChanged(QCameraLens::ProjectionType)), receiver: this, SIGNAL(projectionTypeChanged(QCameraLens::ProjectionType))); |
568 | QObject::connect(sender: d_func()->m_lens, SIGNAL(nearPlaneChanged(float)), receiver: this, SIGNAL(nearPlaneChanged(float))); |
569 | QObject::connect(sender: d_func()->m_lens, SIGNAL(farPlaneChanged(float)), receiver: this, SIGNAL(farPlaneChanged(float))); |
570 | QObject::connect(sender: d_func()->m_lens, SIGNAL(fieldOfViewChanged(float)), receiver: this, SIGNAL(fieldOfViewChanged(float))); |
571 | QObject::connect(sender: d_func()->m_lens, SIGNAL(aspectRatioChanged(float)), receiver: this, SIGNAL(aspectRatioChanged(float))); |
572 | QObject::connect(sender: d_func()->m_lens, SIGNAL(leftChanged(float)), receiver: this, SIGNAL(leftChanged(float))); |
573 | QObject::connect(sender: d_func()->m_lens, SIGNAL(rightChanged(float)), receiver: this, SIGNAL(rightChanged(float))); |
574 | QObject::connect(sender: d_func()->m_lens, SIGNAL(bottomChanged(float)), receiver: this, SIGNAL(bottomChanged(float))); |
575 | QObject::connect(sender: d_func()->m_lens, SIGNAL(topChanged(float)), receiver: this, SIGNAL(topChanged(float))); |
576 | QObject::connect(sender: d_func()->m_lens, SIGNAL(projectionMatrixChanged(const QMatrix4x4 &)), receiver: this, SIGNAL(projectionMatrixChanged(const QMatrix4x4 &))); |
577 | QObject::connect(sender: d_func()->m_lens, SIGNAL(exposureChanged(float)), receiver: this, SIGNAL(exposureChanged(float))); |
578 | QObject::connect(sender: d_func()->m_lens, signal: &QCameraLens::viewSphere, receiver: this, slot: &QCamera::viewSphere); |
579 | |
580 | addComponent(comp: d_func()->m_lens); |
581 | addComponent(comp: d_func()->m_transform); |
582 | } |
583 | |
584 | /*! |
585 | * \internal |
586 | */ |
587 | QCamera::~QCamera() |
588 | { |
589 | } |
590 | |
591 | /*! |
592 | * \internal |
593 | */ |
594 | QCamera::QCamera(QCameraPrivate &dd, Qt3DCore::QNode *parent) |
595 | : Qt3DCore::QEntity(dd, parent) |
596 | { |
597 | QObject::connect(sender: d_func()->m_lens, SIGNAL(projectionTypeChanged(QCameraLens::ProjectionType)), receiver: this, SIGNAL(projectionTypeChanged(QCameraLens::ProjectionType))); |
598 | QObject::connect(sender: d_func()->m_lens, SIGNAL(nearPlaneChanged(float)), receiver: this, SIGNAL(nearPlaneChanged(float))); |
599 | QObject::connect(sender: d_func()->m_lens, SIGNAL(farPlaneChanged(float)), receiver: this, SIGNAL(farPlaneChanged(float))); |
600 | QObject::connect(sender: d_func()->m_lens, SIGNAL(fieldOfViewChanged(float)), receiver: this, SIGNAL(fieldOfViewChanged(float))); |
601 | QObject::connect(sender: d_func()->m_lens, SIGNAL(aspectRatioChanged(float)), receiver: this, SIGNAL(aspectRatioChanged(float))); |
602 | QObject::connect(sender: d_func()->m_lens, SIGNAL(leftChanged(float)), receiver: this, SIGNAL(leftChanged(float))); |
603 | QObject::connect(sender: d_func()->m_lens, SIGNAL(rightChanged(float)), receiver: this, SIGNAL(rightChanged(float))); |
604 | QObject::connect(sender: d_func()->m_lens, SIGNAL(bottomChanged(float)), receiver: this, SIGNAL(bottomChanged(float))); |
605 | QObject::connect(sender: d_func()->m_lens, SIGNAL(topChanged(float)), receiver: this, SIGNAL(topChanged(float))); |
606 | QObject::connect(sender: d_func()->m_lens, SIGNAL(projectionMatrixChanged(const QMatrix4x4 &)), receiver: this, SIGNAL(projectionMatrixChanged(const QMatrix4x4 &))); |
607 | QObject::connect(sender: d_func()->m_lens, signal: &QCameraLens::viewSphere, receiver: this, slot: &QCamera::viewSphere); |
608 | |
609 | addComponent(comp: d_func()->m_lens); |
610 | addComponent(comp: d_func()->m_transform); |
611 | } |
612 | |
613 | /*! |
614 | * Returns the current lens. |
615 | */ |
616 | 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 | */ |
625 | 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 | */ |
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(f: vLocal.x())) { |
642 | // Calculate the vector for the local x axis |
643 | const QVector3D x = QVector3D::crossProduct(v1: viewVector, v2: upVector()).normalized(); |
644 | vWorld += vLocal.x() * x; |
645 | } |
646 | |
647 | if (!qFuzzyIsNull(f: vLocal.y())) |
648 | vWorld += vLocal.y() * upVector(); |
649 | |
650 | if (!qFuzzyIsNull(f: vLocal.z())) |
651 | vWorld += vLocal.z() * viewVector.normalized(); |
652 | |
653 | // Update the camera position using the calculated world vector |
654 | setPosition(position() + vWorld); |
655 | |
656 | // May be also update the view center coordinates |
657 | if (option == TranslateViewCenter) |
658 | setViewCenter(viewCenter() + vWorld); |
659 | |
660 | // Refresh the camera -> view center vector |
661 | viewVector = viewCenter() - position(); |
662 | |
663 | // Calculate a new up vector. We do this by: |
664 | // 1) Calculate a new local x-direction vector from the cross product of the new |
665 | // camera to view center vector and the old up vector. |
666 | // 2) The local x vector is the normal to the plane in which the new up vector |
667 | // must lay. So we can take the cross product of this normal and the new |
668 | // x vector. The new normal vector forms the last part of the orthonormal basis |
669 | const QVector3D x = QVector3D::crossProduct(v1: viewVector, v2: upVector()).normalized(); |
670 | setUpVector(QVector3D::crossProduct(v1: x, v2: viewVector).normalized()); |
671 | } |
672 | |
673 | /*! |
674 | * Translates the camera's position and its view vector by \a vWorld in world coordinates. |
675 | * The \a option allows for toggling whether the view center should be translated. |
676 | */ |
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 | */ |
691 | QQuaternion QCamera::tiltRotation(float angle) const |
692 | { |
693 | const QVector3D viewVector = viewCenter() - position(); |
694 | const QVector3D xBasis = QVector3D::crossProduct(v1: upVector(), v2: viewVector.normalized()).normalized(); |
695 | return QQuaternion::fromAxisAndAngle(axis: xBasis, angle: -angle); |
696 | } |
697 | |
698 | /*! |
699 | * Returns the calculated pan rotation in relation to the \a angle in degrees taken in |
700 | * to adjust the camera's pan or left/right rotation on the Y axis. |
701 | */ |
702 | QQuaternion QCamera::panRotation(float angle) const |
703 | { |
704 | return QQuaternion::fromAxisAndAngle(axis: upVector(), angle); |
705 | } |
706 | |
707 | /*! |
708 | * Returns the calculated roll rotation in relation to the \a angle in degrees taken in |
709 | * to adjust the camera's roll or lean left/right rotation on the Z axis. |
710 | */ |
711 | QQuaternion QCamera::rollRotation(float angle) const |
712 | { |
713 | QVector3D viewVector = viewCenter() - position(); |
714 | return QQuaternion::fromAxisAndAngle(axis: viewVector, angle: -angle); |
715 | } |
716 | |
717 | /*! |
718 | * Returns the calculated rotation in relation to the \a angle in degrees and |
719 | * chosen \a axis taken in. |
720 | */ |
721 | 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 | */ |
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 | */ |
738 | void QCamera::pan(float angle) |
739 | { |
740 | QQuaternion q = panRotation(angle: -angle); |
741 | rotate(q); |
742 | } |
743 | |
744 | /*! |
745 | * Adjusts the pan angle of the camera by \a angle in degrees on a chosen \a axis. |
746 | */ |
747 | void QCamera::pan(float angle, const QVector3D &axis) |
748 | { |
749 | QQuaternion q = rotation(angle: -angle, axis); |
750 | rotate(q); |
751 | } |
752 | |
753 | /*! |
754 | * Adjusts the camera roll by \a angle in degrees. |
755 | */ |
756 | void QCamera::roll(float angle) |
757 | { |
758 | QQuaternion q = rollRotation(angle: -angle); |
759 | rotate(q); |
760 | } |
761 | |
762 | /*! |
763 | * Adjusts the camera tilt about view center by \a angle in degrees. |
764 | */ |
765 | void QCamera::tiltAboutViewCenter(float angle) |
766 | { |
767 | QQuaternion q = tiltRotation(angle: -angle); |
768 | rotateAboutViewCenter(q); |
769 | } |
770 | |
771 | /*! |
772 | * Adjusts the camera pan about view center by \a angle in degrees. |
773 | */ |
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 | */ |
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 | */ |
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 | */ |
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 | */ |
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 | */ |
829 | void QCamera::viewAll() |
830 | { |
831 | Q_D(QCamera); |
832 | d->m_lens->viewAll(cameraId: id()); |
833 | } |
834 | |
835 | /*! |
836 | * Rotates and moves the camera so that it's viewCenter is \a center |
837 | * and a sphere of \a radius fits in the view port. |
838 | * |
839 | * \note Only works if the lens is in perspective or orthographic projection mode. |
840 | * \sa Qt3D.Render::Camera::projectionType |
841 | */ |
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(x: qDegreesToRadians(degrees: d->m_lens->fieldOfView()) / 2.0f); |
855 | } |
856 | else if (d->m_lens->projectionType() == QCameraLens::OrthographicProjection) { |
857 | d->m_lens->setOrthographicProjection(left: -height * d->m_lens->aspectRatio(), right: height * d->m_lens->aspectRatio(), bottom: -height, top: height, |
858 | nearPlane: nearPlane(), farPlane: farPlane()); |
859 | dist = height / std::sin(x: qDegreesToRadians(degrees: d->m_lens->fieldOfView()) / 2.0f); |
860 | } |
861 | else { |
862 | dist = (d->m_viewCenter - d->m_position).length(); |
863 | } |
864 | QVector3D dir = (d->m_viewCenter - d->m_position).normalized(); |
865 | QVector3D newPos = center - (dir * dist); |
866 | setViewCenter(center); |
867 | setPosition(newPos); |
868 | } |
869 | |
870 | /*! |
871 | * Rotates and moves the camera so that it's viewCenter is the center of the |
872 | * \a {entity}'s bounding volume and the entire entity fits in the view port. |
873 | * |
874 | * \note Only works if the lens is in perspective or orthographic projection mode. |
875 | * \sa {Qt3D.Render::Camera::projectionType}{Camera.projectionType} |
876 | */ |
877 | void QCamera::viewEntity(Qt3DCore::QEntity *entity) |
878 | { |
879 | if (!entity) |
880 | return; |
881 | |
882 | Q_D(QCamera); |
883 | d->m_lens->viewEntity(entityId: entity->id(), cameraId: id()); |
884 | } |
885 | |
886 | /*! |
887 | * Sets the camera's projection type to \a type. |
888 | */ |
889 | void QCamera::setProjectionType(QCameraLens::ProjectionType type) |
890 | { |
891 | Q_D(QCamera); |
892 | d->m_lens->setProjectionType(type); |
893 | } |
894 | |
895 | 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 | */ |
904 | void QCamera::setNearPlane(float nearPlane) |
905 | { |
906 | Q_D(QCamera); |
907 | d->m_lens->setNearPlane(nearPlane); |
908 | } |
909 | |
910 | 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 | */ |
919 | void QCamera::setFarPlane(float farPlane) |
920 | { |
921 | Q_D(QCamera); |
922 | d->m_lens->setFarPlane(farPlane); |
923 | } |
924 | |
925 | 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 | */ |
934 | void QCamera::setFieldOfView(float fieldOfView) |
935 | { |
936 | Q_D(QCamera); |
937 | d->m_lens->setFieldOfView(fieldOfView); |
938 | } |
939 | |
940 | 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 | */ |
949 | void QCamera::setAspectRatio(float aspectRatio) |
950 | { |
951 | Q_D(QCamera); |
952 | d->m_lens->setAspectRatio(aspectRatio); |
953 | } |
954 | |
955 | 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 | */ |
964 | void QCamera::setLeft(float left) |
965 | { |
966 | Q_D(QCamera); |
967 | d->m_lens->setLeft(left); |
968 | } |
969 | |
970 | 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 | */ |
979 | void QCamera::setRight(float right) |
980 | { |
981 | Q_D(QCamera); |
982 | d->m_lens->setRight(right); |
983 | } |
984 | |
985 | 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 | */ |
994 | void QCamera::setBottom(float bottom) |
995 | { |
996 | Q_D(QCamera); |
997 | d->m_lens->setBottom(bottom); |
998 | } |
999 | |
1000 | 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 | */ |
1009 | void QCamera::setTop(float top) |
1010 | { |
1011 | Q_D(QCamera); |
1012 | d->m_lens->setTop(top); |
1013 | } |
1014 | |
1015 | 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 | */ |
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 | */ |
1033 | void QCamera::setExposure(float exposure) |
1034 | { |
1035 | Q_D(QCamera); |
1036 | d->m_lens->setExposure(exposure); |
1037 | } |
1038 | |
1039 | QMatrix4x4 QCamera::projectionMatrix() const |
1040 | { |
1041 | Q_D(const QCamera); |
1042 | return d->m_lens->projectionMatrix(); |
1043 | } |
1044 | |
1045 | 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 | */ |
1054 | void QCamera::setPosition(const QVector3D &position) |
1055 | { |
1056 | Q_D(QCamera); |
1057 | if (!qFuzzyCompare(v1: d->m_position, v2: position)) { |
1058 | d->m_position = position; |
1059 | d->m_cameraToCenter = d->m_viewCenter - position; |
1060 | d->m_viewMatrixDirty = true; |
1061 | emit positionChanged(position); |
1062 | emit viewVectorChanged(viewVector: d->m_cameraToCenter); |
1063 | d->updateViewMatrixAndTransform(); |
1064 | } |
1065 | } |
1066 | |
1067 | 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 | */ |
1076 | void QCamera::setUpVector(const QVector3D &upVector) |
1077 | { |
1078 | Q_D(QCamera); |
1079 | if (!qFuzzyCompare(v1: d->m_upVector, v2: upVector)) { |
1080 | d->m_upVector = upVector; |
1081 | d->m_viewMatrixDirty = true; |
1082 | emit upVectorChanged(upVector); |
1083 | d->updateViewMatrixAndTransform(); |
1084 | } |
1085 | } |
1086 | |
1087 | 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 | */ |
1096 | void QCamera::setViewCenter(const QVector3D &viewCenter) |
1097 | { |
1098 | Q_D(QCamera); |
1099 | if (!qFuzzyCompare(v1: d->m_viewCenter, v2: viewCenter)) { |
1100 | d->m_viewCenter = viewCenter; |
1101 | d->m_cameraToCenter = viewCenter - d->m_position; |
1102 | d->m_viewMatrixDirty = true; |
1103 | emit viewCenterChanged(viewCenter); |
1104 | emit viewVectorChanged(viewVector: d->m_cameraToCenter); |
1105 | d->updateViewMatrixAndTransform(); |
1106 | } |
1107 | } |
1108 | |
1109 | QVector3D QCamera::viewCenter() const |
1110 | { |
1111 | Q_D(const QCamera); |
1112 | return d->m_viewCenter; |
1113 | } |
1114 | |
1115 | QVector3D QCamera::viewVector() const |
1116 | { |
1117 | Q_D(const QCamera); |
1118 | return d->m_cameraToCenter; |
1119 | } |
1120 | |
1121 | 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 | |