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 | |
7 | QT_BEGIN_NAMESPACE |
8 | |
9 | namespace 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 | */ |
180 | QCameraLensPrivate::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 | |
196 | void 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 | |
205 | void 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 | |
214 | void QCameraLensPrivate::processViewAllResult(Qt3DCore::QNodeId requestId, const QVector3D ¢er, 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 | */ |
227 | QCameraLens::QCameraLens(QNode *parent) |
228 | : Qt3DCore::QComponent(*new QCameraLensPrivate, parent) |
229 | { |
230 | Q_D(QCameraLens); |
231 | d->updateProjectionMatrix(); |
232 | } |
233 | |
234 | /*! \internal */ |
235 | QCameraLens::~QCameraLens() |
236 | { |
237 | } |
238 | |
239 | QCameraLens::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 | */ |
253 | void 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 | |
267 | QCameraLens::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 | */ |
277 | void 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 | */ |
298 | void 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 | */ |
319 | void 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 | */ |
337 | void 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 | |
351 | float 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 | */ |
361 | void 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 | |
375 | float 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 | */ |
388 | void 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 | |
402 | float 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 | */ |
415 | void 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 | |
429 | float 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 | */ |
442 | void 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 | |
456 | float 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 | */ |
469 | void 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 | |
483 | float 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 | */ |
496 | void 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 | |
510 | float 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 | */ |
523 | void 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 | |
537 | float 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 | */ |
549 | void 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 | |
559 | QMatrix4x4 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 | */ |
568 | void 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 | |
578 | float QCameraLens::exposure() const |
579 | { |
580 | Q_D(const QCameraLens); |
581 | return d->m_exposure; |
582 | } |
583 | |
584 | } // Qt3DRender |
585 | |
586 | QT_END_NAMESPACE |
587 | |
588 | #include "moc_qcameralens.cpp" |
589 | |