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 | |
9 | QT_BEGIN_NAMESPACE |
10 | |
11 | namespace Qt3DRender { |
12 | |
13 | /*! |
14 | * \internal |
15 | */ |
16 | QCameraPrivate::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 | |
29 | void 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 | */ |
528 | QCamera::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 | */ |
551 | QCamera::~QCamera() |
552 | { |
553 | } |
554 | |
555 | /*! |
556 | * \internal |
557 | */ |
558 | QCamera::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 | */ |
580 | QCameraLens *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 | */ |
589 | Qt3DCore::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 | */ |
599 | void 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 | */ |
641 | void 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 | */ |
655 | QQuaternion 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 | */ |
666 | QQuaternion 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 | */ |
675 | QQuaternion 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 | */ |
685 | QQuaternion 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 | */ |
693 | void 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 | */ |
702 | void 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 | */ |
711 | void 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 | */ |
720 | void 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 | */ |
729 | void 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 | */ |
738 | void 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 | */ |
747 | void 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 | */ |
756 | void 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 | */ |
765 | void 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 | */ |
777 | void 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 | */ |
793 | void 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 | */ |
806 | void QCamera::viewSphere(const QVector3D ¢er, 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 | */ |
841 | void 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 | */ |
853 | void QCamera::setProjectionType(QCameraLens::ProjectionType type) |
854 | { |
855 | Q_D(QCamera); |
856 | d->m_lens->setProjectionType(type); |
857 | } |
858 | |
859 | QCameraLens::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 | */ |
868 | void QCamera::setNearPlane(float nearPlane) |
869 | { |
870 | Q_D(QCamera); |
871 | d->m_lens->setNearPlane(nearPlane); |
872 | } |
873 | |
874 | float 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 | */ |
883 | void QCamera::setFarPlane(float farPlane) |
884 | { |
885 | Q_D(QCamera); |
886 | d->m_lens->setFarPlane(farPlane); |
887 | } |
888 | |
889 | float 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 | */ |
898 | void QCamera::setFieldOfView(float fieldOfView) |
899 | { |
900 | Q_D(QCamera); |
901 | d->m_lens->setFieldOfView(fieldOfView); |
902 | } |
903 | |
904 | float 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 | */ |
913 | void QCamera::setAspectRatio(float aspectRatio) |
914 | { |
915 | Q_D(QCamera); |
916 | d->m_lens->setAspectRatio(aspectRatio); |
917 | } |
918 | |
919 | float 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 | */ |
928 | void QCamera::setLeft(float left) |
929 | { |
930 | Q_D(QCamera); |
931 | d->m_lens->setLeft(left); |
932 | } |
933 | |
934 | float 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 | */ |
943 | void QCamera::setRight(float right) |
944 | { |
945 | Q_D(QCamera); |
946 | d->m_lens->setRight(right); |
947 | } |
948 | |
949 | float 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 | */ |
958 | void QCamera::setBottom(float bottom) |
959 | { |
960 | Q_D(QCamera); |
961 | d->m_lens->setBottom(bottom); |
962 | } |
963 | |
964 | float 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 | */ |
973 | void QCamera::setTop(float top) |
974 | { |
975 | Q_D(QCamera); |
976 | d->m_lens->setTop(top); |
977 | } |
978 | |
979 | float 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 | */ |
988 | void 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 | */ |
997 | void QCamera::setExposure(float exposure) |
998 | { |
999 | Q_D(QCamera); |
1000 | d->m_lens->setExposure(exposure); |
1001 | } |
1002 | |
1003 | QMatrix4x4 QCamera::projectionMatrix() const |
1004 | { |
1005 | Q_D(const QCamera); |
1006 | return d->m_lens->projectionMatrix(); |
1007 | } |
1008 | |
1009 | float 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 | */ |
1018 | void 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 | |
1031 | QVector3D 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 | */ |
1040 | void 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 | |
1051 | QVector3D 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 | */ |
1060 | void 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 | |
1073 | QVector3D QCamera::viewCenter() const |
1074 | { |
1075 | Q_D(const QCamera); |
1076 | return d->m_viewCenter; |
1077 | } |
1078 | |
1079 | QVector3D QCamera::viewVector() const |
1080 | { |
1081 | Q_D(const QCamera); |
1082 | return d->m_cameraToCenter; |
1083 | } |
1084 | |
1085 | QMatrix4x4 QCamera::viewMatrix() const |
1086 | { |
1087 | Q_D(const QCamera); |
1088 | return d->m_viewMatrix; |
1089 | } |
1090 | |
1091 | } // Qt3DRender |
1092 | |
1093 | QT_END_NAMESPACE |
1094 | |
1095 | #include "moc_qcamera.cpp" |
1096 | |