Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/jolt_physics/Jolt/Geometry/AABox.h
9913 views
1
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
2
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
3
// SPDX-License-Identifier: MIT
4
5
#pragma once
6
7
#include <Jolt/Geometry/Triangle.h>
8
#include <Jolt/Geometry/IndexedTriangle.h>
9
#include <Jolt/Geometry/Plane.h>
10
#include <Jolt/Math/Mat44.h>
11
12
JPH_NAMESPACE_BEGIN
13
14
/// Axis aligned box
15
class [[nodiscard]] AABox
16
{
17
public:
18
JPH_OVERRIDE_NEW_DELETE
19
20
/// Constructor
21
AABox() : mMin(Vec3::sReplicate(FLT_MAX)), mMax(Vec3::sReplicate(-FLT_MAX)) { }
22
AABox(Vec3Arg inMin, Vec3Arg inMax) : mMin(inMin), mMax(inMax) { }
23
AABox(DVec3Arg inMin, DVec3Arg inMax) : mMin(inMin.ToVec3RoundDown()), mMax(inMax.ToVec3RoundUp()) { }
24
AABox(Vec3Arg inCenter, float inRadius) : mMin(inCenter - Vec3::sReplicate(inRadius)), mMax(inCenter + Vec3::sReplicate(inRadius)) { }
25
26
/// Create box from 2 points
27
static AABox sFromTwoPoints(Vec3Arg inP1, Vec3Arg inP2) { return AABox(Vec3::sMin(inP1, inP2), Vec3::sMax(inP1, inP2)); }
28
29
/// Create box from indexed triangle
30
static AABox sFromTriangle(const VertexList &inVertices, const IndexedTriangle &inTriangle)
31
{
32
AABox box = sFromTwoPoints(Vec3(inVertices[inTriangle.mIdx[0]]), Vec3(inVertices[inTriangle.mIdx[1]]));
33
box.Encapsulate(Vec3(inVertices[inTriangle.mIdx[2]]));
34
return box;
35
}
36
37
/// Get bounding box of size FLT_MAX
38
static AABox sBiggest()
39
{
40
/// Max half extent of AABox is 0.5 * FLT_MAX so that GetSize() remains finite
41
return AABox(Vec3::sReplicate(-0.5f * FLT_MAX), Vec3::sReplicate(0.5f * FLT_MAX));
42
}
43
44
/// Comparison operators
45
bool operator == (const AABox &inRHS) const { return mMin == inRHS.mMin && mMax == inRHS.mMax; }
46
bool operator != (const AABox &inRHS) const { return mMin != inRHS.mMin || mMax != inRHS.mMax; }
47
48
/// Reset the bounding box to an empty bounding box
49
void SetEmpty()
50
{
51
mMin = Vec3::sReplicate(FLT_MAX);
52
mMax = Vec3::sReplicate(-FLT_MAX);
53
}
54
55
/// Check if the bounding box is valid (max >= min)
56
bool IsValid() const
57
{
58
return mMin.GetX() <= mMax.GetX() && mMin.GetY() <= mMax.GetY() && mMin.GetZ() <= mMax.GetZ();
59
}
60
61
/// Encapsulate point in bounding box
62
void Encapsulate(Vec3Arg inPos)
63
{
64
mMin = Vec3::sMin(mMin, inPos);
65
mMax = Vec3::sMax(mMax, inPos);
66
}
67
68
/// Encapsulate bounding box in bounding box
69
void Encapsulate(const AABox &inRHS)
70
{
71
mMin = Vec3::sMin(mMin, inRHS.mMin);
72
mMax = Vec3::sMax(mMax, inRHS.mMax);
73
}
74
75
/// Encapsulate triangle in bounding box
76
void Encapsulate(const Triangle &inRHS)
77
{
78
Vec3 v = Vec3::sLoadFloat3Unsafe(inRHS.mV[0]);
79
Encapsulate(v);
80
v = Vec3::sLoadFloat3Unsafe(inRHS.mV[1]);
81
Encapsulate(v);
82
v = Vec3::sLoadFloat3Unsafe(inRHS.mV[2]);
83
Encapsulate(v);
84
}
85
86
/// Encapsulate triangle in bounding box
87
void Encapsulate(const VertexList &inVertices, const IndexedTriangle &inTriangle)
88
{
89
for (uint32 idx : inTriangle.mIdx)
90
Encapsulate(Vec3(inVertices[idx]));
91
}
92
93
/// Intersect this bounding box with inOther, returns the intersection
94
AABox Intersect(const AABox &inOther) const
95
{
96
return AABox(Vec3::sMax(mMin, inOther.mMin), Vec3::sMin(mMax, inOther.mMax));
97
}
98
99
/// Make sure that each edge of the bounding box has a minimal length
100
void EnsureMinimalEdgeLength(float inMinEdgeLength)
101
{
102
Vec3 min_length = Vec3::sReplicate(inMinEdgeLength);
103
mMax = Vec3::sSelect(mMax, mMin + min_length, Vec3::sLess(mMax - mMin, min_length));
104
}
105
106
/// Widen the box on both sides by inVector
107
void ExpandBy(Vec3Arg inVector)
108
{
109
mMin -= inVector;
110
mMax += inVector;
111
}
112
113
/// Get center of bounding box
114
Vec3 GetCenter() const
115
{
116
return 0.5f * (mMin + mMax);
117
}
118
119
/// Get extent of bounding box (half of the size)
120
Vec3 GetExtent() const
121
{
122
return 0.5f * (mMax - mMin);
123
}
124
125
/// Get size of bounding box
126
Vec3 GetSize() const
127
{
128
return mMax - mMin;
129
}
130
131
/// Get surface area of bounding box
132
float GetSurfaceArea() const
133
{
134
Vec3 extent = mMax - mMin;
135
return 2.0f * (extent.GetX() * extent.GetY() + extent.GetX() * extent.GetZ() + extent.GetY() * extent.GetZ());
136
}
137
138
/// Get volume of bounding box
139
float GetVolume() const
140
{
141
Vec3 extent = mMax - mMin;
142
return extent.GetX() * extent.GetY() * extent.GetZ();
143
}
144
145
/// Check if this box contains another box
146
bool Contains(const AABox &inOther) const
147
{
148
return UVec4::sAnd(Vec3::sLessOrEqual(mMin, inOther.mMin), Vec3::sGreaterOrEqual(mMax, inOther.mMax)).TestAllXYZTrue();
149
}
150
151
/// Check if this box contains a point
152
bool Contains(Vec3Arg inOther) const
153
{
154
return UVec4::sAnd(Vec3::sLessOrEqual(mMin, inOther), Vec3::sGreaterOrEqual(mMax, inOther)).TestAllXYZTrue();
155
}
156
157
/// Check if this box contains a point
158
bool Contains(DVec3Arg inOther) const
159
{
160
return Contains(Vec3(inOther));
161
}
162
163
/// Check if this box overlaps with another box
164
bool Overlaps(const AABox &inOther) const
165
{
166
return !UVec4::sOr(Vec3::sGreater(mMin, inOther.mMax), Vec3::sLess(mMax, inOther.mMin)).TestAnyXYZTrue();
167
}
168
169
/// Check if this box overlaps with a plane
170
bool Overlaps(const Plane &inPlane) const
171
{
172
Vec3 normal = inPlane.GetNormal();
173
float dist_normal = inPlane.SignedDistance(GetSupport(normal));
174
float dist_min_normal = inPlane.SignedDistance(GetSupport(-normal));
175
return dist_normal * dist_min_normal <= 0.0f; // If both support points are on the same side of the plane we don't overlap
176
}
177
178
/// Translate bounding box
179
void Translate(Vec3Arg inTranslation)
180
{
181
mMin += inTranslation;
182
mMax += inTranslation;
183
}
184
185
/// Translate bounding box
186
void Translate(DVec3Arg inTranslation)
187
{
188
mMin = (DVec3(mMin) + inTranslation).ToVec3RoundDown();
189
mMax = (DVec3(mMax) + inTranslation).ToVec3RoundUp();
190
}
191
192
/// Transform bounding box
193
AABox Transformed(Mat44Arg inMatrix) const
194
{
195
// Start with the translation of the matrix
196
Vec3 new_min, new_max;
197
new_min = new_max = inMatrix.GetTranslation();
198
199
// Now find the extreme points by considering the product of the min and max with each column of inMatrix
200
for (int c = 0; c < 3; ++c)
201
{
202
Vec3 col = inMatrix.GetColumn3(c);
203
204
Vec3 a = col * mMin[c];
205
Vec3 b = col * mMax[c];
206
207
new_min += Vec3::sMin(a, b);
208
new_max += Vec3::sMax(a, b);
209
}
210
211
// Return the new bounding box
212
return AABox(new_min, new_max);
213
}
214
215
/// Transform bounding box
216
AABox Transformed(DMat44Arg inMatrix) const
217
{
218
AABox transformed = Transformed(inMatrix.GetRotation());
219
transformed.Translate(inMatrix.GetTranslation());
220
return transformed;
221
}
222
223
/// Scale this bounding box, can handle non-uniform and negative scaling
224
AABox Scaled(Vec3Arg inScale) const
225
{
226
return AABox::sFromTwoPoints(mMin * inScale, mMax * inScale);
227
}
228
229
/// Calculate the support vector for this convex shape.
230
Vec3 GetSupport(Vec3Arg inDirection) const
231
{
232
return Vec3::sSelect(mMax, mMin, Vec3::sLess(inDirection, Vec3::sZero()));
233
}
234
235
/// Get the vertices of the face that faces inDirection the most
236
template <class VERTEX_ARRAY>
237
void GetSupportingFace(Vec3Arg inDirection, VERTEX_ARRAY &outVertices) const
238
{
239
outVertices.resize(4);
240
241
int axis = inDirection.Abs().GetHighestComponentIndex();
242
if (inDirection[axis] < 0.0f)
243
{
244
switch (axis)
245
{
246
case 0:
247
outVertices[0] = Vec3(mMax.GetX(), mMin.GetY(), mMin.GetZ());
248
outVertices[1] = Vec3(mMax.GetX(), mMax.GetY(), mMin.GetZ());
249
outVertices[2] = Vec3(mMax.GetX(), mMax.GetY(), mMax.GetZ());
250
outVertices[3] = Vec3(mMax.GetX(), mMin.GetY(), mMax.GetZ());
251
break;
252
253
case 1:
254
outVertices[0] = Vec3(mMin.GetX(), mMax.GetY(), mMin.GetZ());
255
outVertices[1] = Vec3(mMin.GetX(), mMax.GetY(), mMax.GetZ());
256
outVertices[2] = Vec3(mMax.GetX(), mMax.GetY(), mMax.GetZ());
257
outVertices[3] = Vec3(mMax.GetX(), mMax.GetY(), mMin.GetZ());
258
break;
259
260
case 2:
261
outVertices[0] = Vec3(mMin.GetX(), mMin.GetY(), mMax.GetZ());
262
outVertices[1] = Vec3(mMax.GetX(), mMin.GetY(), mMax.GetZ());
263
outVertices[2] = Vec3(mMax.GetX(), mMax.GetY(), mMax.GetZ());
264
outVertices[3] = Vec3(mMin.GetX(), mMax.GetY(), mMax.GetZ());
265
break;
266
}
267
}
268
else
269
{
270
switch (axis)
271
{
272
case 0:
273
outVertices[0] = Vec3(mMin.GetX(), mMin.GetY(), mMin.GetZ());
274
outVertices[1] = Vec3(mMin.GetX(), mMin.GetY(), mMax.GetZ());
275
outVertices[2] = Vec3(mMin.GetX(), mMax.GetY(), mMax.GetZ());
276
outVertices[3] = Vec3(mMin.GetX(), mMax.GetY(), mMin.GetZ());
277
break;
278
279
case 1:
280
outVertices[0] = Vec3(mMin.GetX(), mMin.GetY(), mMin.GetZ());
281
outVertices[1] = Vec3(mMax.GetX(), mMin.GetY(), mMin.GetZ());
282
outVertices[2] = Vec3(mMax.GetX(), mMin.GetY(), mMax.GetZ());
283
outVertices[3] = Vec3(mMin.GetX(), mMin.GetY(), mMax.GetZ());
284
break;
285
286
case 2:
287
outVertices[0] = Vec3(mMin.GetX(), mMin.GetY(), mMin.GetZ());
288
outVertices[1] = Vec3(mMin.GetX(), mMax.GetY(), mMin.GetZ());
289
outVertices[2] = Vec3(mMax.GetX(), mMax.GetY(), mMin.GetZ());
290
outVertices[3] = Vec3(mMax.GetX(), mMin.GetY(), mMin.GetZ());
291
break;
292
}
293
}
294
}
295
296
/// Get the closest point on or in this box to inPoint
297
Vec3 GetClosestPoint(Vec3Arg inPoint) const
298
{
299
return Vec3::sMin(Vec3::sMax(inPoint, mMin), mMax);
300
}
301
302
/// Get the squared distance between inPoint and this box (will be 0 if in Point is inside the box)
303
inline float GetSqDistanceTo(Vec3Arg inPoint) const
304
{
305
return (GetClosestPoint(inPoint) - inPoint).LengthSq();
306
}
307
308
/// Bounding box min and max
309
Vec3 mMin;
310
Vec3 mMax;
311
};
312
313
JPH_NAMESPACE_END
314
315