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
qssgrenderclippingfrustum_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_CLIPPING_PLANE_H
8#define QSSG_RENDER_CLIPPING_PLANE_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 <QtQuick3DUtils/private/qssgplane_p.h>
22#include <QtQuick3DUtils/private/qssgbounds3_p.h>
23#include <QtQuick3DRuntimeRender/qtquick3druntimerenderexports.h>
24
25QT_BEGIN_NAMESPACE
26
27struct QSSGClipPlane
28{
29 enum BoxEdgeID : quint8
30 {
31 None = 0,
32 xMax = 1,
33 yMax = 1 << 1,
34 zMax = 1 << 2,
35 };
36 using BoxEdgeFlag = std::underlying_type_t<BoxEdgeID>;
37
38 // For an intesection test, we only need two points of the bounding box.
39 // There will be a point nearest to the plane, and a point furthest from the plane.
40 // We can derive these points from the plane normal equation.
41 struct BoxEdge
42 {
43 BoxEdgeFlag lowerEdge;
44 BoxEdgeFlag upperEdge;
45 };
46
47 QVector3D normal;
48 float d;
49 BoxEdge mEdges;
50
51 // For intersection tests, we only need to know if the numerator is greater than, equal to,
52 // or less than zero.
53 [[nodiscard]] constexpr inline float distance(const QVector3D &pt) const { return QVector3D::dotProduct(normal, pt) + d; }
54
55 // Only works if p0 is above the line and p1 is below the plane.
56 inline QVector3D intersectWithLine(const QVector3D &p0, const QVector3D &p1) const
57 {
58 QVector3D dir = p1 - p0;
59 QVector3D pointOnPlane = normal * (-d);
60#ifdef _DEBUG
61 float distanceOfPoint = distance(pointOnPlane);
62 Q_ASSERT(qAbs(distanceOfPoint) < 0.0001f);
63#endif
64 float numerator = QVector3D::dotProduct(pointOnPlane - p0, normal);
65 float denominator = QVector3D::dotProduct(dir, normal);
66
67 Q_ASSERT(qAbs(denominator) > .0001f);
68 float t = (numerator / denominator);
69 QVector3D retval = p0 + dir * t;
70#ifdef _DEBUG
71 float retvalDistance = distance(retval);
72 Q_ASSERT(qAbs(retvalDistance) < .0001f);
73#endif
74 return retval;
75 }
76
77 static inline constexpr QVector3D corner(const QSSGBounds3 &bounds, BoxEdgeFlag edge)
78 {
79 return QVector3D((edge & BoxEdgeID::xMax) ? bounds.maximum[0] : bounds.minimum[0],
80 (edge & BoxEdgeID::yMax) ? bounds.maximum[1] : bounds.minimum[1],
81 (edge & BoxEdgeID::zMax) ? bounds.maximum[2] : bounds.minimum[2]);
82 }
83
84 // dividing the distance numerator
85
86 // I got this code from osg, but it is in graphics gems
87 // as well.
88 /** intersection test between plane and bounding sphere.
89 return 1 if the bs is completely above plane,
90 return 0 if the bs intersects the plane,
91 return -1 if the bs is completely below the plane.*/
92 inline int intersect(const QSSGBounds3 &bounds) const
93 {
94 // if lowest point above plane than all above.
95 if (distance(corner(bounds, mEdges.lowerEdge)) > 0.0f)
96 return 1;
97
98 // if highest point is below plane then all below.
99 if (distance(corner(bounds, mEdges.upperEdge)) < 0.0f)
100 return -1;
101
102 // d_lower<=0.0f && d_upper>=0.0f
103 // therefore must be crossing plane.
104 return 0;
105 }
106
107 [[nodiscard]] constexpr bool intersectSimple(const QSSGBounds3 &bounds) const
108 {
109 return (distance(corner(bounds, mEdges.lowerEdge)) > 0.0f) || !(distance(corner(bounds, mEdges.upperEdge)) < 0.0f);
110 }
111
112 inline void calculateBBoxEdges()
113 {
114 mEdges.upperEdge = (normal[0] >= 0.0f ? BoxEdgeID::xMax : BoxEdgeID::None)
115 | (normal[1] >= 0.0f ? BoxEdgeID::yMax : BoxEdgeID::None)
116 | (normal[2] >= 0.0f ? BoxEdgeID::zMax : BoxEdgeID::None);
117
118 mEdges.lowerEdge = ((~(BoxEdgeFlag(mEdges.upperEdge))) & 7);
119 }
120};
121
122struct Q_QUICK3DRUNTIMERENDER_EXPORT QSSGClippingFrustum
123{
124 QSSGClipPlane mPlanes[6];
125
127
128 QSSGClippingFrustum(const QMatrix4x4 &modelviewprojection, const QSSGClipPlane &nearPlane);
129
130 bool intersectsWith(const QSSGBounds3 &bounds) const
131 {
132 bool ret = true;
133
134 for (quint32 idx = 0; idx < 6 && ret; ++idx)
135 ret = mPlanes[idx].intersectSimple(bounds);
136 return ret;
137 }
138
139 bool intersectsWith(const QVector3D &point, float radius = 0.0f) const
140 {
141 bool ret = true;
142 for (quint32 idx = 0; idx < 6 && ret; ++idx)
143 ret = !(mPlanes[idx].distance(point) < radius);
144 return ret;
145 }
146};
147QT_END_NAMESPACE
148
149#endif
Combined button and popup list for selecting options.
#define M(_x, _y)
bool intersectsWith(const QVector3D &point, float radius=0.0f) const
QSSGClippingFrustum()=default
QSSGClippingFrustum(const QMatrix4x4 &modelviewprojection, const QSSGClipPlane &nearPlane)
bool intersectsWith(const QSSGBounds3 &bounds) const