Move Vectormath main
C++20 game and graphics mathematics
Loading...
Searching...
No Matches
Obb3.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <array>
5#include <cmath>
6#include <optional>
7#include <span>
8#include <type_traits>
9
12
13namespace mv::math
14{
15 // Center/extents/orientation representation follows DirectXCollision's
16 // BoundingOrientedBox (MIT); Move replaces its unchecked quaternion with
17 // invariant-bearing Rotation3 and validates finite nonnegative extents.
18 template <typename T>
19 requires std::is_floating_point_v<T>
20 class Obb3
21 {
22 public:
23 using Component = T;
24
26
31 {
32 if (!std::isfinite(center.X()) || !std::isfinite(center.Y()) ||
33 !std::isfinite(center.Z()) || !std::isfinite(halfExtents.X()) ||
34 !std::isfinite(halfExtents.Y()) ||
35 !std::isfinite(halfExtents.Z()) || halfExtents.X() < T(0) ||
36 halfExtents.Y() < T(0) || halfExtents.Z() < T(0))
37 {
38 return std::nullopt;
39 }
40 return Obb3(center, halfExtents, orientation, UncheckedTag{});
41 }
42
44 {
45 return Center_;
46 }
47
49 {
50 return HalfExtents_;
51 }
52
54 {
55 return Orientation_;
56 }
57
59 {
60 return Rotate(Orientation_, Direction3<T>::AxisX());
61 }
62
64 {
65 return Rotate(Orientation_, Direction3<T>::AxisY());
66 }
67
69 {
70 return Rotate(Orientation_, Direction3<T>::AxisZ());
71 }
72
74 const Point3<T>& point) const noexcept
75 {
76 const Vec3<T> displacement = point - Center_;
77 const Vec3<T> x = AxisX().Vector();
78 const Vec3<T> y = AxisY().Vector();
79 const Vec3<T> z = AxisZ().Vector();
80 return Center_ +
81 x * std::clamp(Dot(displacement, x), -HalfExtents_.X(),
82 HalfExtents_.X()) +
83 y * std::clamp(Dot(displacement, y), -HalfExtents_.Y(),
84 HalfExtents_.Y()) +
85 z * std::clamp(Dot(displacement, z), -HalfExtents_.Z(),
86 HalfExtents_.Z());
87 }
88
91 {
92 const Vec3<T> displacement = point - Center_;
93 const T margin = std::abs(tolerance);
94 return std::abs(Dot(displacement, AxisX().Vector())) <=
95 HalfExtents_.X() + margin &&
96 std::abs(Dot(displacement, AxisY().Vector())) <=
97 HalfExtents_.Y() + margin &&
98 std::abs(Dot(displacement, AxisZ().Vector())) <=
99 HalfExtents_.Z() + margin;
100 }
101
102 [[nodiscard]] Point3<T> Support(const Vec3<T>& direction) const noexcept
103 {
104 const Vec3<T> x = AxisX().Vector();
105 const Vec3<T> y = AxisY().Vector();
106 const Vec3<T> z = AxisZ().Vector();
107 return Center_ +
108 x * (Dot(direction, x) >= T(0) ? HalfExtents_.X()
109 : -HalfExtents_.X()) +
110 y * (Dot(direction, y) >= T(0) ? HalfExtents_.Y()
111 : -HalfExtents_.Y()) +
112 z * (Dot(direction, z) >= T(0) ? HalfExtents_.Z()
113 : -HalfExtents_.Z());
114 }
115
116 [[nodiscard]] std::array<Point3<T>, 8> Corners() const noexcept
117 {
118 const Vec3<T> x = AxisX().Vector() * HalfExtents_.X();
119 const Vec3<T> y = AxisY().Vector() * HalfExtents_.Y();
120 const Vec3<T> z = AxisZ().Vector() * HalfExtents_.Z();
121 return {Center_ - x - y - z, Center_ + x - y - z,
122 Center_ - x + y - z, Center_ + x + y - z,
123 Center_ - x - y + z, Center_ + x - y + z,
124 Center_ - x + y + z, Center_ + x + y + z};
125 }
126
127 [[nodiscard]] friend bool operator==(const Obb3& left,
128 const Obb3& right) noexcept
129 {
130 return left.Center_ == right.Center_ &&
131 left.HalfExtents_ == right.HalfExtents_ &&
132 left.Orientation_ == right.Orientation_;
133 }
134
135 private:
136 struct UncheckedTag
137 {
138 };
139
140 Obb3(const Point3<T>& center,
141 const Vec3<T>& halfExtents,
142 const Rotation3<T>& orientation,
143 UncheckedTag) noexcept :
144 Center_(center),
145 HalfExtents_(halfExtents),
146 Orientation_(orientation)
147 {
148 }
149
150 Point3<T> Center_{};
151 Vec3<T> HalfExtents_{};
152 Rotation3<T> Orientation_{};
153 };
154
157
158 template <typename T>
160 const RigidTransform3<T>& transform, const Obb3<T>& box) noexcept
161 {
163 TransformPoint(transform, box.Center()), box.HalfExtents(),
164 transform.Rotation() * box.Orientation());
165 }
166
167 template <typename T>
168 [[nodiscard]] inline std::optional<Aabb3<T>> TryTransformConservativeAabb(
169 const AffineTransform3<T>& transform, const Obb3<T>& box) noexcept
170 {
171 std::array<Point3<T>, 8> corners = box.Corners();
172 for (Point3<T>& corner : corners)
173 {
175 }
176 return Aabb3<T>::TryFromPoints(std::span<const Point3<T>>(corners));
177 }
178} // namespace mv::math
179
180static_assert(sizeof(mv::math::Obb3f) == 48);
181static_assert(alignof(mv::math::Obb3f) == 16);
182static_assert(std::is_trivially_copyable_v<mv::math::Obb3f>);
183static_assert(std::is_standard_layout_v<mv::math::Obb3f>);
184static_assert(sizeof(mv::math::Obb3d) == 96);
185static_assert(alignof(mv::math::Obb3d) == 32);
186static_assert(std::is_trivially_copyable_v<mv::math::Obb3d>);
187static_assert(std::is_standard_layout_v<mv::math::Obb3d>);
static std::optional< Aabb3 > TryFromPoints(std::span< const Point3< T > > points) noexcept
Definition Aabb3.hpp:61
static std::optional< Obb3 > TryFromCenterHalfExtents(const Point3< T > &center, const Vec3< T > &halfExtents, const Rotation3< T > &orientation=Rotation3< T >::Identity()) noexcept
Definition Obb3.hpp:27
bool Contains(const Point3< T > &point, T tolerance=T(0)) const noexcept
Definition Obb3.hpp:89
Point3< T > Support(const Vec3< T > &direction) const noexcept
Definition Obb3.hpp:102
Point3< T > ClosestPoint(const Point3< T > &point) const noexcept
Definition Obb3.hpp:73
std::array< Point3< T >, 8 > Corners() const noexcept
Definition Obb3.hpp:116
Direction3< T > AxisZ() const noexcept
Definition Obb3.hpp:68
Direction3< T > AxisY() const noexcept
Definition Obb3.hpp:63
Direction3< T > AxisX() const noexcept
Definition Obb3.hpp:58
const Vec3< T > & HalfExtents() const noexcept
Definition Obb3.hpp:48
Obb3() noexcept=default
friend bool operator==(const Obb3 &left, const Obb3 &right) noexcept
Definition Obb3.hpp:127
const Rotation3< T > & Orientation() const noexcept
Definition Obb3.hpp:53
const Point3< T > & Center() const noexcept
Definition Obb3.hpp:43
constexpr T Dot(const Quat< T > &left, const Quat< T > &right) noexcept
Definition Quat.hpp:102
Obb3< float > Obb3f
Definition Obb3.hpp:155
std::optional< Aabb3< T > > TryTransformConservativeAabb(const AffineTransform3< T > &transform, const Obb3< T > &box) noexcept
Definition Obb3.hpp:168
Obb3< double > Obb3d
Definition Obb3.hpp:156
Vec3< T > TransformPoint(const AffineTransform3< T > &transform, const Vec3< T > &point) noexcept
Vec3< T > Rotate(const Rotation3< T > &rotation, const Vec3< T > &vector) noexcept
Obb3< T > TransformObb(const RigidTransform3< T > &transform, const Obb3< T > &box) noexcept
Definition Obb3.hpp:159