libdonut  2.3.2
Application framework for cross-platform game development in C++20
shapes.hpp
Go to the documentation of this file.
1 #ifndef DONUT_SHAPES_HPP
2 #define DONUT_SHAPES_HPP
3 
4 #include <donut/math.hpp>
5 
6 namespace donut {
7 
14 template <length_t L, typename T>
15 using Point = vec<L, T>;
16 
23 template <length_t L, typename T>
24 using Length = vec<L, T>;
25 
32 template <length_t L, typename T>
33 struct LineSegment {
36 };
37 
44 template <length_t L, typename T>
45 struct Sphere {
47  T radius;
48 
54  [[nodiscard]] constexpr bool contains(const Point<L, T>& point) const noexcept;
55 };
56 
62 template <typename T>
63 struct Circle {
65  T radius;
66 
72  constexpr operator Sphere<2, T>() const noexcept {
73  return Sphere<2, T>{.center = center, .radius = radius};
74  }
75 
81  [[nodiscard]] constexpr bool contains(const Point<2, T>& point) const noexcept;
82 };
83 
90 template <length_t L, typename T>
91 struct Capsule {
93  T radius;
94 
100  [[nodiscard]] constexpr bool contains(const Point<L, T>& point) const noexcept;
101 };
102 
109 template <length_t L, typename T>
110 struct Box {
113 
119  [[nodiscard]] constexpr bool contains(const Point<L, T>& point) const noexcept;
120 };
121 
127 template <typename T>
128 struct Rectangle {
131 
137  constexpr operator Box<2, T>() const noexcept {
138  return Box<2, T>{.min = position, .max = position + size};
139  }
140 
146  [[nodiscard]] constexpr bool contains(const Point<2, T>& point) const noexcept;
147 };
148 
156 template <length_t L, typename T>
157 [[nodiscard]] constexpr Box<L, T> getAabbOf(const LineSegment<L, T>& line) noexcept {
158  return {
159  .min = min(line.pointA, line.pointB),
160  .max = max(line.pointA, line.pointB),
161  };
162 }
163 
171 template <length_t L, typename T>
172 [[nodiscard]] constexpr Box<L, T> getAabbOf(const Sphere<L, T>& sphere) noexcept {
173  return {
174  .min = sphere.center - Length<L, T>{sphere.radius},
175  .max = sphere.center + Length<L, T>{sphere.radius},
176  };
177 }
178 
186 template <typename T>
187 [[nodiscard]] constexpr Box<2, T> getAabbOf(const Circle<T>& circle) noexcept {
188  return {
189  .min = circle.center - Length<2, T>{circle.radius},
190  .max = circle.center + Length<2, T>{circle.radius},
191  };
192 }
193 
201 template <length_t L, typename T>
202 [[nodiscard]] constexpr Box<L, T> getAabbOf(const Capsule<L, T>& capsule) noexcept {
203  return {
204  .min = min(capsule.centerLine.pointA, capsule.centerLine.pointB) - Length<L, T>{capsule.radius},
205  .max = max(capsule.centerLine.pointA, capsule.centerLine.pointB) + Length<L, T>{capsule.radius},
206  };
207 }
208 
216 template <length_t L, typename T>
217 [[nodiscard]] constexpr Box<L, T> getAabbOf(const Box<L, T>& box) noexcept {
218  return box;
219 }
220 
228 template <typename T>
229 [[nodiscard]] constexpr Box<2, T> getAabbOf(const Rectangle<T>& rectangle) noexcept {
230  return static_cast<Box<2, T>>(rectangle);
231 }
232 
242 template <length_t L, typename T>
243 [[nodiscard]] constexpr bool intersects(const Sphere<L, T>& a, const Sphere<L, T>& b) noexcept {
244  return distance2(a.center, b.center) < length2(a.radius + b.radius);
245 }
246 
256 template <typename T>
257 [[nodiscard]] constexpr bool intersects(const Circle<T>& a, const Circle<T>& b) noexcept {
258  return intersects(static_cast<Sphere<2, T>>(a), static_cast<Sphere<2, T>>(b));
259 }
260 
270 template <length_t L, typename T>
271 [[nodiscard]] constexpr bool intersects(const Box<L, T>& a, const Box<L, T>& b) noexcept {
272  for (length_t i = 0; i < L; ++i) {
273  if (a.min[i] >= b.max[i] || a.max[i] <= b.min[i]) {
274  return false;
275  }
276  }
277  return true;
278 }
279 
289 template <typename T>
290 [[nodiscard]] constexpr bool intersects(const Rectangle<T>& a, const Rectangle<T>& b) noexcept {
291  return intersects(static_cast<Box<2, T>>(a), static_cast<Box<2, T>>(b));
292 }
293 
303 template <typename T>
304 [[nodiscard]] constexpr bool intersects(const Circle<T>& a, const Sphere<2, T>& b) noexcept {
305  return intersects(static_cast<Sphere<2, T>>(a), b);
306 }
307 
317 template <typename T>
318 [[nodiscard]] constexpr bool intersects(const Sphere<2, T>& a, const Circle<T>& b) noexcept {
319  return intersects(b, a);
320 }
321 
331 template <typename T>
332 [[nodiscard]] constexpr bool intersects(const Rectangle<T>& a, const Box<2, T>& b) noexcept {
333  return intersects(static_cast<Box<2, T>>(a), b);
334 }
335 
345 template <typename T>
346 [[nodiscard]] constexpr bool intersects(const Box<2, T>& a, const Rectangle<T>& b) noexcept {
347  return intersects(b, a);
348 }
349 
359 template <length_t L, typename T>
360 [[nodiscard]] constexpr bool intersects(const Sphere<L, T>& a, const Box<L, T>& b) noexcept {
361  return distance2(a.center, clamp(a.center, b.min, b.max)) < length2(a.radius);
362 }
363 
373 template <length_t L, typename T>
374 [[nodiscard]] constexpr bool intersects(const Box<L, T>& a, const Sphere<L, T>& b) noexcept {
375  return intersects(b, a);
376 }
377 
387 template <typename T>
388 [[nodiscard]] constexpr bool intersects(const Circle<T>& a, const Box<2, T>& b) noexcept {
389  return intersects(static_cast<Sphere<2, T>>(a), b);
390 }
391 
401 template <typename T>
402 [[nodiscard]] constexpr bool intersects(const Box<2, T>& a, const Circle<T>& b) noexcept {
403  return intersects(b, a);
404 }
405 
415 template <typename T>
416 [[nodiscard]] constexpr bool intersects(const Sphere<2, T>& a, const Rectangle<T>& b) noexcept {
417  return intersects(a, static_cast<Box<2, T>>(b));
418 }
419 
429 template <typename T>
430 [[nodiscard]] constexpr bool intersects(const Rectangle<T>& a, const Sphere<2, T>& b) noexcept {
431  return intersects(b, a);
432 }
433 
443 template <typename T>
444 [[nodiscard]] constexpr bool intersects(const Circle<T>& a, const Rectangle<T>& b) noexcept {
445  return intersects(static_cast<Sphere<2, T>>(a), static_cast<Box<2, T>>(b));
446 }
447 
457 template <typename T>
458 [[nodiscard]] constexpr bool intersects(const Rectangle<T>& a, const Circle<T>& b) noexcept {
459  return intersects(b, a);
460 }
461 
471 template <length_t L, typename T>
472 [[nodiscard]] constexpr bool intersects(const Sphere<L, T>& a, const Capsule<L, T>& b) noexcept {
473  const T combinedRadiusSquared = length2(a.radius + b.radius);
474  const vec<L, T> linePointAToPointB = b.centerLine.pointB - b.centerLine.pointA;
475  const vec<L, T> linePointAToSphereCenter = a.center - b.centerLine.pointA;
476  const T linePointAToSphereCenterAlongLine = dot(linePointAToSphereCenter, linePointAToPointB);
477  if (linePointAToSphereCenterAlongLine <= 0.0f) {
478  return length2(linePointAToSphereCenter) < combinedRadiusSquared;
479  }
480  const vec<L, T> linePointBToSphereCenter = a.center - b.centerLine.pointB;
481  const T linePointBToSphereCenterAlongLine = dot(linePointBToSphereCenter, linePointAToPointB);
482  if (linePointBToSphereCenterAlongLine >= 0.0f) {
483  return length2(linePointBToSphereCenter) < combinedRadiusSquared;
484  }
485  const vec<L, T> lineToSphereCenterOrthogonal = linePointAToSphereCenter - linePointAToPointB * (linePointAToSphereCenterAlongLine / length2(linePointAToPointB));
486  return length2(lineToSphereCenterOrthogonal) < combinedRadiusSquared;
487 }
488 
498 template <length_t L, typename T>
499 [[nodiscard]] constexpr bool intersects(const Capsule<L, T>& a, const Sphere<L, T>& b) noexcept {
500  return intersects(b, a);
501 }
502 
512 template <typename T>
513 [[nodiscard]] constexpr bool intersects(const Circle<T>& a, const Capsule<2, T>& b) noexcept {
514  return intersects(static_cast<Sphere<2, T>>(a), b);
515 }
516 
526 template <typename T>
527 [[nodiscard]] constexpr bool intersects(const Capsule<2, T>& a, const Circle<T>& b) noexcept {
528  return intersects(b, a);
529 }
530 
540 template <length_t L, typename T>
541 [[nodiscard]] constexpr bool intersects(const Sphere<L, T>& a, const LineSegment<L, T>& b) noexcept {
542  return intersects(a, Capsule<L, T>{.centerLine = b, .radius = T{0}});
543 }
544 
554 template <length_t L, typename T>
555 [[nodiscard]] constexpr bool intersects(const LineSegment<L, T>& a, const Sphere<L, T>& b) noexcept {
556  return intersects(b, a);
557 }
558 
568 template <typename T>
569 [[nodiscard]] constexpr bool intersects(const Circle<T>& a, const LineSegment<2, T>& b) noexcept {
570  return intersects(static_cast<Sphere<2, T>>(a), b);
571 }
572 
582 template <typename T>
583 [[nodiscard]] constexpr bool intersects(const LineSegment<2, T>& a, const Circle<T>& b) noexcept {
584  return intersects(b, a);
585 }
586 
587 template <length_t L, typename T>
588 constexpr bool Sphere<L, T>::contains(const Point<L, T>& point) const noexcept {
589  return distance2(center, point) < length2(radius);
590 }
591 
592 template <typename T>
593 constexpr bool Circle<T>::contains(const Point<2, T>& point) const noexcept {
594  return static_cast<Sphere<2, T>>(*this).contains(point);
595 }
596 
597 template <length_t L, typename T>
598 constexpr bool Capsule<L, T>::contains(const Point<L, T>& point) const noexcept {
599  return intersects(*this, Sphere<L, T>{.center = point, .radius = T{0}});
600 }
601 
602 template <length_t L, typename T>
603 constexpr bool Box<L, T>::contains(const Point<L, T>& point) const noexcept {
604  for (length_t i = 0; i < L; ++i) {
605  if (point[i] < min[i] || point[i] >= max[i]) {
606  return false;
607  }
608  }
609  return true;
610 }
611 
612 template <typename T>
613 constexpr bool Rectangle<T>::contains(const Point<2, T>& point) const noexcept {
614  return static_cast<Box<2, T>>(*this).contains(point);
615 }
616 
617 } // namespace donut
618 
619 #endif
Definition: Application.hpp:9
vec< L, T > Point
Generic point in space.
Definition: shapes.hpp:15
vec< L, T > Length
Generic length in space.
Definition: shapes.hpp:24
constexpr Box< L, T > getAabbOf(const LineSegment< L, T > &line) noexcept
Get the axis-aligned bounding box of a line segment.
Definition: shapes.hpp:157
constexpr bool intersects(const Sphere< L, T > &a, const Sphere< L, T > &b) noexcept
Check if two spheres intersect.
Definition: shapes.hpp:243
Generic axis-aligned box shape with minimum and maximum extents.
Definition: shapes.hpp:110
constexpr bool contains(const Point< L, T > &point) const noexcept
Check if a given point is contained within the extents of this box.
Definition: shapes.hpp:603
Point< L, T > max
Position with the maximum coordinates of the box extents on each coordinate axis.
Definition: shapes.hpp:112
Point< L, T > min
Position with the minimum coordinates of the box extents on each coordinate axis.
Definition: shapes.hpp:111
Generic capsule shape with a center line segment and radius.
Definition: shapes.hpp:91
T radius
Radius of the capsule from the center line.
Definition: shapes.hpp:93
LineSegment< L, T > centerLine
Center line of the capsule.
Definition: shapes.hpp:92
constexpr bool contains(const Point< L, T > &point) const noexcept
Check if a given point is contained within the extents of this capsule.
Definition: shapes.hpp:598
Flat 2D circle shape with a center and radius.
Definition: shapes.hpp:63
T radius
Radius of the circle.
Definition: shapes.hpp:65
Point< 2, T > center
Position of the center of the circle.
Definition: shapes.hpp:64
constexpr bool contains(const Point< 2, T > &point) const noexcept
Check if a given point is contained within the extents of this circle.
Definition: shapes.hpp:593
Generic line segment between two points.
Definition: shapes.hpp:33
Point< L, T > pointA
Position of the first point of the line segment.
Definition: shapes.hpp:34
Point< L, T > pointB
Position of the second point of the line segment.
Definition: shapes.hpp:35
Flat 2D axis-aligned rectangle shape with a position and size.
Definition: shapes.hpp:128
Length< 2, T > size
Width and height of the rectangle.
Definition: shapes.hpp:130
Point< 2, T > position
Position of the bottom left corner of the rectangle.
Definition: shapes.hpp:129
constexpr bool contains(const Point< 2, T > &point) const noexcept
Check if a given point is contained within the extents of this rectangle.
Definition: shapes.hpp:613
Generic sphere shape with a center and radius.
Definition: shapes.hpp:45
T radius
Radius of the sphere.
Definition: shapes.hpp:47
constexpr bool contains(const Point< L, T > &point) const noexcept
Check if a given point is contained within the extents of this sphere.
Definition: shapes.hpp:588
Point< L, T > center
Position of the center of the sphere.
Definition: shapes.hpp:46