Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qssgrendercamera_p.h
Go to the documentation of this file.
1// Copyright (C) 2008-2012 NVIDIA Corporation.
2// Copyright (C) 2019 The Qt Company Ltd.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
4// Qt-Security score:significant reason:default
5
6
7#ifndef QSSG_RENDER_CAMERA_H
8#define QSSG_RENDER_CAMERA_H
9
10//
11// W A R N I N G
12// -------------
13//
14// This file is not part of the Qt API. It exists purely as an
15// implementation detail. This header file may change from version to
16// version without notice, or even be removed.
17//
18// We mean it.
19//
20
21#include <QtQuick3DRuntimeRender/private/qtquick3druntimerenderglobal_p.h>
22
23#include <QtQuick3DRuntimeRender/private/qssgrendernode_p.h>
24#include <QtQuick3DRuntimeRender/private/qssgrenderray_p.h>
25
26#include <QtQuick3DUtils/private/qssgrenderbasetypes_p.h>
27
28QT_BEGIN_NAMESPACE
29
30struct QSSGCameraGlobalCalculationResult
31{
32 bool m_wasDirty;
33 bool m_computeFrustumSucceeded /* = true */;
34};
35
37{
38 float dpr = 1.0f;
39 float ssaaMultiplier = 1.0f;
40};
41
43{
44public:
45 enum class Orientation
46 {
49 };
50
51 explicit constexpr QSSGRenderCameraFieldOfView(Orientation orientation = Orientation::Vertical) : fovOrientation(orientation) {}
54
56
57 template <Orientation Type = Orientation::Vertical>
59 {
60 return QSSGRenderCameraFieldOfView(fov, FovValue::Degrees, Type);
61 }
62 template <Orientation Type = Orientation::Vertical>
64 {
65 return QSSGRenderCameraFieldOfView(fov, FovValue::Radians, Type);
66 }
67
68 constexpr Orientation orientation() const { return fovOrientation; }
69
70 float degrees() const { return fovDegrees; }
71 float radians() const { return fovRadians; }
72
73 void setDegrees(float fov)
74 {
75 fovDegrees = fov;
76 fovRadians = qDegreesToRadians(fov);
77 }
78
80 {
81 if (fovOrientation == Orientation::Vertical)
82 return *this;
83
84 const float fovV = float(2.0 * qAtan(qTan(qreal(fovRadians) / 2.0) / qreal(aspectRatio)));
85 return fromRadians<Orientation::Vertical>(fovV);
86 }
87
88 void setRadians(float fov)
89 {
90 fovRadians = fov;
91 fovDegrees = qRadiansToDegrees(fov);
92 }
93private:
94 enum class FovValue
95 {
96 Degrees,
97 Radians,
98 };
99 constexpr explicit QSSGRenderCameraFieldOfView(float fov, FovValue value, Orientation angleOfView)
100 : fovDegrees(value == FovValue::Degrees ? fov : qRadiansToDegrees(fov))
101 , fovRadians(value == FovValue::Radians ? fov : qDegreesToRadians(fov))
102 , fovOrientation(angleOfView)
103 {
104 }
105
106 float fovDegrees = 60.0f;
107 float fovRadians = qDegreesToRadians(fovDegrees);
108 Orientation fovOrientation;
109};
110
111class Q_QUICK3DRUNTIMERENDER_EXPORT QSSGRenderCamera : public QSSGRenderNode
112{
113public:
114 using Configuration = QSSGRenderCameraConfiguration;
115 using FieldOfView = QSSGRenderCameraFieldOfView;
116
117 explicit QSSGRenderCamera(QSSGRenderGraphObject::Type type);
118
119 enum class DirtyFlag : quint8
120 {
121 CameraDirty = 0x1,
122 LayerMaskDirty = 0x2,
123 };
124 using FlagT = std::underlying_type_t<DirtyFlag>;
125
126 static constexpr DirtyFlag DirtyMask { std::numeric_limits<FlagT>::max() };
127
128 static constexpr quint32 ReservedLayerMask = 0xFF000000; // The upper 8 bits are reserved for internal use.
129 static constexpr quint32 LayerMaskUserAll = 0x00FFFFFF; // The lower 24 bits are available for user layers.
130 // Default to all layers (user + reserved).
131 static constexpr quint32 LayerMaskAll = LayerMaskUserAll | ReservedLayerMask;
132
133 class ClipPlanes : public QVector2D
134 {
135 public:
136 constexpr inline ClipPlanes() : QVector2D(0.0f, 10000.0f) {}
137 constexpr inline ClipPlanes(float n, float f) : QVector2D(n, f) {}
138 constexpr float clipNear() const noexcept { return x(); }
139 constexpr float clipFar() const noexcept { return y(); }
140
141 constexpr inline void setClipNear(float n) noexcept { setX(n); }
142 constexpr inline void setClipFar(float f) noexcept { setY(f); }
143 };
144
145 class Magnification : public QVector2D
146 {
147 public:
148 constexpr inline Magnification() : QVector2D(1.0f, 1.0f) {}
149 constexpr inline Magnification(float h, float v) : QVector2D(h, v) {}
150 constexpr float horizontal() const noexcept { return x(); }
151 constexpr float vertical() const noexcept { return y(); }
152
153 constexpr inline void setHorizontal(float h) noexcept { setX(h); }
154 constexpr inline void setVertical(float v) noexcept { setY(v); }
155 };
156
157 // Used by the custom frustum camera
158 struct Frustum
159 {
160 float top = 0.0f;
161 float bottom = 0.0f;
162 float left = 0.0f;
163 float right = 0.0f;
164 };
165
166 // Set our position, rotation member variables based on the lookat target
167 // Marks this object as dirty.
168 // Need to test this when the camera's local transform is null.
169 // Assumes parent's local transform is the identity, meaning our local transform is
170 // our global transform.
171 void lookAt(const QVector3D &inCameraPos, const QVector3D &inUpDir, const QVector3D &inTargetPos, const QVector3D &pivot);
172
173 /*!
174 * Convenience function intended for use with internal cameras that's not part of the scene graph!
175 * This function will NOT ensure that the camera's global transform, projection matrix, or state
176 * is updated!.
177 */
178 static bool calculateProjectionInternal(QSSGRenderCamera &camera,
179 const QRectF &inViewport,
180 Configuration config = {});
181
182 /*!
183 * \brief calculateProjection
184 * \param inViewport
185 * \param config
186 * \return true if the projection was successfully calculated, false otherwise.
187 *
188 * This function will calculate the projection matrix for the camera.
189 *
190 * NOTE: This function will not update the camera's global transform. It is the caller's
191 * responsibility to ensure that the camera's global transform has been calculated prior
192 * to calling this function.
193 */
194 bool calculateProjection(const QRectF &inViewport, Configuration config = {});
195
196 void setCustomProjection(const QMatrix4x4 &proj);
197
198 static bool computeFrustumOrtho(QRectF inViewport,
199 QSSGRenderCamera::ClipPlanes clipPlanes,
200 QSSGRenderCamera::Magnification magnification,
201 Configuration config,
202 QMatrix4x4 &outProjection);
203 static bool computeFrustumPerspective(QRectF inViewport,
204 FieldOfView fov,
205 QSSGRenderCamera::ClipPlanes clipPlanes,
206 QMatrix4x4 &outProjection);
207 static bool computeCustomFrustum(QSSGRenderCamera::Frustum frustum,
208 QSSGRenderCamera::ClipPlanes clipPlanes,
209 QMatrix4x4 &outProjection);
210
211 static void calculateViewProjectionMatrix(const QMatrix4x4 &globalTransform,
212 const QMatrix4x4 &projection,
213 QMatrix4x4 &outMatrix);
214
215 void calculateViewProjectionMatrix(const QMatrix4x4 &globalTransform, QMatrix4x4 &outMatrix) const;
216 void calculateViewProjectionWithoutTranslation(const QMatrix4x4 &globalTransform, float near, float far, QMatrix4x4 &outMatrix) const;
217
218 // Unproject a point (x,y) in viewport relative coordinates meaning
219 // left, bottom is 0,0 and values are increasing right,up respectively.
220 QSSGRenderRay unproject(const QMatrix4x4 &globalTransform, const QVector2D &inLayerRelativeMouseCoords, const QRectF &inViewport) const;
221
222 [[nodiscard]] inline bool isDirty(DirtyFlag dirtyFlag = DirtyMask) const
223 {
224 return ((cameraDirtyFlags & FlagT(dirtyFlag)) != 0)
225 || ((dirtyFlag == DirtyMask) && QSSGRenderNode::isDirty());
226 }
227 void markDirty(DirtyFlag dirtyFlag);
228 void clearDirty(DirtyFlag dirtyFlag);
229
230 float getLevelOfDetailMultiplier() const;
231
232 float getDpr() const { return dpr; }
233
234 // Setting these variables should be followed by marking the camera dirty!
235 ClipPlanes clipPlanes;
236 FieldOfView fov;
237 Frustum customFrustum;
238 Magnification magnification;
239 QMatrix4x4 projection;
240 float levelOfDetailPixelThreshold = 1.0;
241 quint32 layerMask = LayerMaskAll;
242 bool enableFrustumClipping = true;
243
244private:
245 // Record some values from creating the projection matrix
246 // to use during mouse picking.
247 QVector2D frustumScale;
248
249 QRectF previousInViewport;
250 float dpr = 1.0f;
251 FlagT cameraDirtyFlags = 0;
252};
253
254[[nodiscard]] constexpr bool qFuzzyCompare(const QSSGRenderCamera::FieldOfView &fov1, const QSSGRenderCamera::FieldOfView &fov2) noexcept
255{
256 return fov1.orientation() == fov2.orientation() && qFuzzyCompare(fov1.degrees(), fov2.degrees());
257}
258
259[[nodiscard]] constexpr bool qFuzzyCompare(QSSGRenderCamera::Frustum f1, QSSGRenderCamera::Frustum f2) noexcept
260{
261 return qFuzzyCompare(f1.top, f2.top) && qFuzzyCompare(f1.bottom, f2.bottom) && qFuzzyCompare(f1.left, f2.left) && qFuzzyCompare(f1.right, f2.right);
262}
263
264QT_END_NAMESPACE
265
266#endif
static QSSGRenderCameraFieldOfView fromRadians(float fov)
static QSSGRenderCameraFieldOfView fromDegrees(float fov)
QSSGRenderCameraFieldOfView(const QSSGRenderCameraFieldOfView &)=default
QSSGRenderCameraFieldOfView asVerticalFov(float aspectRatio) const
QSSGRenderCameraFieldOfView(QSSGRenderCameraFieldOfView &&)=default
QSSGRenderCameraFieldOfView & operator=(const QSSGRenderCameraFieldOfView &other)=default
constexpr QSSGRenderCameraFieldOfView(Orientation orientation=Orientation::Vertical)
constexpr Orientation orientation() const
Combined button and popup list for selecting options.
bool qFuzzyCompare(const QMatrix4x4 &m1, const QMatrix4x4 &m2) noexcept
static QVector2D getViewportHalfExtents(const QMatrix4x4 &projection)
static float getZNear(const QMatrix4x4 &projection)
static QT_BEGIN_NAMESPACE float getAspectRatio(const QRectF &inViewport)
static QQuaternion rotationQuaternionForLookAt(const QVector3D &sourcePosition, const QVector3D &sourceDirection, const QVector3D &targetPosition, const QVector3D &upDirection)
constexpr bool qFuzzyCompare(QSSGRenderCamera::Frustum f1, QSSGRenderCamera::Frustum f2) noexcept