1//
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions
4// are met:
5// * Redistributions of source code must retain the above copyright
6// notice, this list of conditions and the following disclaimer.
7// * Redistributions in binary form must reproduce the above copyright
8// notice, this list of conditions and the following disclaimer in the
9// documentation and/or other materials provided with the distribution.
10// * Neither the name of NVIDIA CORPORATION nor the names of its
11// contributors may be used to endorse or promote products derived
12// from this software without specific prior written permission.
13//
14// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
15// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25//
26// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
27// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
28// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
29
30#ifndef PXFOUNDATION_PXBOUNDS3_H
31#define PXFOUNDATION_PXBOUNDS3_H
32
33/** \addtogroup foundation
34@{
35*/
36
37#include "foundation/PxTransform.h"
38#include "foundation/PxMat33.h"
39
40#if !PX_DOXYGEN
41namespace physx
42{
43#endif
44
45// maximum extents defined such that floating point exceptions are avoided for standard use cases
46#define PX_MAX_BOUNDS_EXTENTS (PX_MAX_REAL * 0.25f)
47
48/**
49\brief Class representing 3D range or axis aligned bounding box.
50
51Stored as minimum and maximum extent corners. Alternate representation
52would be center and dimensions.
53May be empty or nonempty. For nonempty bounds, minimum <= maximum has to hold for all axes.
54Empty bounds have to be represented as minimum = PX_MAX_BOUNDS_EXTENTS and maximum = -PX_MAX_BOUNDS_EXTENTS for all
55axes.
56All other representations are invalid and the behavior is undefined.
57*/
58class PxBounds3
59{
60 public:
61 /**
62 \brief Default constructor, not performing any initialization for performance reason.
63 \remark Use empty() function below to construct empty bounds.
64 */
65 PX_CUDA_CALLABLE PX_FORCE_INLINE PxBounds3()
66 {
67 }
68
69 /**
70 \brief Construct from two bounding points
71 */
72 PX_CUDA_CALLABLE PX_FORCE_INLINE PxBounds3(const PxVec3& minimum, const PxVec3& maximum);
73
74 /**
75 \brief Return empty bounds.
76 */
77 static PX_CUDA_CALLABLE PX_FORCE_INLINE PxBounds3 empty();
78
79 /**
80 \brief returns the AABB containing v0 and v1.
81 \param v0 first point included in the AABB.
82 \param v1 second point included in the AABB.
83 */
84 static PX_CUDA_CALLABLE PX_FORCE_INLINE PxBounds3 boundsOfPoints(const PxVec3& v0, const PxVec3& v1);
85
86 /**
87 \brief returns the AABB from center and extents vectors.
88 \param center Center vector
89 \param extent Extents vector
90 */
91 static PX_CUDA_CALLABLE PX_FORCE_INLINE PxBounds3 centerExtents(const PxVec3& center, const PxVec3& extent);
92
93 /**
94 \brief Construct from center, extent, and (not necessarily orthogonal) basis
95 */
96 static PX_CUDA_CALLABLE PX_INLINE PxBounds3
97 basisExtent(const PxVec3& center, const PxMat33& basis, const PxVec3& extent);
98
99 /**
100 \brief Construct from pose and extent
101 */
102 static PX_CUDA_CALLABLE PX_INLINE PxBounds3 poseExtent(const PxTransform& pose, const PxVec3& extent);
103
104 /**
105 \brief gets the transformed bounds of the passed AABB (resulting in a bigger AABB).
106
107 This version is safe to call for empty bounds.
108
109 \param[in] matrix Transform to apply, can contain scaling as well
110 \param[in] bounds The bounds to transform.
111 */
112 static PX_CUDA_CALLABLE PX_INLINE PxBounds3 transformSafe(const PxMat33& matrix, const PxBounds3& bounds);
113
114 /**
115 \brief gets the transformed bounds of the passed AABB (resulting in a bigger AABB).
116
117 Calling this method for empty bounds leads to undefined behavior. Use #transformSafe() instead.
118
119 \param[in] matrix Transform to apply, can contain scaling as well
120 \param[in] bounds The bounds to transform.
121 */
122 static PX_CUDA_CALLABLE PX_INLINE PxBounds3 transformFast(const PxMat33& matrix, const PxBounds3& bounds);
123
124 /**
125 \brief gets the transformed bounds of the passed AABB (resulting in a bigger AABB).
126
127 This version is safe to call for empty bounds.
128
129 \param[in] transform Transform to apply, can contain scaling as well
130 \param[in] bounds The bounds to transform.
131 */
132 static PX_CUDA_CALLABLE PX_INLINE PxBounds3 transformSafe(const PxTransform& transform, const PxBounds3& bounds);
133
134 /**
135 \brief gets the transformed bounds of the passed AABB (resulting in a bigger AABB).
136
137 Calling this method for empty bounds leads to undefined behavior. Use #transformSafe() instead.
138
139 \param[in] transform Transform to apply, can contain scaling as well
140 \param[in] bounds The bounds to transform.
141 */
142 static PX_CUDA_CALLABLE PX_INLINE PxBounds3 transformFast(const PxTransform& transform, const PxBounds3& bounds);
143
144 /**
145 \brief Sets empty to true
146 */
147 PX_CUDA_CALLABLE PX_FORCE_INLINE void setEmpty();
148
149 /**
150 \brief Sets the bounds to maximum size [-PX_MAX_BOUNDS_EXTENTS, PX_MAX_BOUNDS_EXTENTS].
151 */
152 PX_CUDA_CALLABLE PX_FORCE_INLINE void setMaximal();
153
154 /**
155 \brief expands the volume to include v
156 \param v Point to expand to.
157 */
158 PX_CUDA_CALLABLE PX_FORCE_INLINE void include(const PxVec3& v);
159
160 /**
161 \brief expands the volume to include b.
162 \param b Bounds to perform union with.
163 */
164 PX_CUDA_CALLABLE PX_FORCE_INLINE void include(const PxBounds3& b);
165
166 PX_CUDA_CALLABLE PX_FORCE_INLINE bool isEmpty() const;
167
168 /**
169 \brief indicates whether the intersection of this and b is empty or not.
170 \param b Bounds to test for intersection.
171 */
172 PX_CUDA_CALLABLE PX_FORCE_INLINE bool intersects(const PxBounds3& b) const;
173
174 /**
175 \brief computes the 1D-intersection between two AABBs, on a given axis.
176 \param a the other AABB
177 \param axis the axis (0, 1, 2)
178 */
179 PX_CUDA_CALLABLE PX_FORCE_INLINE bool intersects1D(const PxBounds3& a, uint32_t axis) const;
180
181 /**
182 \brief indicates if these bounds contain v.
183 \param v Point to test against bounds.
184 */
185 PX_CUDA_CALLABLE PX_FORCE_INLINE bool contains(const PxVec3& v) const;
186
187 /**
188 \brief checks a box is inside another box.
189 \param box the other AABB
190 */
191 PX_CUDA_CALLABLE PX_FORCE_INLINE bool isInside(const PxBounds3& box) const;
192
193 /**
194 \brief returns the center of this axis aligned box.
195 */
196 PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 getCenter() const;
197
198 /**
199 \brief get component of the box's center along a given axis
200 */
201 PX_CUDA_CALLABLE PX_FORCE_INLINE float getCenter(uint32_t axis) const;
202
203 /**
204 \brief get component of the box's extents along a given axis
205 */
206 PX_CUDA_CALLABLE PX_FORCE_INLINE float getExtents(uint32_t axis) const;
207
208 /**
209 \brief returns the dimensions (width/height/depth) of this axis aligned box.
210 */
211 PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 getDimensions() const;
212
213 /**
214 \brief returns the extents, which are half of the width/height/depth.
215 */
216 PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 getExtents() const;
217
218 /**
219 \brief scales the AABB.
220
221 This version is safe to call for empty bounds.
222
223 \param scale Factor to scale AABB by.
224 */
225 PX_CUDA_CALLABLE PX_FORCE_INLINE void scaleSafe(float scale);
226
227 /**
228 \brief scales the AABB.
229
230 Calling this method for empty bounds leads to undefined behavior. Use #scaleSafe() instead.
231
232 \param scale Factor to scale AABB by.
233 */
234 PX_CUDA_CALLABLE PX_FORCE_INLINE void scaleFast(float scale);
235
236 /**
237 fattens the AABB in all 3 dimensions by the given distance.
238
239 This version is safe to call for empty bounds.
240 */
241 PX_CUDA_CALLABLE PX_FORCE_INLINE void fattenSafe(float distance);
242
243 /**
244 fattens the AABB in all 3 dimensions by the given distance.
245
246 Calling this method for empty bounds leads to undefined behavior. Use #fattenSafe() instead.
247 */
248 PX_CUDA_CALLABLE PX_FORCE_INLINE void fattenFast(float distance);
249
250 /**
251 checks that the AABB values are not NaN
252 */
253 PX_CUDA_CALLABLE PX_FORCE_INLINE bool isFinite() const;
254
255 /**
256 checks that the AABB values describe a valid configuration.
257 */
258 PX_CUDA_CALLABLE PX_FORCE_INLINE bool isValid() const;
259
260 PxVec3 minimum, maximum;
261};
262
263PX_CUDA_CALLABLE PX_FORCE_INLINE PxBounds3::PxBounds3(const PxVec3& minimum_, const PxVec3& maximum_)
264: minimum(minimum_), maximum(maximum_)
265{
266}
267
268PX_CUDA_CALLABLE PX_FORCE_INLINE PxBounds3 PxBounds3::empty()
269{
270 return PxBounds3(PxVec3(PX_MAX_BOUNDS_EXTENTS), PxVec3(-PX_MAX_BOUNDS_EXTENTS));
271}
272
273PX_CUDA_CALLABLE PX_FORCE_INLINE bool PxBounds3::isFinite() const
274{
275 return minimum.isFinite() && maximum.isFinite();
276}
277
278PX_CUDA_CALLABLE PX_FORCE_INLINE PxBounds3 PxBounds3::boundsOfPoints(const PxVec3& v0, const PxVec3& v1)
279{
280 return PxBounds3(v0.minimum(v: v1), v0.maximum(v: v1));
281}
282
283PX_CUDA_CALLABLE PX_FORCE_INLINE PxBounds3 PxBounds3::centerExtents(const PxVec3& center, const PxVec3& extent)
284{
285 return PxBounds3(center - extent, center + extent);
286}
287
288PX_CUDA_CALLABLE PX_INLINE PxBounds3
289PxBounds3::basisExtent(const PxVec3& center, const PxMat33& basis, const PxVec3& extent)
290{
291 // extended basis vectors
292 PxVec3 c0 = basis.column0 * extent.x;
293 PxVec3 c1 = basis.column1 * extent.y;
294 PxVec3 c2 = basis.column2 * extent.z;
295
296 PxVec3 w;
297 // find combination of base vectors that produces max. distance for each component = sum of abs()
298 w.x = PxAbs(a: c0.x) + PxAbs(a: c1.x) + PxAbs(a: c2.x);
299 w.y = PxAbs(a: c0.y) + PxAbs(a: c1.y) + PxAbs(a: c2.y);
300 w.z = PxAbs(a: c0.z) + PxAbs(a: c1.z) + PxAbs(a: c2.z);
301
302 return PxBounds3(center - w, center + w);
303}
304
305PX_CUDA_CALLABLE PX_INLINE PxBounds3 PxBounds3::poseExtent(const PxTransform& pose, const PxVec3& extent)
306{
307 return basisExtent(center: pose.p, basis: PxMat33(pose.q), extent);
308}
309
310PX_CUDA_CALLABLE PX_FORCE_INLINE void PxBounds3::setEmpty()
311{
312 minimum = PxVec3(PX_MAX_BOUNDS_EXTENTS);
313 maximum = PxVec3(-PX_MAX_BOUNDS_EXTENTS);
314}
315
316PX_CUDA_CALLABLE PX_FORCE_INLINE void PxBounds3::setMaximal()
317{
318 minimum = PxVec3(-PX_MAX_BOUNDS_EXTENTS);
319 maximum = PxVec3(PX_MAX_BOUNDS_EXTENTS);
320}
321
322PX_CUDA_CALLABLE PX_FORCE_INLINE void PxBounds3::include(const PxVec3& v)
323{
324 PX_SHARED_ASSERT(isValid());
325 minimum = minimum.minimum(v);
326 maximum = maximum.maximum(v);
327}
328
329PX_CUDA_CALLABLE PX_FORCE_INLINE void PxBounds3::include(const PxBounds3& b)
330{
331 PX_SHARED_ASSERT(isValid());
332 minimum = minimum.minimum(v: b.minimum);
333 maximum = maximum.maximum(v: b.maximum);
334}
335
336PX_CUDA_CALLABLE PX_FORCE_INLINE bool PxBounds3::isEmpty() const
337{
338 PX_SHARED_ASSERT(isValid());
339 return minimum.x > maximum.x;
340}
341
342PX_CUDA_CALLABLE PX_FORCE_INLINE bool PxBounds3::intersects(const PxBounds3& b) const
343{
344 PX_SHARED_ASSERT(isValid() && b.isValid());
345 return !(b.minimum.x > maximum.x || minimum.x > b.maximum.x || b.minimum.y > maximum.y || minimum.y > b.maximum.y ||
346 b.minimum.z > maximum.z || minimum.z > b.maximum.z);
347}
348
349PX_CUDA_CALLABLE PX_FORCE_INLINE bool PxBounds3::intersects1D(const PxBounds3& a, uint32_t axis) const
350{
351 PX_SHARED_ASSERT(isValid() && a.isValid());
352 return maximum[axis] >= a.minimum[axis] && a.maximum[axis] >= minimum[axis];
353}
354
355PX_CUDA_CALLABLE PX_FORCE_INLINE bool PxBounds3::contains(const PxVec3& v) const
356{
357 PX_SHARED_ASSERT(isValid());
358
359 return !(v.x < minimum.x || v.x > maximum.x || v.y < minimum.y || v.y > maximum.y || v.z < minimum.z ||
360 v.z > maximum.z);
361}
362
363PX_CUDA_CALLABLE PX_FORCE_INLINE bool PxBounds3::isInside(const PxBounds3& box) const
364{
365 PX_SHARED_ASSERT(isValid() && box.isValid());
366 if(box.minimum.x > minimum.x)
367 return false;
368 if(box.minimum.y > minimum.y)
369 return false;
370 if(box.minimum.z > minimum.z)
371 return false;
372 if(box.maximum.x < maximum.x)
373 return false;
374 if(box.maximum.y < maximum.y)
375 return false;
376 if(box.maximum.z < maximum.z)
377 return false;
378 return true;
379}
380
381PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 PxBounds3::getCenter() const
382{
383 PX_SHARED_ASSERT(isValid());
384 return (minimum + maximum) * 0.5f;
385}
386
387PX_CUDA_CALLABLE PX_FORCE_INLINE float PxBounds3::getCenter(uint32_t axis) const
388{
389 PX_SHARED_ASSERT(isValid());
390 return (minimum[axis] + maximum[axis]) * 0.5f;
391}
392
393PX_CUDA_CALLABLE PX_FORCE_INLINE float PxBounds3::getExtents(uint32_t axis) const
394{
395 PX_SHARED_ASSERT(isValid());
396 return (maximum[axis] - minimum[axis]) * 0.5f;
397}
398
399PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 PxBounds3::getDimensions() const
400{
401 PX_SHARED_ASSERT(isValid());
402 return maximum - minimum;
403}
404
405PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 PxBounds3::getExtents() const
406{
407 PX_SHARED_ASSERT(isValid());
408 return getDimensions() * 0.5f;
409}
410
411PX_CUDA_CALLABLE PX_FORCE_INLINE void PxBounds3::scaleSafe(float scale)
412{
413 PX_SHARED_ASSERT(isValid());
414 if(!isEmpty())
415 scaleFast(scale);
416}
417
418PX_CUDA_CALLABLE PX_FORCE_INLINE void PxBounds3::scaleFast(float scale)
419{
420 PX_SHARED_ASSERT(isValid());
421 *this = centerExtents(center: getCenter(), extent: getExtents() * scale);
422}
423
424PX_CUDA_CALLABLE PX_FORCE_INLINE void PxBounds3::fattenSafe(float distance)
425{
426 PX_SHARED_ASSERT(isValid());
427 if(!isEmpty())
428 fattenFast(distance);
429}
430
431PX_CUDA_CALLABLE PX_FORCE_INLINE void PxBounds3::fattenFast(float distance)
432{
433 PX_SHARED_ASSERT(isValid());
434 minimum.x -= distance;
435 minimum.y -= distance;
436 minimum.z -= distance;
437
438 maximum.x += distance;
439 maximum.y += distance;
440 maximum.z += distance;
441}
442
443PX_CUDA_CALLABLE PX_INLINE PxBounds3 PxBounds3::transformSafe(const PxMat33& matrix, const PxBounds3& bounds)
444{
445 PX_SHARED_ASSERT(bounds.isValid());
446 return !bounds.isEmpty() ? transformFast(matrix, bounds) : bounds;
447}
448
449PX_CUDA_CALLABLE PX_INLINE PxBounds3 PxBounds3::transformFast(const PxMat33& matrix, const PxBounds3& bounds)
450{
451 PX_SHARED_ASSERT(bounds.isValid());
452 return PxBounds3::basisExtent(center: matrix * bounds.getCenter(), basis: matrix, extent: bounds.getExtents());
453}
454
455PX_CUDA_CALLABLE PX_INLINE PxBounds3 PxBounds3::transformSafe(const PxTransform& transform, const PxBounds3& bounds)
456{
457 PX_SHARED_ASSERT(bounds.isValid());
458 return !bounds.isEmpty() ? transformFast(transform, bounds) : bounds;
459}
460
461PX_CUDA_CALLABLE PX_INLINE PxBounds3 PxBounds3::transformFast(const PxTransform& transform, const PxBounds3& bounds)
462{
463 PX_SHARED_ASSERT(bounds.isValid());
464 return PxBounds3::basisExtent(center: transform.transform(input: bounds.getCenter()), basis: PxMat33(transform.q), extent: bounds.getExtents());
465}
466
467PX_CUDA_CALLABLE PX_FORCE_INLINE bool PxBounds3::isValid() const
468{
469 return (isFinite() && (((minimum.x <= maximum.x) && (minimum.y <= maximum.y) && (minimum.z <= maximum.z)) ||
470 ((minimum.x == PX_MAX_BOUNDS_EXTENTS) && (minimum.y == PX_MAX_BOUNDS_EXTENTS) &&
471 (minimum.z == PX_MAX_BOUNDS_EXTENTS) && (maximum.x == -PX_MAX_BOUNDS_EXTENTS) &&
472 (maximum.y == -PX_MAX_BOUNDS_EXTENTS) && (maximum.z == -PX_MAX_BOUNDS_EXTENTS))));
473}
474
475#if !PX_DOXYGEN
476} // namespace physx
477#endif
478
479/** @} */
480#endif // #ifndef PXFOUNDATION_PXBOUNDS3_H
481

source code of qtquick3dphysics/src/3rdparty/PhysX/pxshared/include/foundation/PxBounds3.h