Library of Assembled Shared Sources
aabb_3d.inl
Go to the documentation of this file.
1/** @file
2 * @author Bram de Greve (bram@cocamware.com)
3 * @author Tom De Muer (tom@cocamware.com)
4 *
5 * *** BEGIN LICENSE INFORMATION ***
6 *
7 * The contents of this file are subject to the Common Public Attribution License
8 * Version 1.0 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://lass.sourceforge.net/cpal-license. The License is based on the
11 * Mozilla Public License Version 1.1 but Sections 14 and 15 have been added to cover
12 * use of software over a computer network and provide for limited attribution for
13 * the Original Developer. In addition, Exhibit A has been modified to be consistent
14 * with Exhibit B.
15 *
16 * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
17 * WARRANTY OF ANY KIND, either express or implied. See the License for the specific
18 * language governing rights and limitations under the License.
19 *
20 * The Original Code is LASS - Library of Assembled Shared Sources.
21 *
22 * The Initial Developer of the Original Code is Bram de Greve and Tom De Muer.
23 * The Original Developer is the Initial Developer.
24 *
25 * All portions of the code written by the Initial Developer are:
26 * Copyright (C) 2004-2022 the Initial Developer.
27 * All Rights Reserved.
28 *
29 * Contributor(s):
30 *
31 * Alternatively, the contents of this file may be used under the terms of the
32 * GNU General Public License Version 2 or later (the GPL), in which case the
33 * provisions of GPL are applicable instead of those above. If you wish to allow use
34 * of your version of this file only under the terms of the GPL and not to allow
35 * others to use your version of this file under the CPAL, indicate your decision by
36 * deleting the provisions above and replace them with the notice and other
37 * provisions required by the GPL License. If you do not delete the provisions above,
38 * a recipient may use your version of this file under either the CPAL or the GPL.
39 *
40 * *** END LICENSE INFORMATION ***
41 */
42
43
44
45#ifndef LASS_GUARDIAN_OF_INCLUSION_PRIM_AABB_3D_INL
46#define LASS_GUARDIAN_OF_INCLUSION_PRIM_AABB_3D_INL
47
48
49
50#include "aabb_3d.h"
51#include <cstdlib>
52#include <random>
53
54namespace lass
55{
56
57namespace prim
58{
59
60/** Construct an empty bounding box.
61 */
62template <typename T, class MMP>
64 min_(Vector3D<T>(TNumTraits::max, TNumTraits::max, TNumTraits::max)),
65 max_(Vector3D<T>(TNumTraits::min, TNumTraits::min, TNumTraits::min))
66{
67 LASS_ASSERT(isEmpty());
68}
69
70
71
72/** Construct bounding box, spanned by min and max
73 */
74template <typename T, class MMP>
75Aabb3D<T, MMP>::Aabb3D(const TPoint& min, const TPoint& max):
76 min_(min),
77 max_(max)
78{
79 MMP::checkMinMax(min_, max_);
80 LASS_ASSERT(isValid());
81}
82
83
84
85/** Construct bounding box around a single point (min == max)
86 */
87template <typename T, class MMP>
88Aabb3D<T, MMP>::Aabb3D(const TPoint& point):
89 min_(point),
90 max_(point)
91{
92 LASS_ASSERT(isValid());
93}
94
95
96
97/** copy constructor.
98 */
99template <typename T, class MMP>
100template <class MMP2>
102 min_(other.min()),
103 max_(other.max())
104{
105}
106
107
108
109/** return corner with smallest component values
110 */
111template <typename T, class MMP>
112const typename Aabb3D<T, MMP>::TPoint&
115 LASS_ASSERT(isValid());
116 return min_;
121/** Return corner with largest component values
122 */
123template <typename T, class MMP>
124const typename Aabb3D<T, MMP>::TPoint&
127 LASS_ASSERT(isValid());
128 return max_;
129}
133/** set corner with smallest component values
134 */
135template <typename T, class MMP>
136void Aabb3D<T, MMP>::setMin(const TPoint& min)
138 if (isEmpty())
140 min_ = min;
141 max_ = min;
142 }
143 else
145 MMP::setMin(min_, max_, min);
146 }
148
149
150
151/** set corner with larges component values
152 */
153template <typename T, class MMP>
154void Aabb3D<T, MMP>::setMax(const TPoint& max)
155{
156 if (isEmpty())
157 {
158 min_ = max;
159 max_ = max;
160 }
161 else
162 {
163 MMP::setMax(min_, max_, max);
164 }
165}
166
167
168
169/** assign one bounding box to another.
170 */
171template <typename T, class MMP>
172template <class MMP2>
173typename Aabb3D<T, MMP>::TSelf&
175{
176 TSelf temp(other);
177 swap(temp);
178 return *this;
179}
180
181
182
183/** Expand bounding box so it contains point.
184 */
185template <typename T, class MMP>
186typename Aabb3D<T, MMP>::TSelf&
187Aabb3D<T, MMP>::operator+=(const TPoint& point)
188{
189 LASS_ASSERT(isValid());
190 min_ = pointwiseMin(min_, point);
191 max_ = pointwiseMax(max_, point);
192 return *this;
193}
194
195
196
197/** Expand boundix box so it contains the other bounding box.
198 */
199template <typename T, class MMP>
200template <class MMP2>
201typename Aabb3D<T, MMP>::TSelf&
203{
204 LASS_ASSERT(isValid());
205 min_ = pointwiseMin(min_, other.min());
206 max_ = pointwiseMax(max_, other.max());
207 return *this;
208}
209
210/** Expand bounding box by distance iDistance. Negative values causing
211 * reversal of the bounding box will cause the box to shrink to the
212 * empty box.
213 */
214template <typename T, class MMP>
215void Aabb3D<T, MMP>::grow(TParam iDistance)
216{
217 grow(TVector(iDistance, iDistance, iDistance));
218}
219
220/** Expand bounding box by axis-dependent distance. Negative values causing
221 * reversal of the bounding box will cause the box to shrink to the
222 * empty box.
223 */
224template <typename T, class MMP>
225void Aabb3D<T, MMP>::grow(TVector iDistance)
226{
227 min_ -= iDistance;
228 max_ += iDistance;
229 if (max_.x < min_.x || max_.y < min_.y || max_.z < min_.z)
230 {
231 clear();
232 }
233 LASS_ASSERT(isValid());
234}
235
236
237/** Scale bounding box by scale iScale. Fractions will shrink the bounding box.
238 * The origin of scaling is the center of the bounding box. Negative values of the
239 * scale have same effect as positive ones.
240 */
241template <typename T, class MMP>
242void Aabb3D<T, MMP>::scale(TParam iScale)
243{
244 const TVector extra = size() * ((num::abs(iScale) - 1) / 2);
245 min_ -= extra;
246 max_ += extra;
247 LASS_ASSERT(isValid());
248}
249
250
251
252/** Return the center point of the bounding box.
253 * We return a homogeneous point to avoid the division by two (that might not be supported
254 * by some types like integers)
255 */
256template <typename T, class MMP>
257const typename Aabb3D<T, MMP>::TPointH
259{
260 LASS_ASSERT(isValid());
261 return min_ + max_;
262}
263
264
265
266/** Return size of bounding box per axis, max - min.
267 */
268template <typename T, class MMP>
269const typename Aabb3D<T, MMP>::TVector
271{
272 if (isEmpty())
273 {
274 return TVector();
275 }
276 return max_ - min_;
277}
278
279
280
281/** Returns surface area of bounding box.
282 * the surface of a bounding box consists of three pair of rectangles
283 */
284template <typename T, class MMP>
285const typename Aabb3D<T, MMP>::TValue
287{
288 if (isEmpty())
289 {
290 return 0;
291 }
292 const TVector result = size();
293 return 2 * (result.x * result.y + result.y * result.z + result.z * result.x);
294}
295
296
297
298/** Returns volume of bounding box.
299 */
300template <typename T, class MMP>
301const typename Aabb3D<T, MMP>::TValue
303{
304 if (isEmpty())
305 {
306 return 0;
307 }
308 const TVector result = size();
309 return result.x * result.y * result.z;
310}
311
312
313/** Classify if a point is in or outside the bounding box, or on its surface
314 * @return sInside, sSurface, sOutside
315 */
316template <typename T, class MMP>
317Side Aabb3D<T, MMP>::classify(const TPoint& point) const
318{
319 LASS_ASSERT(isValid());
320
321 if (point.x > min_.x && point.x < max_.x &&
322 point.y > min_.y && point.y < max_.y &&
323 point.z > min_.z && point.z < max_.z)
324 {
325 return sInside;
326 }
327
328 if (point.x < min_.x || point.x > max_.x ||
329 point.y < min_.y || point.y > max_.y ||
330 point.z < min_.z || point.z > max_.z)
331 {
332 return sOutside;
333 }
334
335 return sSurface;
336}
337
338
339
340/** Returns true if point is inside bounding box or on its surface.
341 * Is equivalent to this->classify(point) != sOutside, but might be faster.
342 */
343template <typename T, class MMP>
344bool Aabb3D<T, MMP>::contains(const TPoint& point) const
345{
346 LASS_ASSERT(isValid());
347 return point.x >= min_.x && point.x <= max_.x &&
348 point.y >= min_.y && point.y <= max_.y &&
349 point.z >= min_.z && point.z <= max_.z;
350}
351
352
353
354/** Returns true if the AABB other is inside (or on its surface) this AABB.
355 * - Is equivalent to this->contains(other.min()) && this->contains(other.max()).
356 * - if other is an empty AABB, it will always return true (an empty set is always a part of
357 * any other set).
358 */
359template <typename T, class MMP>
360template <class MMP2>
362{
363 LASS_ASSERT(isValid() && other.isValid());
364 return other.min().x >= min_.x && other.max().x <= max_.x
365 && other.min().y >= min_.y && other.max().y <= max_.y
366 && other.min().z >= min_.z && other.max().z <= max_.z;
367}
368
369
370
371/** Check if two axis-aligned bounding boxes do intersect.
372 * @return @arg false intersection of the AABBs is empty.
373 * @arg true intersection of the AABBs is not empty.
374 *
375 * @par FAQ: What's the difference between @c this->intersects(other) and @c this->collides(other) ?
376 * When two AABB are touching each other (surface to surface), the intersection isn't empty.
377 * i.e. the intersection is the line of points that belong to both the surfaces of the AABBs.
378 * In that case, the intersection is a degenerated AABB though, one with @c volume()==0.
379 * In collision detection however, you don't want this degenerated case of intersection to be
380 * considered as a collision. Two bodies may touch, but the must not have an overlap thas has a
381 * non-zero volume. That's why we have two methods: @c intersects returns true on touching
382 * AABBs, @c collides will return false. Of course, in the non-degenerate cases, they behave the
383 * same.
384 *
385 * Use the seperating axis test to test if two AABB's do intersect:
386 * GOMEZ M. (1999), <i>Simple Intersection Tests For Games</i>, Gamasutra,
387 * http://www.gamasutra.com,
388 * http://www.gamasutra.com/features/19991018/Gomez_3.htm
389 */
390template <typename T, class MMP>
391template <class MMP2>
393{
394 LASS_ASSERT(isValid() && other.isValid());
395 if (other.max().x < min_.x || other.min().x > max_.x) return false;
396 if (other.max().y < min_.y || other.min().y > max_.y) return false;
397 if (other.max().z < min_.z || other.min().z > max_.z) return false;
398 return true;
399}
400
401
402
403/** Check if two axis-aligned bounding boxes do dollide.
404 * @return @arg true the AABBs do collide.
405 * @arg false they don't.
406 *
407 * @par FAQ: What's the difference between @c this->intersects(other) and @c this->collides(other) ?
408 * When two AABB are touching each other (surface to surface), the intersection isn't empty.
409 * i.e. the intersection is the line of points that belong to both the surfaces of the AABBs.
410 * In that case, the intersection is a degenerated AABB though, one with @c volume()==0.
411 * In collision detection however, you don't want this degenerated case of intersection to be
412 * considered as a collision. Two bodies may touch, but the must not have an overlap thas has a
413 * non-zero volume. That's why we have two methods: @c intersects returns true on touching
414 * AABBs, @c collides will return false. Of course, in the non-degenerate cases, they behave the
415 * same.
416 *
417 * Use the seperating axis test to test if two AABB's do intersect:
418 * GOMEZ M. (1999), <i>Simple Intersection Tests For Games</i>, Gamasutra,
419 * http://www.gamasutra.com,
420 * http://www.gamasutra.com/features/19991018/Gomez_3.htm
421 */
422template <typename T, class MMP>
423template <class MMP2>
425{
426 LASS_ASSERT(isValid() && other.isValid());
427 if (other.max().x <= min_.x || other.min().x >= max_.x) return false;
428 if (other.max().y <= min_.y || other.min().y >= max_.y) return false;
429 if (other.max().z <= min_.z || other.min().z >= max_.z) return false;
430 return true;
431}
432
433
434
435
436
437
438/** Return a random point so that bounding box contains it.
439 */
440template <typename T, class MMP>
441template <class RandomGenerator>
442const typename Aabb3D<T, MMP>::TPoint
443Aabb3D<T, MMP>::random(RandomGenerator& generator) const
444{
445 LASS_ASSERT(isValid());
446 std::uniform_real_distribution<TValue> uniform;
447 const TVector t(uniform(generator), uniform(generator), uniform(generator));
448 const TPoint result(min_ + t * (max_ - min_));
449 LASS_ASSERT(contains(result));
450 return result;
451}
452
453
454
455/** set AABB to an empty box
456 */
457template <typename T, class MMP>
459{
460 min_ = TPoint(TNumTraits::max, TNumTraits::max, TNumTraits::max);
461 max_ = TPoint(TNumTraits::min, TNumTraits::min, TNumTraits::min);
462 LASS_ASSERT(isValid() && isEmpty());
463}
464
465
466
467/** Return true if bounding box contains no points.
468 * i.e. this->contains(Point3<T>(x, y, z)) will return false for all possible values of
469 * x, y and z.
470 */
471template <typename T, class MMP>
473{
474 LASS_ASSERT(isValid());
475 return min_.x > max_.x;
476}
477
478
479
480/** internal check to see if AABB is valid.
481 * There are two valid states for the AABB:
482 * @arg <tt>max_.x < min_.x</tt> which means the box is empty
483 * @arg <tt>max_.x >= min_.x && max_.y >= min_.y && max_.z >= min_.z</tt> which means the box is
484 * not empty.
485 * That gives us an invalid state as well:
486 * @arg <tt>max_.x >= min_.x && (max_.y < min_.y || max_.z < min_.z)</tt>. This state would cause
487 * @c isEmpty() to yield false, while there's still nothing in it (there's no single point for
488 * which @c contains(p) would return true.
489 *
490 * When the regular minmax policies are used (StrictMinMax and AutoMinMax), there's no way any AABB
491 * would become invalid, and this test counts as an invariant to the box. However, when using the
492 * UncheckedMinMax policy, you're on your own.
493 */
494template <typename T, class MMP>
496{
497 return (min_.x <= max_.x && min_.y <= max_.y && min_.z <= max_.z) || (min_.x > max_.x);
498}
499
500
501
502/** swap two bounding boxes.
503 */
504template <typename T, class MMP>
505template <typename MMP2>
507{
508 std::swap(min_, other.min_);
509 std::swap(max_, other.max_);
510}
511
512
513
514// --- free ----------------------------------------------------------------------------------------
515
516/** join two AABBs
517 * @relates Aabb3D
518 */
519template <typename T, class MMPa, class MMPb> inline
521{
522 Aabb3D<T, MMPa> result(a);
523 result += b;
524 return result;
525}
526
527
528
529/** add a point to an AABB
530 * @relates Aabb3D
531 */
532template <typename T, class MMP> inline
534{
535 Aabb3D<T, MMP> result(a);
536 result += b;
537 return result;
538}
539
540
541
542/** add a point to an AABB
543 * @relates Aabb3D
544 */
545template <typename T, class MMP> inline
547{
548 Aabb3D<T, MMP> result(b);
549 result += a;
550 return result;
551}
552
553
554
555/** @relates Aabb3D
556 */
557template <typename T>
558const Aabb3D<T> aabb(const Point3D<T>& point)
559{
560 return Aabb3D<T>(point, point);
561}
562
563
564
565/** distance between AABB and point
566 * @relates Aabb3D
567 * @param a AABB
568 * @param b point
569 * @return absolute distance between point and AABB. If point is inside AABB, distance is 0.
570 * @pre @a a should not be empty. Undefined behaviour if it is empty.
571 */
572template <typename T, class MMP> inline
573T distance(const Aabb3D<T, MMP>& a, const Point3D<T>& b)
574{
575 LASS_ASSERT(!a.isEmpty());
576 typedef Vector3D<T> TVector;
577 return pointwiseMax(pointwiseMax(a.min() - b, b - a.max()), TVector()).norm();
578}
579
580
581
582/** distance between two AABBs
583 * @relates Aabb3D
584 * @param a AABB
585 * @param b AABB
586 * @return absolute distance. If one AABB is completely inside the other, distance is 0.
587 * @pre @a a and @a b should not be empty. Undefined behaviour if they are.
588 */
589template <typename T, class MMPa, class MMPb> inline
591{
592 LASS_ASSERT(!a.isEmpty() && !b.isEmpty());
593 typedef Vector3D<T> TVector;
594 return pointwiseMax(pointwiseMax(a.min() - b.max(), b.min() - a.max()), TVector()).norm();
595}
596
597
598
599/** Calculate the intersection of two axis aligned bounding boxes.
600 * @relates lass::prim::Aabb3D
601 * @param a the first AABB :)
602 * @param b the second AABB
603 * @param result the intersection of @a a and @a b. In contrary to other intersection
604 * functions, this output argument will @e always be assigned, even if there's no
605 * result. By no result we mean: the intersection is empty. For most other
606 * intersection functions, we can't assign a meaning full value if there's no
607 * intersection, so we don't. However, in this case we can assign an @e empty AABB.
608 * And that's exactly what we do. So, the output argument is @e always valid, even
609 * if the return value suggests otherwise (in fact, you don't have to bother the
610 * return value this time)
611 * @return @arg rNone intersection of the AABBs is empty.
612 * @a result is an @e empty AABB.
613 * @arg rOne intersection of the AABBs is not empty.
614 * @a result contains intersection.
615 */
616template <typename T, class MMPa, class MMPb, class MMPr>
618{
619 LASS_ASSERT(a.isValid() && b.isValid());
620
621 if (!a.intersects(b))
622 {
623 result = Aabb3D<T, MMPr>(); // empty box
624 return rNone;
625 }
626
627 // by now, we're sure they are intersecting. now, we only need the highest minimum
628 // and lowest maximum.
629 //
630 result = Aabb3D<T, MMPr>(pointwiseMax(a.min(), b.min()), pointwiseMin(a.max(), b.max()));
631 return rOne;
632}
633
634
635
636template <typename T, class MMPa, class MMPb> inline
637bool intersects(const Aabb3D<T, MMPa>& a, const Aabb3D<T, MMPb>& b)
638{
639 return a.intersects(b);
640}
641
642
643
644/** @relates lass::prim::Aabb2D
645 */
646template <typename T, typename MMP> inline
647bool intersects(const Aabb3D<T, MMP>& a, const Point3D<T>& b)
648{
649 return a.contains(b);
650}
651
652
653
654/** @relates lass::prim::Aabb2D
655 */
656template <typename T, typename MMP> inline
657bool intersects(const Point3D<T>& a, const Aabb3D<T, MMP>& b)
658{
659 return b.contains(a);
660}
661
662
663
664template <typename T, class MMPa, class MMPb> inline
665bool collides(const Aabb3D<T, MMPa>& a, const Aabb3D<T, MMPb>& b)
666{
667 return a.collides(b);
668}
669
670
671
672/** @relates lass::prim::Aabb2D
673 */
674template <typename T, typename MMP> inline
675bool collides(const Aabb3D<T, MMP>& a, const Point3D<T>& b)
676{
677 typedef typename Aabb3D<T, MMP>::TPoint TPoint;
678 const TPoint& min = a.min();
679 const TPoint& max = a.max();
680 return min.x < b.x && b.x < max.x &&
681 min.y < b.y && b.y < max.y &&
682 min.z < b.z && b.z < max.z;
683}
684
685
686
687/** @relates lass::prim::Aabb2D
688 */
689template <typename T, typename MMP> inline
690bool collides(const Point3D<T>& a, const Aabb3D<T, MMP>& b)
691{
692 return collides(b, a);
693}
694
695
696
697/** @relates lass::prim::Aabb3D
698 */
699template <typename T, class MMP>
700std::ostream& operator<<(std::ostream& stream, const Aabb3D<T, MMP>& aabb)
701{
702 LASS_ENFORCE_STREAM(stream) << "{m=" << aabb.min() << ", M=" << aabb.max() << "}";
703 return stream;
704}
705
706
707
708/** @relates lass::prim::Aabb3D
709 */
710template<typename T, class MMP>
711io::XmlOStream& operator<<(io::XmlOStream& stream, const Aabb3D<T, MMP>& aabb)
712{
713 LASS_ENFORCE_STREAM(stream)
714 << "<Aabb3D>\n"
715 << "<min>" << aabb.min() << "</min>\n"
716 << "<max>" << aabb.max() << "</max>\n"
717 << "</Aabb3D>\n";
718
719 return stream;
720}
721
722
723
724}
725
726}
727
728#endif
your momma's axis aligned bounding box.
Definition aabb_3d.h:89
const TVector size() const
Return size of bounding box per axis, max - min.
Definition aabb_3d.inl:270
TSelf & operator+=(const TPoint &point)
Expand bounding box so it contains point.
Definition aabb_3d.inl:187
const Aabb3D< T, MMP > operator+(const Point3D< T > &a, const Aabb3D< T, MMP > &b)
add a point to an AABB
Definition aabb_3d.inl:546
const TValue volume() const
Returns volume of bounding box.
Definition aabb_3d.inl:302
void clear()
set AABB to an empty box
Definition aabb_3d.inl:458
const TPointH center() const
Return the center point of the bounding box.
Definition aabb_3d.inl:258
bool intersects(const Aabb3D< T, MMP2 > &other) const
Check if two axis-aligned bounding boxes do intersect.
Definition aabb_3d.inl:392
T distance(const Aabb3D< T, MMPa > &a, const Aabb3D< T, MMPb > &b)
distance between two AABBs
Definition aabb_3d.inl:590
const TPoint random(RandomGenerator &random) const
Return a random point so that bounding box contains it.
Definition aabb_3d.inl:443
const TPoint & min() const
return corner with smallest component values
Definition aabb_3d.inl:113
void scale(TParam iScale)
Scale bounding box by scale iScale.
Definition aabb_3d.inl:242
T distance(const Aabb3D< T, MMP > &a, const Point3D< T > &b)
distance between AABB and point
Definition aabb_3d.inl:573
const TPoint & max() const
Return corner with largest component values.
Definition aabb_3d.inl:125
Side classify(const TPoint &point) const
Classify if a point is in or outside the bounding box, or on its surface.
Definition aabb_3d.inl:317
TSelf & operator=(const Aabb3D< T, MMP2 > &other)
assign one bounding box to another.
Definition aabb_3d.inl:174
Result intersect(const Aabb3D< T, MMPa > &a, const Aabb3D< T, MMPb > &b, Aabb3D< T, MMPr > &result)
Calculate the intersection of two axis aligned bounding boxes.
Definition aabb_3d.inl:617
const TValue area() const
Returns surface area of bounding box.
Definition aabb_3d.inl:286
bool collides(const Aabb3D< T, MMP2 > &other) const
Check if two axis-aligned bounding boxes do dollide.
Definition aabb_3d.inl:424
void grow(TParam iDistance)
Expand bounding box by distance iDistance.
Definition aabb_3d.inl:215
void setMin(const TPoint &min)
set corner with smallest component values
Definition aabb_3d.inl:136
const Aabb3D< T, MMPa > operator+(const Aabb3D< T, MMPa > &a, const Aabb3D< T, MMPb > &b)
join two AABBs
Definition aabb_3d.inl:520
bool isEmpty() const
Return true if bounding box contains no points.
Definition aabb_3d.inl:472
void setMax(const TPoint &max)
set corner with larges component values
Definition aabb_3d.inl:154
bool isValid() const
internal check to see if AABB is valid.
Definition aabb_3d.inl:495
const Aabb3D< T, MMP > operator+(const Aabb3D< T, MMP > &a, const Point3D< T > &b)
add a point to an AABB
Definition aabb_3d.inl:533
bool contains(const TPoint &point) const
Returns true if point is inside bounding box or on its surface.
Definition aabb_3d.inl:344
Aabb3D()
Construct an empty bounding box.
Definition aabb_3d.inl:63
void swap(Aabb3D< T, MMP2 > &other)
swap two bounding boxes.
Definition aabb_3d.inl:506
T abs(const T &x)
if x < 0 return -x, else return x.
Definition basic_ops.h:145
set of geometrical primitives
Definition aabb_2d.h:81
Side
Different sides of a surface.
Definition side.h:79
@ sOutside
outside the surface
Definition side.h:86
@ sSurface
right on the surface
Definition side.h:87
@ sInside
inside the surface
Definition side.h:85
Result
meta information on the result you have from an operation like an intersection ...
Definition result.h:74
@ rNone
operation has no answer, output arguments are meaningless
Definition result.h:76
@ rOne
there's exactly one answer, 1 output argument contains the answer
Definition result.h:77
Library for Assembled Shared Sources.
Definition config.h:53
const TValue norm() const
Return norm of vector.