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 LayerMaskAll = 0xFFFFFFFF; // Default to all layers
129
130 class ClipPlanes : public QVector2D
131 {
132 public:
133 constexpr inline ClipPlanes() : QVector2D(0.0f, 10000.0f) {}
134 constexpr inline ClipPlanes(float n, float f) : QVector2D(n, f) {}
135 constexpr float clipNear() const noexcept { return x(); }
136 constexpr float clipFar() const noexcept { return y(); }
137
138 constexpr inline void setClipNear(float n) noexcept { setX(n); }
139 constexpr inline void setClipFar(float f) noexcept { setY(f); }
140 };
141
142 class Magnification : public QVector2D
143 {
144 public:
145 constexpr inline Magnification() : QVector2D(1.0f, 1.0f) {}
146 constexpr inline Magnification(float h, float v) : QVector2D(h, v) {}
147 constexpr float horizontal() const noexcept { return x(); }
148 constexpr float vertical() const noexcept { return y(); }
149
150 constexpr inline void setHorizontal(float h) noexcept { setX(h); }
151 constexpr inline void setVertical(float v) noexcept { setY(v); }
152 };
153
154 // Used by the custom frustum camera
155 struct Frustum
156 {
157 float top = 0.0f;
158 float bottom = 0.0f;
159 float left = 0.0f;
160 float right = 0.0f;
161 };
162
163 // Set our position, rotation member variables based on the lookat target
164 // Marks this object as dirty.
165 // Need to test this when the camera's local transform is null.
166 // Assumes parent's local transform is the identity, meaning our local transform is
167 // our global transform.
168 void lookAt(const QVector3D &inCameraPos, const QVector3D &inUpDir, const QVector3D &inTargetPos, const QVector3D &pivot);
169
170 /*!
171 * Convenience function intended for use with internal cameras that's not part of the scene graph!
172 * This function will NOT ensure that the camera's global transform, projection matrix, or state
173 * is updated!.
174 */
175 static bool calculateProjectionInternal(QSSGRenderCamera &camera,
176 const QRectF &inViewport,
177 Configuration config = {});
178
179 /*!
180 * \brief calculateProjection
181 * \param inViewport
182 * \param config
183 * \return true if the projection was successfully calculated, false otherwise.
184 *
185 * This function will calculate the projection matrix for the camera.
186 *
187 * NOTE: This function will not update the camera's global transform. It is the caller's
188 * responsibility to ensure that the camera's global transform has been calculated prior
189 * to calling this function.
190 */
191 bool calculateProjection(const QRectF &inViewport, Configuration config = {});
192
193 void setCustomProjection(const QMatrix4x4 &proj);
194
195 static bool computeFrustumOrtho(QRectF inViewport,
196 QSSGRenderCamera::ClipPlanes clipPlanes,
197 QSSGRenderCamera::Magnification magnification,
198 Configuration config,
199 QMatrix4x4 &outProjection);
200 static bool computeFrustumPerspective(QRectF inViewport,
201 FieldOfView fov,
202 QSSGRenderCamera::ClipPlanes clipPlanes,
203 QMatrix4x4 &outProjection);
204 static bool computeCustomFrustum(QSSGRenderCamera::Frustum frustum,
205 QSSGRenderCamera::ClipPlanes clipPlanes,
206 QMatrix4x4 &outProjection);
207
208 static void calculateViewProjectionMatrix(const QMatrix4x4 &globalTransform,
209 const QMatrix4x4 &projection,
210 QMatrix4x4 &outMatrix);
211
212 void calculateViewProjectionMatrix(const QMatrix4x4 &globalTransform, QMatrix4x4 &outMatrix) const;
213 void calculateViewProjectionWithoutTranslation(const QMatrix4x4 &globalTransform, float near, float far, QMatrix4x4 &outMatrix) const;
214
215 // Unproject a point (x,y) in viewport relative coordinates meaning
216 // left, bottom is 0,0 and values are increasing right,up respectively.
217 QSSGRenderRay unproject(const QMatrix4x4 &globalTransform, const QVector2D &inLayerRelativeMouseCoords, const QRectF &inViewport) const;
218
219 [[nodiscard]] inline bool isDirty(DirtyFlag dirtyFlag = DirtyMask) const
220 {
221 return ((cameraDirtyFlags & FlagT(dirtyFlag)) != 0)
222 || ((dirtyFlag == DirtyMask) && QSSGRenderNode::isDirty());
223 }
224 void markDirty(DirtyFlag dirtyFlag);
225 void clearDirty(DirtyFlag dirtyFlag);
226
227 float getLevelOfDetailMultiplier() const;
228
229 float getDpr() const { return dpr; }
230
231 // Setting these variables should be followed by marking the camera dirty!
232 ClipPlanes clipPlanes;
233 FieldOfView fov;
234 Frustum customFrustum;
235 Magnification magnification;
236 QMatrix4x4 projection;
237 float levelOfDetailPixelThreshold = 1.0;
238 quint32 layerMask = LayerMaskAll;
239 bool enableFrustumClipping = true;
240
241private:
242 // Record some values from creating the projection matrix
243 // to use during mouse picking.
244 QVector2D frustumScale;
245
246 QRectF previousInViewport;
247 float dpr = 1.0f;
248 FlagT cameraDirtyFlags = 0;
249};
250
251[[nodiscard]] constexpr bool qFuzzyCompare(const QSSGRenderCamera::FieldOfView &fov1, const QSSGRenderCamera::FieldOfView &fov2) noexcept
252{
253 return fov1.orientation() == fov2.orientation() && qFuzzyCompare(fov1.degrees(), fov2.degrees());
254}
255
256[[nodiscard]] constexpr bool qFuzzyCompare(QSSGRenderCamera::Frustum f1, QSSGRenderCamera::Frustum f2) noexcept
257{
258 return qFuzzyCompare(f1.top, f2.top) && qFuzzyCompare(f1.bottom, f2.bottom) && qFuzzyCompare(f1.left, f2.left) && qFuzzyCompare(f1.right, f2.right);
259}
260
261QT_END_NAMESPACE
262
263#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