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
qssgbounds3_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 QSSGBOUNDS3_H
8#define QSSGBOUNDS3_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 "qssgutils_p.h"
22#include <QtQuick3DUtils/private/qtquick3dutilsglobal_p.h>
23
24#include <QVector3D>
25#include <QMatrix3x3>
26#include <QMatrix4x4>
27
28#include <limits>
29#include <qnumeric.h>
30
32
33using QSSGBoxPoints = std::array<QVector3D, 8>;
34
35/**
36\brief Class representing 3D range or axis aligned bounding box.
37
38Stored as minimum and maximum extent corners. Alternate representation
39would be center and dimensions.
40May be empty or nonempty. If not empty, minimum <= maximum has to hold.
41*/
42class Q_QUICK3DUTILS_EXPORT QSSGBounds3
43{
44public:
45 /**
46 \brief Default constructor, using empty bounds.
47 */
48 Q_DECL_CONSTEXPR Q_ALWAYS_INLINE QSSGBounds3();
49
50 /**
51 \brief Construct uninitialized.
52 */
53 Q_ALWAYS_INLINE QSSGBounds3(Qt::Initialization);
54
55 /**
56 \brief Construct from two bounding points
57 */
58 Q_DECL_CONSTEXPR Q_ALWAYS_INLINE QSSGBounds3(const QVector3D &minimum, const QVector3D &maximum);
59
60 /**
61 \brief Construct from QSSGBoxPoints
62 */
63 Q_DECL_CONSTEXPR Q_ALWAYS_INLINE QSSGBounds3(const QSSGBoxPoints &points);
64
65 /**
66 \brief returns the AABB containing v0 and v1.
67 \param v0 first point included in the AABB.
68 \param v1 second point included in the AABB.
69 */
70 static Q_ALWAYS_INLINE QSSGBounds3 boundsOfPoints(const QVector3D &v0, const QVector3D &v1);
71
72 /**
73 \brief returns the AABB from center and extents vectors.
74 \param center Center vector
75 \param extent Extents vector
76 */
77 static Q_ALWAYS_INLINE QSSGBounds3 centerExtents(const QVector3D &center, const QVector3D &extent);
78
79 /**
80 \brief Construct from center, extent, and (not necessarily orthogonal) basis
81 */
82 static Q_ALWAYS_INLINE QSSGBounds3 basisExtent(const QVector3D &center, const QMatrix3x3 &basis, const QVector3D &extent);
83
84 /**
85 \brief gets the transformed bounds of the passed AABB (resulting in a bigger AABB).
86 \param[in] matrix Transform to apply, can contain scaling as well
87 \param[in] bounds The bounds to transform.
88 */
89 static QSSGBounds3 transform(const QMatrix3x3 &matrix, const QSSGBounds3 &bounds);
90
91 /**
92 \brief Sets empty to true
93 */
94 Q_ALWAYS_INLINE void setEmpty();
95
96 /**
97 \brief Sets infinite bounds
98 */
99 Q_ALWAYS_INLINE void setInfinite();
100
101 /**
102 \brief expands the volume to include v
103 \param v Point to expand to.
104 */
105 void include(const QVector3D &v);
106
107 /**
108 \brief expands the volume to include b.
109 \param b Bounds to perform union with.
110 */
111 void include(const QSSGBounds3 &b);
112
113 Q_ALWAYS_INLINE bool isEmpty() const;
114
115 /**
116 \brief indicates whether the intersection of this and b is empty or not.
117 \param b Bounds to test for intersection.
118 */
119 Q_ALWAYS_INLINE bool intersects(const QSSGBounds3 &b) const;
120
121 /**
122 \brief computes the 1D-intersection between two AABBs, on a given axis.
123 \param a the other AABB
124 \param axis the axis (0, 1, 2)
125 */
126 Q_ALWAYS_INLINE bool intersects1D(const QSSGBounds3 &a, quint32 axis) const;
127
128 /**
129 \brief indicates if these bounds contain v.
130 \param v Point to test against bounds.
131 */
132 Q_ALWAYS_INLINE bool contains(const QVector3D &v) const;
133
134 /**
135 \brief checks a box is inside another box.
136 \param box the other AABB
137 */
138 Q_ALWAYS_INLINE bool isInside(const QSSGBounds3 &box) const;
139
140 /**
141 \brief returns the center of this axis aligned box.
142 */
143 Q_ALWAYS_INLINE QVector3D center() const;
144
145 /**
146 \brief get component of the box's center along a given axis
147 */
148 Q_ALWAYS_INLINE float center(quint32 axis) const;
149
150 /**
151 \brief get component of the box's extents along a given axis
152 */
153 Q_ALWAYS_INLINE float extents(quint32 axis) const;
154
155 /**
156 \brief returns the dimensions (width/height/depth) of this axis aligned box.
157 */
158 Q_ALWAYS_INLINE QVector3D dimensions() const;
159
160 /**
161 \brief returns the extents, which are half of the width/height/depth.
162 */
163 Q_ALWAYS_INLINE QVector3D extents() const;
164
165 /**
166 \brief scales the AABB.
167 \param scale Factor to scale AABB by.
168 */
169 Q_ALWAYS_INLINE void scale(float scale);
170
171 /**
172 fattens the AABB in all 3 dimensions by the given distance.
173 */
174 Q_ALWAYS_INLINE void fatten(double distance);
175
176 /**
177 checks that the AABB values are not NaN
178 */
179
180 bool isFinite() const;
181
182 /**
183 Use when the bounds is already verified to be non-empty!!!
184 */
185 Q_ALWAYS_INLINE QSSGBoxPoints toQSSGBoxPointsNoEmptyCheck() const;
186 /**
187 Verifies that the bounds is non-empty.
188 */
189 Q_ALWAYS_INLINE QSSGBoxPoints toQSSGBoxPoints() const;
190
191 void transform(const QMatrix4x4 &inMatrix);
192
193 /**
194 Returns the support point in a given direction
195 */
196 QVector3D getSupport(const QVector3D &direction) const;
197
198 QVector3D minimum;
199 QVector3D maximum;
200};
201
202Q_DECL_CONSTEXPR Q_ALWAYS_INLINE QSSGBounds3::QSSGBounds3()
203 : minimum(QVector3D(std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max()))
204 , maximum(-std::numeric_limits<float>::max(), -std::numeric_limits<float>::max(), -std::numeric_limits<float>::max())
205{
206}
207
208Q_ALWAYS_INLINE QSSGBounds3::QSSGBounds3(Qt::Initialization)
209 : minimum(Qt::Uninitialized), maximum(Qt::Uninitialized) { }
210
211Q_DECL_CONSTEXPR Q_ALWAYS_INLINE QSSGBounds3::QSSGBounds3(const QVector3D &_minimum, const QVector3D &_maximum)
212 : minimum(_minimum), maximum(_maximum)
213{
214}
215
216Q_DECL_CONSTEXPR Q_ALWAYS_INLINE QSSGBounds3::QSSGBounds3(const QSSGBoxPoints &points)
217 : minimum(QVector3D(std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max()))
218 , maximum(-std::numeric_limits<float>::max(), -std::numeric_limits<float>::max(), -std::numeric_limits<float>::max())
219{
220 for (const QVector3D &v : points)
221 include(v);
222}
223
224Q_ALWAYS_INLINE QSSGBounds3 QSSGBounds3::centerExtents(const QVector3D &center, const QVector3D &extent)
225{
226 return QSSGBounds3(center - extent, center + extent);
227}
228
229Q_ALWAYS_INLINE void QSSGBounds3::setEmpty()
230{
231 constexpr float maxFloat = std::numeric_limits<float>::max();
232 minimum = QVector3D(maxFloat, maxFloat, maxFloat);
233 maximum = QVector3D(-maxFloat, -maxFloat, -maxFloat);
234}
235
236Q_ALWAYS_INLINE void QSSGBounds3::setInfinite()
237{
238 constexpr float maxFloat = std::numeric_limits<float>::max();
239 minimum = QVector3D(-maxFloat, -maxFloat, -maxFloat);
240 maximum = QVector3D(maxFloat, maxFloat, maxFloat);
241}
242
243Q_ALWAYS_INLINE bool QSSGBounds3::isEmpty() const
244{
245 Q_ASSERT(isFinite());
246 // Consistency condition for (Min, Max) boxes: minimum < maximum
247 return minimum.x() > maximum.x() || minimum.y() > maximum.y() || minimum.z() > maximum.z();
248}
249
250Q_ALWAYS_INLINE bool QSSGBounds3::intersects(const QSSGBounds3 &b) const
251{
252 Q_ASSERT(isFinite() && b.isFinite());
253 return !(b.minimum.x() > maximum.x() || minimum.x() > b.maximum.x() || b.minimum.y() > maximum.y()
254 || minimum.y() > b.maximum.y() || b.minimum.z() > maximum.z() || minimum.z() > b.maximum.z());
255}
256
257Q_ALWAYS_INLINE bool QSSGBounds3::intersects1D(const QSSGBounds3 &a, quint32 axis) const
258{
259 Q_ASSERT(isFinite() && a.isFinite());
260 return maximum[int(axis)] >= a.minimum[axis] && a.maximum[axis] >= minimum[axis];
261}
262
263Q_ALWAYS_INLINE bool QSSGBounds3::contains(const QVector3D &v) const
264{
265 Q_ASSERT(isFinite());
266
267 return !(v.x() < minimum.x() || v.x() > maximum.x() || v.y() < minimum.y() || v.y() > maximum.y()
268 || v.z() < minimum.z() || v.z() > maximum.z());
269}
270
271Q_ALWAYS_INLINE bool QSSGBounds3::isInside(const QSSGBounds3 &box) const
272{
273 Q_ASSERT(isFinite() && box.isFinite());
274 if (box.minimum.x() > minimum.x())
275 return false;
276 if (box.minimum.y() > minimum.y())
277 return false;
278 if (box.minimum.z() > minimum.z())
279 return false;
280 if (box.maximum.x() < maximum.x())
281 return false;
282 if (box.maximum.y() < maximum.y())
283 return false;
284 if (box.maximum.z() < maximum.z())
285 return false;
286 return true;
287}
288
289Q_ALWAYS_INLINE QVector3D QSSGBounds3::center() const
290{
291 Q_ASSERT(isFinite());
292 return (minimum + maximum) * double(0.5);
293}
294
295Q_ALWAYS_INLINE float QSSGBounds3::center(quint32 axis) const
296{
297 Q_ASSERT(isFinite());
298 return (minimum[int(axis)] + maximum[int(axis)]) * 0.5f;
299}
300
301Q_ALWAYS_INLINE float QSSGBounds3::extents(quint32 axis) const
302{
303 Q_ASSERT(isFinite());
304 return (maximum[int(axis)] - minimum[int(axis)]) * 0.5f;
305}
306
307Q_ALWAYS_INLINE QVector3D QSSGBounds3::dimensions() const
308{
309 Q_ASSERT(isFinite());
310 return maximum - minimum;
311}
312
313Q_ALWAYS_INLINE QVector3D QSSGBounds3::extents() const
314{
315 Q_ASSERT(isFinite());
316 return dimensions() * double(0.5);
317}
318
319Q_ALWAYS_INLINE void QSSGBounds3::scale(float scale)
320{
321 Q_ASSERT(isFinite());
322 *this = centerExtents(center(), extents() * scale);
323}
324
325Q_ALWAYS_INLINE void QSSGBounds3::fatten(double distance)
326{
327 Q_ASSERT(isFinite());
328 minimum -= QVector3D(float(distance), float(distance), float(distance));
329 maximum += QVector3D(float(distance), float(distance), float(distance));
330}
331
332Q_ALWAYS_INLINE QSSGBoxPoints QSSGBounds3::toQSSGBoxPointsNoEmptyCheck() const
333{
334 return { // Min corner of box
335 QVector3D(minimum[0], minimum[1], minimum[2]),
336 QVector3D(maximum[0], minimum[1], minimum[2]),
337 QVector3D(maximum[0], maximum[1], minimum[2]),
338 QVector3D(minimum[0], maximum[1], minimum[2]),
339 // Max corner of box
340 QVector3D(minimum[0], minimum[1], maximum[2]),
341 QVector3D(maximum[0], minimum[1], maximum[2]),
342 QVector3D(maximum[0], maximum[1], maximum[2]),
343 QVector3D(minimum[0], maximum[1], maximum[2])
344 };
345}
346
347Q_ALWAYS_INLINE QSSGBoxPoints QSSGBounds3::toQSSGBoxPoints() const
348{
349 if (isEmpty())
350 return { QVector3D(0, 0, 0), QVector3D(0, 0, 0), QVector3D(0, 0, 0), QVector3D(0, 0, 0),
351 QVector3D(0, 0, 0), QVector3D(0, 0, 0), QVector3D(0, 0, 0), QVector3D(0, 0, 0) };
352 return toQSSGBoxPointsNoEmptyCheck();
353}
354
355QT_END_NAMESPACE
356
357#endif // QSSGBOUNDS3_H
Class representing 3D range or axis aligned bounding box.
Combined button and popup list for selecting options.