|
|
|
@@ -276,4 +276,145 @@ namespace J3ML::Geometry {
|
|
|
|
|
|
|
|
|
|
AABB::AABB() : Shape() {}
|
|
|
|
|
|
|
|
|
|
float Max(float a, float b)
|
|
|
|
|
{
|
|
|
|
|
return std::max(a, b);
|
|
|
|
|
}
|
|
|
|
|
float Max(float a, float b, float c)
|
|
|
|
|
{
|
|
|
|
|
return std::max(a, std::max(b, c));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float Min(float a, float b, float c)
|
|
|
|
|
{
|
|
|
|
|
return std::min(a, std::min(b, c));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Compute the face normals of the AABB, because the AABB is at center
|
|
|
|
|
// and (of course) axis aligned, we know it's normals are the X,Y,Z axes.
|
|
|
|
|
Vector3 u0 = Vector3(1.f, 0.f, 0.f);
|
|
|
|
|
Vector3 u1 = Vector3(0.f, 1.f, 0.f);
|
|
|
|
|
Vector3 u2 = Vector3(0.f, 0.f, 1.f);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool AABB::TestAxis(Vector3 axis, Vector3 v0, Vector3 v1, Vector3 v2) const
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
Vector3 e = this->Size();
|
|
|
|
|
|
|
|
|
|
// Testing axis: axis_u0_f0
|
|
|
|
|
// Project all 3 vertices of the triangle onto the Separating axis
|
|
|
|
|
float p0 = Vector3::Dot(v0, axis);
|
|
|
|
|
float p1 = Vector3::Dot(v1, axis);
|
|
|
|
|
float p2 = Vector3::Dot(v2, axis);
|
|
|
|
|
|
|
|
|
|
// Project the AABB onto the separating axis
|
|
|
|
|
// We don't care about the end points of the projection
|
|
|
|
|
// just the length of the half-size of the AABB
|
|
|
|
|
// that is, we're only casting the extents onto the
|
|
|
|
|
// separating axis, not the AABB center. We don't
|
|
|
|
|
// need to cast the center, because we know that the
|
|
|
|
|
// AABB is at origin compared to the triangle!
|
|
|
|
|
float r = e.x * std::abs(Vector3::Dot(u0, axis)) +
|
|
|
|
|
e.y * std::abs(Vector3::Dot(u1, axis)) +
|
|
|
|
|
e.z * std::abs(Vector3::Dot(u2, axis));
|
|
|
|
|
|
|
|
|
|
// Now do the actual test, basically see if either of
|
|
|
|
|
// the most extreme of the triangle points intersects r
|
|
|
|
|
// You might need to write Min & Max functions that take 3 arguments
|
|
|
|
|
if (Max(Max(p0, p1, p2), Min(p0, p1, p2)) > r)
|
|
|
|
|
{
|
|
|
|
|
// This means BOTH of the points of the projected triangle
|
|
|
|
|
// are outside the projected half-length of the AABB
|
|
|
|
|
// Therefore the axis is separating and we can exit
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool AABB::Intersects(const Triangle &triangle) const {
|
|
|
|
|
|
|
|
|
|
// https://gdbooks.gitbooks.io/3dcollisions/content/Chapter4/aabb-triangle.html
|
|
|
|
|
|
|
|
|
|
Vector3 v0 = triangle.V0;
|
|
|
|
|
Vector3 v1 = triangle.V1;
|
|
|
|
|
Vector3 v2 = triangle.V2;
|
|
|
|
|
|
|
|
|
|
// Convert AABB to center-extentss form
|
|
|
|
|
Vector3 c = this->Centroid();
|
|
|
|
|
Vector3 e = this->Size();
|
|
|
|
|
|
|
|
|
|
// Translate the triangle as conceptually moving the AABB to origin
|
|
|
|
|
// This is the same as we did with the point in triangle test
|
|
|
|
|
v0 -= c;
|
|
|
|
|
v1 -= c;
|
|
|
|
|
v2 -= c;
|
|
|
|
|
|
|
|
|
|
// Compute the edge vectors of the triangle
|
|
|
|
|
// That is , get the lines between the points as vectors
|
|
|
|
|
Vector3 f0 = v1 - v0; // B - A
|
|
|
|
|
Vector3 f1 = v2 - v1; // C - B
|
|
|
|
|
Vector3 f2 = v0 - v2; // A - C
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// There are a total of 13 axes to test!!!
|
|
|
|
|
// We first test against 9 axis, these axes are given by cross product combinations
|
|
|
|
|
// of the edges of the triangle and the edges of the AABB. You need to get an axis testing each of the 3 sides
|
|
|
|
|
// of the AABB against each of the 3 sides of the triangle. The result is 9 axes of separation.
|
|
|
|
|
|
|
|
|
|
// Compute the 9 axes
|
|
|
|
|
Vector3 axis_u0_f0 = Vector3::Cross(u0, f0);
|
|
|
|
|
Vector3 axis_u0_f1 = Vector3::Cross(u0, f1);
|
|
|
|
|
Vector3 axis_u0_f2 = Vector3::Cross(u0, f2);
|
|
|
|
|
|
|
|
|
|
Vector3 axis_u1_f0 = Vector3::Cross(u1, f0);
|
|
|
|
|
Vector3 axis_u1_f1 = Vector3::Cross(u1, f1);
|
|
|
|
|
Vector3 axis_u1_f2 = Vector3::Cross(u1, f2);
|
|
|
|
|
|
|
|
|
|
Vector3 axis_u2_f0 = Vector3::Cross(u1, f0);
|
|
|
|
|
Vector3 axis_u2_f1 = Vector3::Cross(u1, f1);
|
|
|
|
|
Vector3 axis_u2_f2 = Vector3::Cross(u1, f2);
|
|
|
|
|
|
|
|
|
|
if (TestAxis(axis_u0_f0, u0, u1, u2))
|
|
|
|
|
return true;
|
|
|
|
|
if (TestAxis(axis_u0_f1, u0, u1, u2))
|
|
|
|
|
return true;
|
|
|
|
|
if (TestAxis(axis_u0_f2, u0, u1, u2))
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
if (TestAxis(axis_u1_f0, u0, u1, u2))
|
|
|
|
|
return true;
|
|
|
|
|
if (TestAxis(axis_u1_f1, u0, u1, u2))
|
|
|
|
|
return true;
|
|
|
|
|
if (TestAxis(axis_u1_f2, u0, u1, u2))
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
if (TestAxis(axis_u2_f0, u0, u1, u2))
|
|
|
|
|
return true;
|
|
|
|
|
if (TestAxis(axis_u2_f1, u0, u1, u2))
|
|
|
|
|
return true;
|
|
|
|
|
if (TestAxis(axis_u2_f2, u0, u1, u2))
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Next we have 3 face normals from the AABB
|
|
|
|
|
// for these tests we are conceptually checking if the bounding box
|
|
|
|
|
// of the triangle intersects the bounding box of the AABB
|
|
|
|
|
// that is to say, the separating axis for all tests are axis aligned:
|
|
|
|
|
// axis1: (1, 0, 0), axis2: (0, 1, 0), axis3: (0, 0, 1)
|
|
|
|
|
|
|
|
|
|
// Do the SAT given the 3 primary axes of the AABB
|
|
|
|
|
// You already have two vectors for this: u0, u1, and u2
|
|
|
|
|
|
|
|
|
|
// Finally we have one last axis to test, the face normal of the triangle
|
|
|
|
|
// We can get the normal of the triangle by crossing the first two line segments
|
|
|
|
|
Vector3 triangleNormal = Vector3::Cross(f0, f1);
|
|
|
|
|
// TODO: SAT Test
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Passed testing for all 13 separating axes that exist
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|