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

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