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
43QT_BEGIN_NAMESPACE
44
45namespace 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 */
216QCameraLensPrivate::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
232void 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
241void 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
250void QCameraLensPrivate::processViewAllResult(Qt3DCore::QNodeId requestId, const QVector3D &center, 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 */
263QCameraLens::QCameraLens(QNode *parent)
264 : Qt3DCore::QComponent(*new QCameraLensPrivate, parent)
265{
266 Q_D(QCameraLens);
267 d->updateProjectionMatrix();
268}
269
270/*! \internal */
271QCameraLens::~QCameraLens()
272{
273}
274
275QCameraLens::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 */
289void 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
303QCameraLens::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 */
313void 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 */
334void 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 */
355void 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 */
373void 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
387float 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 */
397void 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
411float 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 */
424void 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
438float 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 */
451void 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
465float 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 */
478void 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
492float 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 */
505void 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
519float 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 */
532void 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
546float 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 */
559void 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
573float 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 */
585void 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
595QMatrix4x4 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 */
604void 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
614float QCameraLens::exposure() const
615{
616 Q_D(const QCameraLens);
617 return d->m_exposure;
618}
619
620Qt3DCore::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
629void QCameraLens::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
630{
631 Q_UNUSED(change)
632}
633
634} // Qt3DRender
635
636QT_END_NAMESPACE
637

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