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