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