Skip to main content

aabb.ixx File

Axis-Aligned Bounding Box (AABB) type and transformations. More...

Included Headers

#include <memory> #include <cassert> #include <helios.math.traits.FloatingPointType> #include <helios.math.concepts> #include <helios.math.types:mat4>

Namespaces Index

namespacehelios
namespacemath

Mathematical operations and types. More...

Classes Index

structaabb<T>

Axis-Aligned Bounding Box for spatial culling and collision detection. More...

Description

Axis-Aligned Bounding Box (AABB) type and transformations.

File Listing

The file content with the documentation metadata removed is:

1/**
2 * @file aabb.ixx
3 * @brief Axis-Aligned Bounding Box (AABB) type and transformations.
4 */
5module;
6
7#include <memory>
8#include <cassert>
9
10export module helios.math.types:aabb;
11
12import :vec3;
13import :mat4;
14import helios.math.concepts;
15import helios.math.traits.FloatingPointType;
16
17export namespace helios::math {
18
19 /**
20 * @brief Axis-Aligned Bounding Box for spatial culling and collision detection.
21 *
22 * An AABB is defined by two corner points: a minimum and maximum point in 3D space.
23 * Depending on the use case, the box is aligned to the world or local coordinate axes.
24 *
25 * Common use cases include frustum culling, broad-phase collision detection,
26 * and spatial partitioning in scene graphs.
27 *
28 * @tparam T The numeric type of the vector components (typically `float` or `double`).
29 *
30 * @see [Gla95, pp. 548-550] Glassner, A. (1995). Graphics Gems
31 * @see [DP11, pp. 304-311] Dunn, F., & Parberry, I. (2011). 3D Math Primer for Graphics and Game Development
32 */
33 template<helios::math::Numeric T>
34 struct aabb {
35
36 private:
37 /**
38 * @brief Minimum corner point of the bounding box.
39 *
40 * Contains the smallest x, y, and z coordinates across all points within the AABB.
41 */
43
44 /**
45 * @brief Maximum corner point of the bounding box.
46 *
47 * Contains the largest x, y, and z coordinates across all points within the AABB.
48 */
50
51 public:
52
53 /**
54 * @brief Constructs an empty AABB with inverted min/max values.
55 *
56 * The AABB is initialized with min set to the maximum representable value
57 * and max set to the minimum representable value. This allows the first
58 * `add()` call to properly establish the initial bounds.
59 */
60 constexpr aabb() noexcept
61 : min_{std::numeric_limits<T>::max(), std::numeric_limits<T>::max(), std::numeric_limits<T>::max()},
62 max_{std::numeric_limits<T>::lowest(), std::numeric_limits<T>::lowest(), std::numeric_limits<T>::lowest()}
63 {}
64
65 /**
66 * @brief Constructs an AABB from individual component values.
67 *
68 * @param minX Minimum X coordinate.
69 * @param minY Minimum Y coordinate.
70 * @param minZ Minimum Z coordinate.
71 * @param maxX Maximum X coordinate.
72 * @param maxY Maximum Y coordinate.
73 * @param maxZ Maximum Z coordinate.
74 */
75 constexpr aabb(const T minX, const T minY, const T minZ, const T maxX, const T maxY, const T maxZ) noexcept
76 : min_{minX, minY, minZ},
77 max_{maxX, maxY, maxZ}
78 {}
79
80 /**
81 * @brief Constructs an AABB from two corner points.
82 *
83 * @param min The minimum corner point (smallest x, y, z).
84 * @param max The maximum corner point (largest x, y, z).
85 */
86 constexpr aabb(const helios::math::vec3<T> min, const helios::math::vec3<T> max) noexcept
87 : min_(min),
88 max_(max)
89 {}
90
91 /**
92 * @brief Returns the minimum corner point of the AABB.
93 *
94 * @return Const reference to the minimum corner point.
95 */
96 [[nodiscard]] constexpr const helios::math::vec3<T>& min() const noexcept {
97 return min_;
98 }
99
100 /**
101 * @brief Returns the maximum corner point of the AABB.
102 *
103 * @return Const reference to the maximum corner point.
104 */
105 [[nodiscard]] constexpr const helios::math::vec3<T>& max() const noexcept {
106 return max_;
107 }
108
109 /**
110 * @brief Computes the center point of the AABB.
111 *
112 * @return The center point, calculated as `(min + max) / 2`.
113 */
114 [[nodiscard]] constexpr helios::math::vec3<T> center() const noexcept {
115 return (min_ + max_) * static_cast<T>(0.5);
116 }
117
118 /**
119 * @brief Computes the size of the AABB over all axes.
120 *
121 * @return A vector representing the width, height, and depth of the AABB.
122 */
123 [[nodiscard]] constexpr helios::math::vec3<T> size() const noexcept {
124 return max_ - min_;
125 }
126
127 /**
128 * @brief Checks if this AABB fully contains another AABB.
129 *
130 * @details Tests whether all corners of the specified bounding box lie within
131 * the bounds of this AABB. Both minimum and maximum corners must be contained.
132 *
133 * @param box The AABB to test for containment.
134 *
135 * @return True if the specified box is fully contained within this AABB, false otherwise.
136 */
137 [[nodiscard]] constexpr bool contains(const helios::math::aabb<T>& box) const noexcept {
138
139 auto v_min = box.min();
140 auto v_max = box.max();
141
142 return v_min[0] >= min_[0] && v_min[1] >= min_[1] && v_min[2] >= min_[2] &&
143 v_max[0] <= max_[0] && v_max[1] <= max_[1] && v_max[2] <= max_[2];
144
145 }
146
147 /**
148 * Checks if this AABB fully contains the specified point.
149 *
150 * @param point The vec3 to test for containment.
151 *
152 * @return True if the specified point is fully contained within this AABB, otherwise false.
153 */
154 [[nodiscard]] constexpr bool contains(const helios::math::vec3<T>& point) const noexcept {
155 return point[0] >= min_[0] && point[1] >= min_[1] && point[2] >= min_[2] &&
156 point[0] <= max_[0] && point[1] <= max_[1] && point[2] <= max_[2];
157 }
158
159 /**
160 * @brief Checks if this AABB intersects or touches another AABB.
161 *
162 * @param box The AABB to test for intersection.
163 *
164 * @return True if the specified box intersects this AABB, false otherwise.
165 */
166 [[nodiscard]] constexpr bool intersects(const helios::math::aabb<T>& box) const noexcept {
167
168 if (max_[0] < box.min()[0] || min_[0] > box.max()[0]) {
169 return false;
170 }
171 if (max_[1] < box.min()[1] || min_[1] > box.max()[1]) {
172 return false;
173 }
174 if (max_[2] < box.min()[2] || min_[2] > box.max()[2]) {
175 return false;
176 }
177 return true;
178 }
179
180
181 /**
182 * @brief Translates the AABB by a given vector.
183 *
184 * Creates a new AABB by adding the components of the given translation vector
185 * to the minimum and maximum corner points of the current AABB.
186 *
187 * @param v The translation vector to apply to the AABB.
188 *
189 * @return A new AABB translated by the given vector.
190 */
191 [[nodiscard]] constexpr helios::math::aabb<T> translate(const helios::math::vec3<T>& v) const noexcept {
193 min_ + v, max_ + v
194 };
195 }
196
197
198
199 /**
200 * @brief Expands the AABB to include a given point.
201 *
202 * Updates the minimum and maximum bounds to ensure the specified point
203 * lies within the AABB. Each component is compared independently:
204 * - If a component of the point is smaller than the current minimum, the minimum is updated.
205 * - If a component of the point is larger than the current maximum, the maximum is updated.
206 *
207 * @param point The 3D point to include in the bounding box.
208 */
209 void add(const helios::math::vec3<T>& point) noexcept {
210 min_[0] = std::min(min_[0], point[0]);
211 min_[1] = std::min(min_[1], point[1]);
212 min_[2] = std::min(min_[2], point[2]);
213
214 max_[0] = std::max(max_[0], point[0]);
215 max_[1] = std::max(max_[1], point[1]);
216 max_[2] = std::max(max_[2], point[2]);
217 }
218
219 /**
220 * @brief Transforms the AABB by a 4x4 transformation matrix.
221 *
222 * Applies a transformation matrix to the AABB and returns a new axis-aligned bounding box
223 * that fully contains the transformed original. This method preserves the axis-aligned property
224 * by computing new min/max bounds from the transformed corners.
225 *
226 * The algorithm efficiently transforms only the min/max corners instead of all 8 vertices,
227 * using Arvo's optimization technique from Graphics Gems.
228 *
229 * @param mat The 4x4 transformation matrix to apply.
230 *
231 * @return A new AABB that fully contains the transformed bounding box.
232 *
233 * @see [Gla95, pp. 548-550] "Transforming Axis-Aligned Bounding Boxes" by James Arvo
234 */
235 [[nodiscard]] aabb<T> applyTransform(const mat4<T>& mat) const noexcept {
236
237 const T translationX = static_cast<T>(mat(0, 3));
238 const T translationY = static_cast<T>(mat(1, 3));
239 const T translationZ = static_cast<T>(mat(2, 3));
240
241 vec3<T> newMin = {translationX, translationY, translationZ};
242 vec3<T> newMax = newMin;
243
244 for (int i = 0; i < 3; ++i) {
245 for (int j = 0; j < 3; ++j) {
246
247 T val = static_cast<T>(mat(j, i));
248
249 T e = val * min_[i];
250 T f = val * max_[i];
251
252 if (e < f) {
253 newMin[j] += e;
254 newMax[j] += f;
255 } else {
256 newMin[j] += f;
257 newMax[j] += e;
258 }
259 }
260 }
261
262 return aabb<T>(newMin, newMax);
263 }
264 };
265
266 /**
267 * @brief Computes the signed dimensions of the overlapping region between two axis-aligned
268 * bounding boxes (AABBs).
269 *
270 * Given two AABBs, this function calculates the intersection bounds along each axis.
271 * The resulting vector represents the size (extents) of the intersection.
272 *
273 * @tparam T The numeric type used for the vector components (e.g., `float` or `double`).
274 * @param a The first AABB.
275 * @param b The second AABB.
276 *
277 * @return A 3D vector representing the dimensions of the overlapping region between
278 * the AABBs. If no overlap exists, the resulting vector may contain non-positive
279 * values in one or more components.
280 */
281 template<typename T>
282 [[nodiscard]] constexpr helios::math::vec3<T> overlap(
283 const helios::math::aabb<T> a, const helios::math::aabb<T> b) noexcept {
284
285 const auto overlapMin = helios::math::vec3<T>{
286 std::max(a.min()[0], b.min()[0]),
287 std::max(a.min()[1], b.min()[1]),
288 std::max(a.min()[2], b.min()[2])
289 };
290
291 const auto overlapMax = helios::math::vec3<T>{
292 std::min(a.max()[0], b.max()[0]),
293 std::min(a.max()[1], b.max()[1]),
294 std::min(a.max()[2], b.max()[2])
295 };
296
297 return overlapMax - overlapMin;
298 }
299
300 /**
301 * @brief Computes the center of intersection of the overlapping region between two axis-aligned bounding
302 * boxes (AABBs).
303 *
304 * This function calculates the center of the intersection region of the two AABBs.
305 * If the AABBs do not overlap, the returned value represents the midpoint of the gap between them.
306 *
307 * @tparam T The numeric type used for the vector components (e.g., `float` or `double`).
308 * @param a The first AABB.
309 * @param b The second AABB.
310 *
311 * @return A 3D vector representing the center point of the overlapping or gapping region between the AABBs.
312 */
313 template<typename T>
314 [[nodiscard]] constexpr helios::math::vec3<T> overlapCenter(
315 const helios::math::aabb<T> a, const helios::math::aabb<T> b) noexcept {
316
317 const auto overlapMin = helios::math::vec3<T>{
318 std::max(a.min()[0], b.min()[0]),
319 std::max(a.min()[1], b.min()[1]),
320 std::max(a.min()[2], b.min()[2])
321 };
322
323 const auto overlapMax = helios::math::vec3<T>{
324 std::min(a.max()[0], b.max()[0]),
325 std::min(a.max()[1], b.max()[1]),
326 std::min(a.max()[2], b.max()[2])
327 };
328
329 return (overlapMax + overlapMin) * static_cast<T>(0.5);
330 }
331
332 /**
333 * @brief Adds a translation vector to an AABB.
334 *
335 * This operator overload allows the addition of a translation vector
336 * to an axis-aligned bounding box (AABB), resulting in a new translated AABB.
337 *
338 * @tparam T The numeric type of the vector components (e.g., `float` or `double`).
339 * @param aabb The AABB to be translated.
340 * @param v The translation vector to apply.
341 *
342 * @return A new AABB translated by the given vector.
343 */
344 template<typename T>
345 [[nodiscard]] constexpr helios::math::aabb<T> operator+(
346 const helios::math::aabb<T> aabb, const helios::math::vec3<T> v) noexcept {
347 return aabb.translate(v);
348 }
349
350 /**
351 * @brief Scales an AABB by a given vector.
352 *
353 * This operator overload allows scaling of an axis-aligned bounding box (AABB)
354 * by multiplying its min and max points with the given vector.
355 *
356 * @tparam T The numeric type of the vector components.
357 * @param aabb The AABB to be scaled.
358 * @param v The scaling vector, for which only positive values are allowed.
359 *
360 * @return A new AABB scaled by the given vector.
361 */
362 template<typename T>
363 [[nodiscard]] constexpr helios::math::aabb<T> operator*(
364 const helios::math::aabb<T>& aabb, const helios::math::vec3<T> v) noexcept {
365 assert(v[0] >= 0 && v[1] >= 0 && v[2] >= 0 && "unexpected negative value for scaling vector");
366 return helios::math::aabb<T>{aabb.min() * v, aabb.max() * v};
367 }
368
369 /**
370 * @brief Single-precision floating-point AABB.
371 */
373
374 /**
375 * @brief Integer AABB.
376 */
378
379 /**
380 * @brief Unsigned Integer AABB.
381 */
383
384 /**
385 * @brief Double-precision floating-point AABB.
386 */
388
389} // namespace helios::math

Generated via doxygen2docusaurus 2.0.0 by Doxygen 1.15.0.