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 "qcameralens.h" |
41 | #include "qcameralens_p.h" |
42 | |
43 | QT_BEGIN_NAMESPACE |
44 | |
45 | namespace Qt3DRender { |
46 | |
47 | /*! |
48 | * \class Qt3DRender::QCameraLens |
49 | * \inheaderfile Qt3DRender/QCameraLens |
50 | * \inmodule Qt3DRender |
51 | * |
52 | * \brief Qt3DRender::QCameraLens specifies the projection matrix that will be used to |
53 | * define a Camera for a 3D scene. |
54 | * |
55 | * \since 5.5 |
56 | */ |
57 | |
58 | /*! |
59 | * \qmltype CameraLens |
60 | * \instantiates Qt3DRender::QCameraLens |
61 | * \inqmlmodule Qt3D.Render |
62 | * \inherits Component3D |
63 | * \since 5.5 |
64 | * \brief Provides the projection matrix that is used to define a Camera for 3D scene. |
65 | */ |
66 | |
67 | /*! |
68 | * \enum Qt3DRender::QCameraLens::ProjectionType |
69 | * |
70 | * Specifies which parameters of Qt3DRender::QCameraLens are used to compute the projection matrix. |
71 | * |
72 | * \value OrthographicProjection Orthogonal projection |
73 | * \value PerspectiveProjection Perspective projection |
74 | * \value FrustumProjection Frustum projection |
75 | * \value CustomProjection Custom user-defined projection |
76 | */ |
77 | |
78 | /*! |
79 | * \qmlproperty enumeration CameraLens::projectionType |
80 | * |
81 | * Holds the type of the camera projection. |
82 | * |
83 | * \list |
84 | * \li CameraLens.OrthographicProjection |
85 | * \li CameraLens.PerspectiveProjection |
86 | * \li CameraLens.FrustumProjection |
87 | * \li CameraLens.CustomProjection |
88 | * \endlist |
89 | * \sa Qt3DRender::QCameraLens::ProjectionType |
90 | */ |
91 | |
92 | /*! |
93 | * \qmlproperty real CameraLens::nearPlane |
94 | * Holds the current near plane of the camera lens. |
95 | */ |
96 | |
97 | /*! |
98 | * \qmlproperty real CameraLens::farPlane |
99 | * Holds the current near plane of the camera lens. |
100 | */ |
101 | |
102 | /*! |
103 | * \qmlproperty real CameraLens::fieldOfView |
104 | * Holds the current field of view of the camera lens in degrees. |
105 | */ |
106 | |
107 | /*! |
108 | * \qmlproperty real CameraLens::aspectRatio |
109 | * Holds the current aspect ratio of the camera lens. |
110 | */ |
111 | |
112 | /*! |
113 | * \qmlproperty real CameraLens::left |
114 | * Holds the current left plane of the camera lens. |
115 | */ |
116 | |
117 | /*! |
118 | * \qmlproperty real CameraLens::right |
119 | * Holds the current right plane of the camera lens. |
120 | */ |
121 | |
122 | /*! |
123 | * \qmlproperty real CameraLens::bottom |
124 | * Holds the current bottom plane of the camera lens. |
125 | */ |
126 | |
127 | /*! |
128 | * \qmlproperty real CameraLens::top |
129 | * Holds the current top plane of the camera lens. |
130 | */ |
131 | |
132 | /*! |
133 | * \qmlproperty matrix4x4 CameraLens::projectionMatrix |
134 | * Holds the current projection matrix of the camera lens. |
135 | * |
136 | * \note This will set the projection type to |
137 | * Qt3DRender::QCameraLens::CustomProjection and thus ignore all other camera |
138 | * parameters that might have been specified. |
139 | * \readonly |
140 | */ |
141 | |
142 | |
143 | /*! |
144 | * \property QCameraLens::projectionType |
145 | * |
146 | * Holds the type of the camera projection. |
147 | * \sa Qt3DRender::QCameraLens::ProjectionType |
148 | */ |
149 | |
150 | /*! |
151 | * \property QCameraLens::nearPlane |
152 | * Holds the current near plane of the camera lens. |
153 | */ |
154 | |
155 | /*! |
156 | * \property QCameraLens::farPlane |
157 | * Holds the current near plane of the camera lens. |
158 | */ |
159 | |
160 | /*! |
161 | * \property QCameraLens::fieldOfView |
162 | * Holds the current field of view of the camera lens. |
163 | * \note: The return value may be undefined if the projection type is not |
164 | * Qt3DRender::QCameraLens::PerspectiveProjection. |
165 | */ |
166 | |
167 | /*! |
168 | * \property QCameraLens::aspectRatio |
169 | * Holds the current aspect ratio of the camera lens. |
170 | * \note: The return value may be undefined if the projection type is not |
171 | * Qt3DRender::QCameraLens::PerspectiveProjection. |
172 | */ |
173 | |
174 | /*! |
175 | * \property QCameraLens::left |
176 | * Holds the current left plane of the camera lens. |
177 | * \note The return value may be undefined if the projection type is |
178 | * Qt3DRender::QCameraLens::PerspectiveProjection. |
179 | */ |
180 | |
181 | /*! |
182 | * \property QCameraLens::right |
183 | * Holds the current right plane of the camera lens. |
184 | * \note The return value may be undefined if the projection type is |
185 | * Qt3DRender::QCameraLens::PerspectiveProjection. |
186 | */ |
187 | |
188 | /*! |
189 | * \property QCameraLens::bottom |
190 | * Holds the current bottom plane of the camera lens. |
191 | * \note The return value may be undefined if the projection type is |
192 | * Qt3DRender::QCameraLens::PerspectiveProjection. |
193 | */ |
194 | |
195 | /*! |
196 | * \property QCameraLens::top |
197 | * Holds the current top plane of the camera lens. |
198 | * \note The return value may be undefined if the projection type is |
199 | * Qt3DRender::QCameraLens::PerspectiveProjection. |
200 | */ |
201 | |
202 | /*! |
203 | * \property QCameraLens::projectionMatrix |
204 | * Holds the current projection matrix of the camera lens. |
205 | * \readonly |
206 | */ |
207 | |
208 | /*! |
209 | * \property QCameraLens::exposure |
210 | * Holds the current exposure of the camera lens. |
211 | */ |
212 | |
213 | /*! |
214 | * \internal |
215 | */ |
216 | QCameraLensPrivate::QCameraLensPrivate() |
217 | : Qt3DCore::QComponentPrivate() |
218 | , m_projectionType(QCameraLens::PerspectiveProjection) |
219 | , m_nearPlane(0.1f) |
220 | , m_farPlane(1024.0f) |
221 | , m_fieldOfView(25.0f) |
222 | , m_aspectRatio(1.0f) |
223 | , m_left(-0.5f) |
224 | , m_right(0.5f) |
225 | , m_bottom(-0.5f) |
226 | , m_top(0.5f) |
227 | , m_exposure(0.0f) |
228 | { |
229 | } |
230 | |
231 | |
232 | void QCameraLens::viewAll(Qt3DCore::QNodeId cameraId) |
233 | { |
234 | Q_D(QCameraLens); |
235 | if (d->m_projectionType == PerspectiveProjection || d->m_projectionType == OrthographicProjection) { |
236 | d->m_pendingViewAllRequest = {.requestId: Qt3DCore::QNodeId::createId(), .cameraId: cameraId, .entityId: {}}; |
237 | d->update(); |
238 | } |
239 | } |
240 | |
241 | void QCameraLens::viewEntity(Qt3DCore::QNodeId entityId, Qt3DCore::QNodeId cameraId) |
242 | { |
243 | Q_D(QCameraLens); |
244 | if (d->m_projectionType == PerspectiveProjection || d->m_projectionType == OrthographicProjection) { |
245 | d->m_pendingViewAllRequest = {.requestId: Qt3DCore::QNodeId::createId(), .cameraId: cameraId, .entityId: entityId}; |
246 | d->update(); |
247 | } |
248 | } |
249 | |
250 | void QCameraLensPrivate::processViewAllResult(Qt3DCore::QNodeId requestId, const QVector3D ¢er, float radius) |
251 | { |
252 | Q_Q(QCameraLens); |
253 | if (!m_pendingViewAllRequest || m_pendingViewAllRequest.requestId != requestId) |
254 | return; |
255 | |
256 | Q_EMIT q->viewSphere(center, radius); |
257 | m_pendingViewAllRequest = {}; |
258 | } |
259 | |
260 | /*! |
261 | * Constructs a QCameraLens with given \a parent |
262 | */ |
263 | QCameraLens::QCameraLens(QNode *parent) |
264 | : Qt3DCore::QComponent(*new QCameraLensPrivate, parent) |
265 | { |
266 | Q_D(QCameraLens); |
267 | d->updateProjectionMatrix(); |
268 | } |
269 | |
270 | /*! \internal */ |
271 | QCameraLens::~QCameraLens() |
272 | { |
273 | } |
274 | |
275 | QCameraLens::QCameraLens(QCameraLensPrivate &dd, QNode *parent) |
276 | : QComponent(dd, parent) |
277 | { |
278 | Q_D(QCameraLens); |
279 | d->updateOrthographicProjection(); |
280 | } |
281 | |
282 | /*! |
283 | * Sets the lens' projection type \a projectionType. |
284 | * |
285 | * \note Qt3DRender::QCameraLens::Frustum and |
286 | * Qt3DRender::QCameraLens::PerspectiveProjection are two different ways of |
287 | * specifying the same projection. |
288 | */ |
289 | void QCameraLens::setProjectionType(QCameraLens::ProjectionType projectionType) |
290 | { |
291 | Q_D(QCameraLens); |
292 | if (d->m_projectionType != projectionType) { |
293 | d->m_projectionType = projectionType; |
294 | |
295 | const bool wasBlocked = blockNotifications(block: true); |
296 | emit projectionTypeChanged(projectionType); |
297 | blockNotifications(block: wasBlocked); |
298 | |
299 | d->updateProjectionMatrix(); |
300 | } |
301 | } |
302 | |
303 | QCameraLens::ProjectionType QCameraLens::projectionType() const |
304 | { |
305 | Q_D(const QCameraLens); |
306 | return d->m_projectionType; |
307 | } |
308 | |
309 | /*! |
310 | * Defines an orthographic projection based on \a left, \a right, \a bottom, \a |
311 | * top, \a nearPlane, \a farPlane. |
312 | */ |
313 | void QCameraLens::setOrthographicProjection(float left, float right, |
314 | float bottom, float top, |
315 | float nearPlane, float farPlane) |
316 | { |
317 | Q_D(QCameraLens); |
318 | bool block = blockNotifications(block: true); |
319 | setLeft(left); |
320 | setRight(right); |
321 | setBottom(bottom); |
322 | setTop(top); |
323 | setNearPlane(nearPlane); |
324 | setFarPlane(farPlane); |
325 | setProjectionType(OrthographicProjection); |
326 | blockNotifications(block); |
327 | d->updateProjectionMatrix(); |
328 | } |
329 | |
330 | /*! |
331 | * Defines an orthographic projection based on \a left, \a right, \a bottom, \a |
332 | * top, \a nearPlane, \a farPlane. |
333 | */ |
334 | void QCameraLens::setFrustumProjection(float left, float right, |
335 | float bottom, float top, |
336 | float nearPlane, float farPlane) |
337 | { |
338 | Q_D(QCameraLens); |
339 | bool block = blockNotifications(block: true); |
340 | setLeft(left); |
341 | setRight(right); |
342 | setBottom(bottom); |
343 | setTop(top); |
344 | setNearPlane(nearPlane); |
345 | setFarPlane(farPlane); |
346 | setProjectionType(FrustumProjection); |
347 | blockNotifications(block); |
348 | d->updateProjectionMatrix(); |
349 | } |
350 | |
351 | /*! |
352 | * Defines a perspective projection based on \a fieldOfView, \a aspectRatio, \a |
353 | * nearPlane, \a farPlane. |
354 | */ |
355 | void QCameraLens::setPerspectiveProjection(float fieldOfView, float aspectRatio, |
356 | float nearPlane, float farPlane) |
357 | { |
358 | Q_D(QCameraLens); |
359 | bool block = blockNotifications(block: true); |
360 | setFieldOfView(fieldOfView); |
361 | setAspectRatio(aspectRatio); |
362 | setNearPlane(nearPlane); |
363 | setFarPlane(farPlane); |
364 | setProjectionType(PerspectiveProjection); |
365 | blockNotifications(block); |
366 | d->updateProjectionMatrix(); |
367 | } |
368 | |
369 | /*! |
370 | * Sets the projection's near plane to \a nearPlane. This triggers a projection |
371 | * matrix update. |
372 | */ |
373 | void QCameraLens::setNearPlane(float nearPlane) |
374 | { |
375 | Q_D(QCameraLens); |
376 | if (qFuzzyCompare(p1: d->m_nearPlane, p2: nearPlane)) |
377 | return; |
378 | d->m_nearPlane = nearPlane; |
379 | |
380 | const bool wasBlocked = blockNotifications(block: true); |
381 | emit nearPlaneChanged(nearPlane); |
382 | blockNotifications(block: wasBlocked); |
383 | |
384 | d->updateProjectionMatrix(); |
385 | } |
386 | |
387 | float QCameraLens::nearPlane() const |
388 | { |
389 | Q_D(const QCameraLens); |
390 | return d->m_nearPlane; |
391 | } |
392 | |
393 | /*! |
394 | * Sets the projection's far plane to \a farPlane. This triggers a projection |
395 | * matrix update. |
396 | */ |
397 | void QCameraLens::setFarPlane(float farPlane) |
398 | { |
399 | Q_D(QCameraLens); |
400 | if (qFuzzyCompare(p1: d->m_farPlane, p2: farPlane)) |
401 | return; |
402 | d->m_farPlane = farPlane; |
403 | |
404 | const bool wasBlocked = blockNotifications(block: true); |
405 | emit farPlaneChanged(farPlane); |
406 | blockNotifications(block: wasBlocked); |
407 | |
408 | d->updateProjectionMatrix(); |
409 | } |
410 | |
411 | float QCameraLens::farPlane() const |
412 | { |
413 | Q_D(const QCameraLens); |
414 | return d->m_farPlane; |
415 | } |
416 | |
417 | /*! |
418 | * Sets the projection's field of view to \a fieldOfView degrees. This triggers |
419 | * a projection matrix update. |
420 | * |
421 | * \note this has no effect if the projection type is not |
422 | * Qt3DRender::QCameraLens::PerspectiveProjection. |
423 | */ |
424 | void QCameraLens::setFieldOfView(float fieldOfView) |
425 | { |
426 | Q_D(QCameraLens); |
427 | if (qFuzzyCompare(p1: d->m_fieldOfView, p2: fieldOfView)) |
428 | return; |
429 | d->m_fieldOfView = fieldOfView; |
430 | |
431 | const bool wasBlocked = blockNotifications(block: true); |
432 | emit fieldOfViewChanged(fieldOfView); |
433 | blockNotifications(block: wasBlocked); |
434 | |
435 | d->updateProjectionMatrix(); |
436 | } |
437 | |
438 | float QCameraLens::fieldOfView() const |
439 | { |
440 | Q_D(const QCameraLens); |
441 | return d->m_fieldOfView; |
442 | } |
443 | |
444 | /*! |
445 | * Sets the projection's aspect ratio to \a aspectRatio. This triggers a projection |
446 | * matrix update. |
447 | * |
448 | * \note this has no effect if the projection type is not |
449 | * Qt3DRender::QCameraLens::PerspectiveProjection. |
450 | */ |
451 | void QCameraLens::setAspectRatio(float aspectRatio) |
452 | { |
453 | Q_D(QCameraLens); |
454 | if (qFuzzyCompare(p1: d->m_aspectRatio, p2: aspectRatio)) |
455 | return; |
456 | d->m_aspectRatio = aspectRatio; |
457 | |
458 | const bool wasBlocked = blockNotifications(block: true); |
459 | emit aspectRatioChanged(aspectRatio); |
460 | blockNotifications(block: wasBlocked); |
461 | |
462 | d->updateProjectionMatrix(); |
463 | } |
464 | |
465 | float QCameraLens::aspectRatio() const |
466 | { |
467 | Q_D(const QCameraLens); |
468 | return d->m_aspectRatio; |
469 | } |
470 | |
471 | /*! |
472 | * Sets the projection's lower left window coordinate to \a left. This |
473 | * triggers a projection matrix update. |
474 | * |
475 | * \note this has no effect if the projection type is |
476 | * Qt3DRender::QCameraLens::PerspectiveProjection. |
477 | */ |
478 | void QCameraLens::setLeft(float left) |
479 | { |
480 | Q_D(QCameraLens); |
481 | if (qFuzzyCompare(p1: d->m_left, p2: left)) |
482 | return; |
483 | d->m_left = left; |
484 | |
485 | const bool wasBlocked = blockNotifications(block: true); |
486 | emit leftChanged(left); |
487 | blockNotifications(block: wasBlocked); |
488 | |
489 | d->updateProjectionMatrix(); |
490 | } |
491 | |
492 | float QCameraLens::left() const |
493 | { |
494 | Q_D(const QCameraLens); |
495 | return d->m_left; |
496 | } |
497 | |
498 | /*! |
499 | * Sets the projection's upper right window coordinate to \a right. This triggers |
500 | * a projection matrix update. |
501 | * |
502 | * \note this has no effect if the projection type is |
503 | * Qt3DRender::QCameraLens::PerspectiveProjection. |
504 | */ |
505 | void QCameraLens::setRight(float right) |
506 | { |
507 | Q_D(QCameraLens); |
508 | if (qFuzzyCompare(p1: d->m_right, p2: right)) |
509 | return; |
510 | d->m_right = right; |
511 | |
512 | const bool wasBlocked = blockNotifications(block: true); |
513 | emit rightChanged(right); |
514 | blockNotifications(block: wasBlocked); |
515 | |
516 | d->updateProjectionMatrix(); |
517 | } |
518 | |
519 | float QCameraLens::right() const |
520 | { |
521 | Q_D(const QCameraLens); |
522 | return d->m_right; |
523 | } |
524 | |
525 | /*! |
526 | * Sets the projection's bottom window coordinate to \a bottom. This triggers a |
527 | * projection matrix update. |
528 | * |
529 | * \note this has no effect if the projection type is |
530 | * Qt3DRender::QCameraLens::PerspectiveProjection. |
531 | */ |
532 | void QCameraLens::setBottom(float bottom) |
533 | { |
534 | Q_D(QCameraLens); |
535 | if (qFuzzyCompare(p1: d->m_bottom, p2: bottom)) |
536 | return; |
537 | d->m_bottom = bottom; |
538 | |
539 | const bool wasBlocked = blockNotifications(block: true); |
540 | emit bottomChanged(bottom); |
541 | blockNotifications(block: wasBlocked); |
542 | |
543 | d->updateProjectionMatrix(); |
544 | } |
545 | |
546 | float QCameraLens::bottom() const |
547 | { |
548 | Q_D(const QCameraLens); |
549 | return d->m_bottom; |
550 | } |
551 | |
552 | /*! |
553 | * Sets the projection's top window coordinate to \a top. This triggers a |
554 | * projection matrix update. |
555 | * |
556 | * \note this has no effect if the projection type is |
557 | * Qt3DRender::QCameraLens::PerspectiveProjection. |
558 | */ |
559 | void QCameraLens::setTop(float top) |
560 | { |
561 | Q_D(QCameraLens); |
562 | if (qFuzzyCompare(p1: d->m_top, p2: top)) |
563 | return; |
564 | d->m_top = top; |
565 | |
566 | const bool wasBlocked = blockNotifications(block: true); |
567 | emit topChanged(top); |
568 | blockNotifications(block: wasBlocked); |
569 | |
570 | d->updateProjectionMatrix(); |
571 | } |
572 | |
573 | float QCameraLens::top() const |
574 | { |
575 | Q_D(const QCameraLens); |
576 | return d->m_top; |
577 | } |
578 | |
579 | /*! |
580 | * Sets the project matrix to \a projectionMatrix. |
581 | * |
582 | * \note This will set the projection type to Qt3DRender::QCameraLens::CustomProjection and thus |
583 | * ignore all other camera parameters that might have been specified. |
584 | */ |
585 | void QCameraLens::setProjectionMatrix(const QMatrix4x4 &projectionMatrix) |
586 | { |
587 | Q_D(QCameraLens); |
588 | setProjectionType(CustomProjection); |
589 | if (qFuzzyCompare(m1: d->m_projectionMatrix, m2: projectionMatrix)) |
590 | return; |
591 | d->m_projectionMatrix = projectionMatrix; |
592 | emit projectionMatrixChanged(projectionMatrix); |
593 | } |
594 | |
595 | QMatrix4x4 QCameraLens::projectionMatrix() const |
596 | { |
597 | Q_D(const QCameraLens); |
598 | return d->m_projectionMatrix; |
599 | } |
600 | |
601 | /*! |
602 | * Sets the camera lens' \a exposure |
603 | */ |
604 | void QCameraLens::setExposure(float exposure) |
605 | { |
606 | Q_D(QCameraLens); |
607 | if (qFuzzyCompare(p1: d->m_exposure, p2: exposure)) |
608 | return; |
609 | d->m_exposure = exposure; |
610 | |
611 | emit exposureChanged(exposure); |
612 | } |
613 | |
614 | float QCameraLens::exposure() const |
615 | { |
616 | Q_D(const QCameraLens); |
617 | return d->m_exposure; |
618 | } |
619 | |
620 | Qt3DCore::QNodeCreatedChangeBasePtr QCameraLens::createNodeCreationChange() const |
621 | { |
622 | auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QCameraLensData>::create(arguments: this); |
623 | auto &data = creationChange->data; |
624 | data.projectionMatrix = d_func()->m_projectionMatrix; |
625 | data.exposure = d_func()->m_exposure; |
626 | return creationChange; |
627 | } |
628 | |
629 | void QCameraLens::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) |
630 | { |
631 | Q_UNUSED(change) |
632 | } |
633 | |
634 | } // Qt3DRender |
635 | |
636 | QT_END_NAMESPACE |
637 | |