Divide Framework 0.1
A free and open-source 3D Framework under heavy development
Loading...
Searching...
No Matches
OBB.cpp
Go to the documentation of this file.
1
2
3#include "Headers/OBB.h"
4
7
8namespace Divide {
9 OBB::OBB(vec3<F32> pos, vec3<F32> hExtents, OBBAxis axis) noexcept
10 : _position(MOV(pos)),
11 _halfExtents(MOV(hExtents)),
12 _axis(MOV(axis))
13 {
14 }
15
16 OBB::OBB(const BoundingBox &aabb) noexcept
17 {
18 fromBoundingBox(aabb);
19 }
20
21 OBB::OBB(const BoundingSphere &bSphere) noexcept
22 {
23 fromBoundingSphere(bSphere);
24 }
25
26 vec3<F32> OBB::cornerPoint(const U8 cornerIndex) const noexcept {
27 assert(0 <= cornerIndex && cornerIndex <= 7);
28 switch (cornerIndex) {
29 default:
30 case 0: return _position - _halfExtents.x * _axis[0] - _halfExtents.y * _axis[1] - _halfExtents.z * _axis[2];
31 case 1: return _position - _halfExtents.x * _axis[0] - _halfExtents.y * _axis[1] + _halfExtents.z * _axis[2];
32 case 2: return _position - _halfExtents.x * _axis[0] + _halfExtents.y * _axis[1] - _halfExtents.z * _axis[2];
33 case 3: return _position - _halfExtents.x * _axis[0] + _halfExtents.y * _axis[1] + _halfExtents.z * _axis[2];
34 case 4: return _position + _halfExtents.x * _axis[0] - _halfExtents.y * _axis[1] - _halfExtents.z * _axis[2];
35 case 5: return _position + _halfExtents.x * _axis[0] - _halfExtents.y * _axis[1] + _halfExtents.z * _axis[2];
36 case 6: return _position + _halfExtents.x * _axis[0] + _halfExtents.y * _axis[1] - _halfExtents.z * _axis[2];
37 case 7: return _position + _halfExtents.x * _axis[0] + _halfExtents.y * _axis[1] + _halfExtents.z * _axis[2];
38 }
39 }
40
41 void OBB::fromBoundingBox(const BoundingBox& aabb) noexcept {
42 _position.set(aabb.getCenter());
43 _halfExtents.set(aabb.getHalfExtent());
45 }
46
47 void OBB::fromBoundingBox(const BoundingBox& aabb, const mat4<F32>& worldMatrix) {
48 assert(worldMatrix.isColOrthogonal()); // We cannot convert transform an AABB to OBB if it gets sheared in the process.
49
50 fromBoundingBox(aabb);
51 _position = worldMatrix * _position;
52 _axis[0] = Normalized(worldMatrix.transformNonHomogeneous(_axis[0]));
53 _axis[1] = Normalized(worldMatrix.transformNonHomogeneous(_axis[1]));
54 _axis[2] = Normalized(worldMatrix.transformNonHomogeneous(_axis[2]));
55
57 Util::decomposeMatrix(worldMatrix, position, scale);
58 _halfExtents *= scale;
59 OrthoNormalize(_axis[0], _axis[1], _axis[2]);
60 }
61
62 void OBB::fromBoundingBox(const BoundingBox& aabb, const Quaternion<F32>& orientation) {
63 fromBoundingBox(aabb, mat4<F32>(GetMatrix(orientation), false));
64 }
65
66 void OBB::fromBoundingBox(const BoundingBox& aabb, const vec3<F32>& position, const Quaternion<F32>& rotation, const vec3<F32>& scale) {
67 fromBoundingBox(aabb, mat4<F32>(position, scale, GetMatrix(rotation)));
68 }
69
70 void OBB::fromBoundingSphere(const BoundingSphere& sphere) noexcept {
71 _position.set(sphere.getCenter());
72 _halfExtents.set(sphere.getRadius());
74 }
75
76 void OBB::translate(const vec3<F32>& offset) {
77 _position += offset;
78 }
79
80 void OBB::scale(const vec3<F32>& centerPoint, const F32 scaleFactor) {
81 scale(centerPoint, vec3<F32>(scaleFactor));
82 }
83
84 void OBB::scale(const vec3<F32>& centerPoint, const vec3<F32>& scaleFactor) {
85 transform(mat4<F32>(centerPoint, scaleFactor, mat3<F32>()));
86 }
87
88 void OBB::transform(const mat3<F32>& transformIn) {
89 assert(transformIn.isColOrthogonal());
90 transform(mat4<F32>(transformIn, false));
91 }
92
93 void OBB::transform(const mat4<F32>& transform) {
94 assert(transform.isColOrthogonal());
95 _position = transform * _position;
96 for (U8 i = 0u; i < 3u; ++i) {
97 _axis[i] = transform.transform((_halfExtents[i] * _axis[i]), false);
98 _halfExtents[i] = _axis[i].length();
99 _axis[i].normalize();
100 }
101 }
102
103 void OBB::transform(const Quaternion<F32>& rotation) {
104 transform(GetMatrix(rotation));
105 }
106
108 return BoundingBox{ *this };
109 }
110
112 return BoundingSphere{ position(), halfDiagonal().length() };
113 }
114
116 return BoundingSphere{ position(), halfExtents().minComponent() };
117 }
118
119 vec3<F32> OBB::size() const noexcept {
120 return _halfExtents * 2;
121 }
122
123 vec3<F32> OBB::diagonal() const noexcept {
124 return halfDiagonal() * 2;
125 }
126
127 vec3<F32> OBB::halfDiagonal() const noexcept {
128 return _axis[0] * _halfExtents[0] +
129 _axis[1] * _halfExtents[1] +
130 _axis[2] * _halfExtents[2];
131 }
132
133 LineSegment OBB::edge(const U8 edgeIndex) const noexcept {
134 assert(0 <= edgeIndex && edgeIndex <= 11);
135 switch (edgeIndex) {
136 default:
137 case 0: return {cornerPoint(0), cornerPoint(1) };
138 case 1: return {cornerPoint(0), cornerPoint(2) };
139 case 2: return {cornerPoint(0), cornerPoint(4) };
140 case 3: return {cornerPoint(1), cornerPoint(3) };
141 case 4: return {cornerPoint(1), cornerPoint(5) };
142 case 5: return {cornerPoint(2), cornerPoint(3) };
143 case 6: return {cornerPoint(2), cornerPoint(6) };
144 case 7: return {cornerPoint(3), cornerPoint(7) };
145 case 8: return {cornerPoint(4), cornerPoint(5) };
146 case 9: return {cornerPoint(4), cornerPoint(6) };
147 case 10: return {cornerPoint(5), cornerPoint(7) };
148 case 11: return {cornerPoint(6), cornerPoint(7) };
149 }
150 }
151
153 return {
154 edge(0), edge(1), edge(2),
155 edge(3), edge(4), edge(5),
156 edge(6), edge(7), edge(8),
157 edge(9),edge(10), edge(11),
158 };
159 }
160
161 vec3<F32> OBB::closestPoint(const vec3<F32>& point) const noexcept {
162 const vec3<F32> d = point - _position;
163 vec3<F32> closestPoint = _position;
164 for (U8 i = 0; i < 3; ++i) {
165 closestPoint += CLAMPED(Dot(d, _axis[i]), -_halfExtents[i], _halfExtents[i]) * _axis[i];
166 }
167
168 return closestPoint;
169 }
170
171 F32 OBB::distance(const vec3<F32>& point) const noexcept {
172 return closestPoint(point).distance(point);
173 }
174
175 bool OBB::containsPoint(const vec3<F32>& point) const noexcept {
176 const vec3<F32> pt = point - position();
177 return std::abs(Dot(pt, _axis[0])) <= _halfExtents[0] &&
178 std::abs(Dot(pt, _axis[1])) <= _halfExtents[1] &&
179 std::abs(Dot(pt, _axis[2])) <= _halfExtents[2];
180 }
181
182 bool OBB::containsBox(const OBB& OBB) const noexcept {
183 for (U8 i = 0; i < 8; ++i) {
184 if (!containsPoint(OBB.cornerPoint(i))) {
185 return false;
186 }
187 }
188
189 return true;
190 }
191
192 bool OBB::containsBox(const BoundingBox& AABB) const noexcept {
193 for (U8 i = 0; i < 8; ++i) {
194 if (!containsPoint(AABB.cornerPoint(i))) {
195 return false;
196 }
197 }
198
199 return true;
200 }
201
202 bool OBB::containsSphere(const BoundingSphere& bSphere) const noexcept {
203 return distance(bSphere.getCenter()) - bSphere.getRadius() < 0.f;
204 }
205
206 RayResult OBB::intersect(const Ray& ray, const F32 t0In, const F32 t1In) const noexcept {
207 F32 tNear = -F32_MAX;
208 F32 tFar = F32_MAX;
209 for (U8 i = 0; i < 3; ++i) {
210 if (std::abs(Dot(ray._direction, _axis[i])) < EPSILON_F32)
211 {
212 // Ray parallel to planes
213 const F32 r = Dot(_axis[i], _position - ray._origin);
214 if (-r - _halfExtents[i] > 0.f ||
215 -r + _halfExtents[i] > 0.f)
216 {
217 return {};
218 }
219 }
220 const F32 r = Dot(_axis[i], _position - ray._origin);
221 const F32 s = Dot(_axis[i], ray._direction);
222 F32 t0 = (r + _halfExtents[i]) / s;
223 F32 t1 = (r - _halfExtents[i]) / s;
224 if (t0 > t1) {
225 std::swap(t0, t1);
226 }
227 if (t0 > tNear) {
228 tNear = t0;
229 }
230 if (t1 < tFar) {
231 tFar = t1;
232 }
233 if (tFar < 0.f) {
234 return {};
235 }
236 }
237
238 RayResult ret;
239 ret.inside = tNear < 0.f;
240 ret.dist = tNear > 0.f ? tNear : tFar;
241 // Ray started inside the box
242 if (ret.dist < 0.0f) {
243 ret.dist = 0.0f;
244 ret.hit = true;
245 } else {
246 ret.hit = IS_IN_RANGE_INCLUSIVE(ret.dist, t0In, t1In);
247 }
248 return ret;
249 }
250
251} // namespace Divide
#define MOV(...)
LineSegment edge(U8 edgeIndex) const noexcept
Definition: OBB.cpp:133
vec3< F32 > size() const noexcept
Definition: OBB.cpp:119
F32 distance(const vec3< F32 > &point) const noexcept
Definition: OBB.cpp:171
void transform(const mat3< F32 > &transform)
Definition: OBB.cpp:88
bool containsPoint(const vec3< F32 > &point) const noexcept
Definition: OBB.cpp:175
BoundingSphere toEnclosedSphere() const noexcept
Definition: OBB.cpp:115
vec3< F32 > closestPoint(const vec3< F32 > &point) const noexcept
Definition: OBB.cpp:161
bool containsBox(const OBB &OBB) const noexcept
Definition: OBB.cpp:182
RayResult intersect(const Ray &ray, F32 t0In, F32 t1In) const noexcept
Definition: OBB.cpp:206
vec3< F32 > cornerPoint(U8 cornerIndex) const noexcept
Definition: OBB.cpp:26
void fromBoundingSphere(const BoundingSphere &sphere) noexcept
Definition: OBB.cpp:70
void translate(const vec3< F32 > &offset)
Definition: OBB.cpp:76
std::array< LineSegment, 12 > OOBBEdgeList
Definition: OBB.h:52
bool containsSphere(const BoundingSphere &bSphere) const noexcept
Definition: OBB.cpp:202
OBB()=default
OOBBEdgeList edgeList() const noexcept
Definition: OBB.cpp:152
void fromBoundingBox(const BoundingBox &aabb) noexcept
Definition: OBB.cpp:41
BoundingSphere toEnclosingSphere() const noexcept
Definition: OBB.cpp:111
void scale(const vec3< F32 > &centerPoint, F32 scaleFactor)
Uniform scaling.
Definition: OBB.cpp:80
std::array< vec3< F32 >, 3 > OBBAxis
Definition: OBB.h:51
vec3< F32 > halfDiagonal() const noexcept
Definition: OBB.cpp:127
BoundingBox toBoundingBox() const noexcept
Definition: OBB.cpp:107
vec3< F32 > diagonal() const noexcept
Definition: OBB.cpp:123
bool isColOrthogonal() const noexcept
vec3< U > transformNonHomogeneous(const vec3< U > &v) const noexcept
bool isColOrthogonal() const noexcept
T length() const noexcept
return the vector's length
Definition: MathVectors.h:747
bool decomposeMatrix(const mat4< F32 > &transform, vec3< F32 > &translationOut, vec3< F32 > &scaleOut, vec3< Angle::RADIANS< F32 > > &rotationOut, bool &isUniformScaleOut)
Definition: MathHelper.cpp:14
Handle console commands that start with a forward slash.
Definition: AIProcessor.cpp:7
vec2< T > Normalized(vec2< T > vector) noexcept
Definition: MathVectors.inl:98
static const vec3< F32 > WORLD_X_AXIS
Definition: MathVectors.h:1439
bool IS_IN_RANGE_INCLUSIVE(const T x, const U min, const U max) noexcept
uint8_t U8
static const vec3< F32 > WORLD_Z_AXIS
Definition: MathVectors.h:1441
T Dot(vec2< T > a, vec2< T > b) noexcept
general vec2 dot product
constexpr F32 EPSILON_F32
static const vec3< F32 > VECTOR3_UNIT
Definition: MathVectors.h:1437
constexpr F32 F32_MAX
void OrthoNormalize(vec2< T > &n, vec2< T > &u) noexcept
::value constexpr T CLAMPED(T n, T min, T max) noexcept
Definition: MathHelper.inl:126
mat3< T > GetMatrix(const Quaternion< T > &q) noexcept
Definition: Quaternion.inl:719
static const vec3< F32 > VECTOR3_ZERO
Definition: MathVectors.h:1434
static const vec3< F32 > WORLD_Y_AXIS
Definition: MathVectors.h:1440
bool inside
Definition: Ray.h:50
bool hit
Definition: Ray.h:49