Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qssgrendercamera.cpp
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
7
8#include <QtQuick3DRuntimeRender/private/qssgrendererutil_p.h>
9
10#include <QtQuick3DUtils/private/qssgutils_p.h>
11
12#include <QtGui/QVector2D>
13
14#include <qmath.h>
15
17
18namespace {
19
20float getAspectRatio(const QRectF &inViewport)
21{
22 return inViewport.height() != 0 ? inViewport.width() / inViewport.height() : 0.0f;
23}
24
25}
26
29 , clipNear(10)
30 , clipFar(10000)
31 , fov(qDegreesToRadians(60.0f))
32 , fovHorizontal(false)
33 , enableFrustumClipping(true)
34{
37}
38
39// Code for testing
45
47{
48 bool retval = false;
49
50 const bool argumentsChanged = inViewport != previousInViewport;
51 if (!argumentsChanged && !isDirty(DirtyFlag::CameraDirty))
52 return true;
53 previousInViewport = inViewport;
55
56 switch (type) {
57 case QSSGRenderGraphObject::Type::OrthographicCamera:
58 retval = computeFrustumOrtho(inViewport);
59 break;
60 case QSSGRenderGraphObject::Type::PerspectiveCamera:
61 retval = computeFrustumPerspective(inViewport);
62 break;
63 case QSSGRenderGraphObject::Type::CustomCamera:
64 retval = true; // Do nothing
65 break;
66 case QSSGRenderGraphObject::Type::CustomFrustumCamera:
67 retval = computeCustomFrustum(inViewport);
68 break;
69 default:
70 Q_UNREACHABLE();
71 }
72
73 if (retval) {
74 float *writePtr(projection.data());
75 frustumScale.setX(writePtr[0]);
76 frustumScale.setY(writePtr[5]);
77 }
78 return retval;
79}
80
81//==============================================================================
87{
89 projection.perspective(qRadiansToDegrees(verticalFov(inViewport)), getAspectRatio(inViewport), clipNear, clipFar);
90 return true;
91}
92
94{
95 Q_UNUSED(inViewport);
98 return true;
99}
100
102 const QMatrix4x4 &projection,
103 QMatrix4x4 &outMatrix)
104{
105 QMatrix4x4 nonScaledGlobal(Qt::Uninitialized);
106 nonScaledGlobal.setColumn(0, globalTransform.column(0).normalized());
107 nonScaledGlobal.setColumn(1, globalTransform.column(1).normalized());
108 nonScaledGlobal.setColumn(2, globalTransform.column(2).normalized());
109 nonScaledGlobal.setColumn(3, globalTransform.column(3));
110 outMatrix = projection * nonScaledGlobal.inverted();
111}
112
113//==============================================================================
119{
121 float halfWidth = inViewport.width() / 2.0f / horizontalMagnification / dpr;
122 float halfHeight = inViewport.height() / 2.0f / verticalMagnification / dpr;
123 projection.ortho(-halfWidth, halfWidth, -halfHeight, halfHeight, clipNear, clipFar);
124 return true;
125}
126
128{
129 Q_UNUSED(inViewport);
131}
132
134 const QVector3D &sourceDirection,
135 const QVector3D &targetPosition,
136 const QVector3D &upDirection)
137{
138 QVector3D targetDirection = sourcePosition - targetPosition;
139 targetDirection.normalize();
140
141 QVector3D rotationAxis = QVector3D::crossProduct(sourceDirection, targetDirection);
142
143 const QVector3D normalizedAxis = rotationAxis.normalized();
144 if (qFuzzyIsNull(normalizedAxis.lengthSquared()))
145 rotationAxis = upDirection;
146
147 float dot = QVector3D::dotProduct(sourceDirection, targetDirection);
148 float rotationAngle = float(qRadiansToDegrees(qAcos(qreal(dot))));
149
150 return QQuaternion::fromAxisAndAngle(rotationAxis, rotationAngle);
151}
152
159
161{
162 QMatrix4x4 nonScaledGlobal(Qt::Uninitialized);
163 nonScaledGlobal.setColumn(0, globalTransform.column(0).normalized());
164 nonScaledGlobal.setColumn(1, globalTransform.column(1).normalized());
165 nonScaledGlobal.setColumn(2, globalTransform.column(2).normalized());
166 nonScaledGlobal.setColumn(3, globalTransform.column(3));
167 outMatrix = projection * nonScaledGlobal.inverted();
168}
169
170void QSSGRenderCamera::calculateViewProjectionWithoutTranslation(float clipNear, float clipFar, QMatrix4x4 &outMatrix) const
171{
173 qWarning() << "QSSGRenderCamera::calculateViewProjection: far == near";
174 return;
175 }
176
177 QMatrix4x4 proj = projection;
178 proj(2, 2) = -(clipFar + clipNear) / (clipFar - clipNear);
179 proj(2, 3) = -2 * clipFar * clipNear / (clipFar - clipNear);
180 QMatrix4x4 nonScaledGlobal(Qt::Uninitialized);
181 nonScaledGlobal.setColumn(0, globalTransform.column(0).normalized());
182 nonScaledGlobal.setColumn(1, globalTransform.column(1).normalized());
183 nonScaledGlobal.setColumn(2, globalTransform.column(2).normalized());
184 nonScaledGlobal.setColumn(3, QVector4D(0, 0, 0, 1));
185 outMatrix = proj * nonScaledGlobal.inverted();
186}
187
189 const QRectF &inViewport) const
190{
191 QSSGRenderRay theRay;
192 QVector2D normalizedCoords = QSSGUtils::rect::relativeToNormalizedCoordinates(inViewport, inViewportRelativeCoords);
193 QVector3D &outOrigin(theRay.origin);
194 QVector3D &outDir(theRay.direction);
195 QVector2D inverseFrustumScale(1.0f / frustumScale.x(), 1.0f / frustumScale.y());
196 QVector2D scaledCoords(inverseFrustumScale.x() * normalizedCoords.x(), inverseFrustumScale.y() * normalizedCoords.y());
197
198 if (type == QSSGRenderCamera::Type::OrthographicCamera) {
199 outOrigin.setX(scaledCoords.x());
200 outOrigin.setY(scaledCoords.y());
201 outOrigin.setZ(0.0f);
202
203 outDir.setX(0.0f);
204 outDir.setY(0.0f);
205 outDir.setZ(-1.0f);
206 } else {
207 outOrigin.setX(0.0f);
208 outOrigin.setY(0.0f);
209 outOrigin.setZ(0.0f);
210
211 outDir.setX(scaledCoords.x());
212 outDir.setY(scaledCoords.y());
213 outDir.setZ(-1.0f);
214 }
215
216 outOrigin = QSSGUtils::mat44::transform(globalTransform, outOrigin);
217 QMatrix3x3 theNormalMatrix = calculateNormalMatrix();
218
219 outDir = QSSGUtils::mat33::transform(theNormalMatrix, outDir);
220 outDir.normalize();
221
222 return theRay;
223}
224
226{
227 QVector3D theCameraDir = getDirection();
228 QVector3D theObjGlobalPos = inGlobalPos;
229 float theDistance = -1.0f * QVector3D::dotProduct(theObjGlobalPos, theCameraDir);
230 QSSGPlane theCameraPlane(theCameraDir, theDistance);
231 return QSSGRenderRay::intersect(theCameraPlane, inRay).value_or(QVector3D{});
232}
233
234float QSSGRenderCamera::verticalFov(float aspectRatio) const
235{
236 return fovHorizontal ? float(2.0 * qAtan(qTan(qreal(fov) / 2.0) / qreal(aspectRatio))) : fov;
237}
238
239float QSSGRenderCamera::verticalFov(const QRectF &inViewport) const
240{
241 return verticalFov(getAspectRatio(inViewport));
242}
243
249
255
256static float getZNear(const QMatrix4x4 &projection)
257{
258 const float *data = projection.constData();
259 QSSGPlane plane(QVector3D(data[3] + data[2], data[7] + data[6], data[11] + data[10]), -data[15] - data[14]);
260 plane.normalize();
261 return plane.d;
262}
263
264static QVector2D getViewportHalfExtents(const QMatrix4x4 &projection) {
265 const float *data = projection.constData();
266
267 QSSGPlane nearPlane(QVector3D(data[3] + data[2], data[7] + data[6], data[11] + data[10]), -data[15] - data[14]);
268 nearPlane.normalize();
269 QSSGPlane rightPlane(QVector3D(data[3] - data[0], data[7] - data[4], data[11] - data[8]), -data[15] + data[12]);
270 rightPlane.normalize();
271 QSSGPlane topPlane(QVector3D(data[3] - data[1], data[7] - data[5], data[11] - data[9]), -data[15] + data[13]);
272 topPlane.normalize();
273
274 // Get intersection the 3 planes
275 float denom = QVector3D::dotProduct(QVector3D::crossProduct(nearPlane.n, rightPlane.n), topPlane.n);
276 if (qFuzzyIsNull(denom))
277 return QVector2D();
278
279 QVector3D intersection = (QVector3D::crossProduct(rightPlane.n, topPlane.n) * nearPlane.d +
280 (QVector3D::crossProduct(topPlane.n, nearPlane.n) * rightPlane.d) +
281 (QVector3D::crossProduct(nearPlane.n, rightPlane.n) * topPlane.d)) / denom;
282
283 return QVector2D(intersection.x(), intersection.y());
284}
285
287{
288 if (type == QSSGRenderGraphObject::Type::OrthographicCamera)
290
291 float zn = getZNear(projection);
292 float width = getViewportHalfExtents(projection).x() * 2.0;
293 return 1.0 / (zn / width);
294
295}
296
The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
Definition qmatrix4x4.h:25
void frustum(float left, float right, float bottom, float top, float nearPlane, float farPlane)
Multiplies this matrix by another that applies a perspective frustum projection for a window with low...
QVector4D column(int index) const
Returns the elements of column index as a 4D vector.
Definition qmatrix4x4.h:259
void ortho(const QRect &rect)
This is an overloaded member function, provided for convenience. It differs from the above function o...
float * data()
Returns a pointer to the raw data of this matrix.
void perspective(float verticalAngle, float aspectRatio, float nearPlane, float farPlane)
Multiplies this matrix by another that applies a perspective projection.
QMatrix4x4 inverted(bool *invertible=nullptr) const
Returns the inverse of this matrix.
void setToIdentity()
Sets this matrix to the identity.
Definition qmatrix4x4.h:316
const float * constData() const
Returns a constant pointer to the raw data of this matrix.
Definition qmatrix4x4.h:147
The QQuaternion class represents a quaternion consisting of a vector and scalar.
\inmodule QtCore\reentrant
Definition qrect.h:484
Representation of a plane.
Definition qssgplane_p.h:31
float d
The distance from the origin.
Definition qssgplane_p.h:83
void normalize()
equivalent plane with unit normal
Definition qssgplane.cpp:16
static constexpr bool isCamera(Type type) noexcept
The QVector2D class represents a vector or vertex in 2D space.
Definition qvectornd.h:31
constexpr float y() const noexcept
Returns the y coordinate of this point.
Definition qvectornd.h:502
constexpr float x() const noexcept
Returns the x coordinate of this point.
Definition qvectornd.h:501
constexpr void setY(float y) noexcept
Sets the y coordinate of this point to the given finite y coordinate.
Definition qvectornd.h:505
constexpr void setX(float x) noexcept
Sets the x coordinate of this point to the given finite x coordinate.
Definition qvectornd.h:504
The QVector3D class represents a vector or vertex in 3D space.
Definition qvectornd.h:171
QVector3D normalized() const noexcept
Returns the normalized unit vector form of this vector.
Definition qvectornd.h:695
constexpr float y() const noexcept
Returns the y coordinate of this point.
Definition qvectornd.h:671
constexpr float x() const noexcept
Returns the x coordinate of this point.
Definition qvectornd.h:670
static constexpr float dotProduct(QVector3D v1, QVector3D v2) noexcept
Returns the dot product of v1 and v2.
Definition qvectornd.h:770
static constexpr QVector3D crossProduct(QVector3D v1, QVector3D v2) noexcept
Returns the cross-product of vectors v1 and v2, which is normal to the plane spanned by v1 and v2.
Definition qvectornd.h:775
void normalize() noexcept
Normalizes the current vector in place.
Definition qvectornd.h:702
The QVector4D class represents a vector or vertex in 4D space.
Definition qvectornd.h:330
QVector4D normalized() const noexcept
Returns the normalized unit vector form of this vector.
Definition qvectornd.h:910
QVector3D Q_QUICK3DUTILS_EXPORT transform(const QMatrix3x3 &m, const QVector3D &v)
Definition qssgutils.cpp:43
QVector3D Q_QUICK3DUTILS_EXPORT transform(const QMatrix4x4 &m, const QVector3D &v)
Definition qssgutils.cpp:86
QVector2D relativeToNormalizedCoordinates(const QRectF &r, QVector2D rectRelativeCoords)
Combined button and popup list for selecting options.
float getAspectRatio(const QRectF &inViewport)
constexpr Initialization Uninitialized
bool qFuzzyIsNull(qfloat16 f) noexcept
Definition qfloat16.h:349
#define qWarning
Definition qlogging.h:166
constexpr float qRadiansToDegrees(float radians)
Definition qmath.h:281
auto qAcos(T v)
Definition qmath.h:72
auto qAtan(T v)
Definition qmath.h:84
constexpr float qDegreesToRadians(float degrees)
Definition qmath.h:260
auto qTan(T v)
Definition qmath.h:66
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLdouble GLdouble GLdouble GLdouble top
GLdouble GLdouble right
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLint GLsizei width
GLint left
GLenum type
GLint GLint bottom
static qreal dot(const QPointF &a, const QPointF &b)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
static QVector2D getViewportHalfExtents(const QMatrix4x4 &projection)
static float getZNear(const QMatrix4x4 &projection)
static QQuaternion rotationQuaternionForLookAt(const QVector3D &sourcePosition, const QVector3D &sourceDirection, const QVector3D &targetPosition, const QVector3D &upDirection)
#define Q_UNUSED(x)
double qreal
Definition qtypes.h:187
void clearDirty(DirtyFlag dirtyFlag)
std::underlying_type_t< DirtyFlag > FlagT
float getOrthographicScaleFactor(const QRectF &inViewport) const
bool computeFrustumOrtho(const QRectF &inViewport)
float getLevelOfDetailMultiplier() const
float verticalFov(float aspectRatio) const
bool computeFrustumPerspective(const QRectF &inViewport)
bool computeCustomFrustum(const QRectF &inViewport)
static void calculateViewProjectionMatrix(const QMatrix4x4 &globalTransform, const QMatrix4x4 &projection, QMatrix4x4 &outMatrix)
void calculateViewProjectionWithoutTranslation(float near, float far, QMatrix4x4 &outMatrix) const
bool isDirty(DirtyFlag dirtyFlag=DirtyMask) const
void lookAt(const QVector3D &inCameraPos, const QVector3D &inUpDir, const QVector3D &inTargetPos, const QVector3D &pivot)
QSSGRenderRay unproject(const QVector2D &inLayerRelativeMouseCoords, const QRectF &inViewport) const
QVector3D unprojectToPosition(const QVector3D &inGlobalPos, const QSSGRenderRay &inRay) const
void markDirty(DirtyFlag dirtyFlag)
bool calculateProjection(const QRectF &inViewport)
QSSGRenderCamera(QSSGRenderGraphObject::Type type)
static constexpr QVector3D initScale
bool calculateGlobalVariables()
void clearDirty(DirtyFlag dirtyFlag)
QVector3D getDirection() const
QMatrix4x4 globalTransform
QVector3D getScalingCorrectDirection() const
static QMatrix4x4 calculateTransformMatrix(QVector3D position, QVector3D scale, QVector3D pivot, QQuaternion rotation)
QMatrix4x4 localTransform
QMatrix3x3 calculateNormalMatrix() const
void markDirty(DirtyFlag dirtyFlag)
static std::optional< QVector3D > intersect(const QSSGPlane &inPlane, const QSSGRenderRay &ray)