Add AABBvAABB interesection & add AABB scale

This commit is contained in:
Mishura
2024-05-07 14:55:09 -04:00
parent 35e1309d6f
commit 82cb3d7ee3
2 changed files with 68 additions and 2 deletions

View File

@@ -1,5 +1,7 @@
#pragma once
#include <optional>
#include <J3ML/LinearAlgebra.h>
#include <J3ML/Geometry/Common.h>
#include <J3ML/Geometry/Shape.h>
@@ -179,6 +181,8 @@ namespace J3ML::Geometry
void Translate(const Vector3& offset);
AABB Translated(const Vector3& offset) const;
void Scale(const Vector3& scale);
AABB Scaled(const Vector3& scale) const;
AABB TransformAABB(const Matrix3x3& transform);
AABB TransformAABB(const Matrix4x4& transform);
AABB TransformAABB(const Quaternion& transform);
@@ -230,6 +234,7 @@ namespace J3ML::Geometry
bool Intersects(const Polygon& polygon) const;
bool Intersects(const Frustum& frustum) const;
bool Intersects(const Polyhedron& polyhedron) const;
bool Intersects(const AABB& aabb) const;
/** For reference documentation on the Sphere-AABB intersection test, see Christer Ericson's Real-Time Collision Detection, p. 165. [groupSyntax]
@param sphere The first parameter of this function specifies the other object to test against.
@@ -270,9 +275,9 @@ namespace J3ML::Geometry
}
/// Finds the set intersection of this and the given AABB.
/** @return This function returns the AABB that is contained in both this and the given AABB.
/** @return This function returns an intersection that is contained in both this and the given AABB if there is one.
@todo Add Intersection(OBB/Polyhedron). */
AABB Intersection(const AABB& rhs) const;
std::optional<AABB> Intersection(const AABB& rhs) const;
/// Sets this AABB to enclose the given set of points.

View File

@@ -454,6 +454,51 @@ namespace J3ML::Geometry {
#endif
}
bool AABB::Intersects(const AABB& aabb) const {
return Intersection(aabb).has_value();
}
std::optional<AABB> AABB::Intersection(const AABB& rhs) const {
// Here we do SAT, except that due to both objects being AABBs, they are "already projected" onto the same axis
constexpr auto test = [](float a, float b, float c, float d) -> std::optional<Vector2> {
// Overlap Test
// Points go:
// +-------------+
// +-----|-----+ |
// | 1 | | 2 |
// | +-----|-------+
// +-----------+
//
// A-----C-----B-------D
//
// IF A < C AND B > C ( Overlap in order object 1 -> object 2)
// IF C < A AND D > A ( Overlap in order object 2 -> object 1)
if (a < c && b > c) {
return Vector2{c, b};
}
if (c < a && d > a) {
return Vector2{a, d};
}
return std::nullopt;
};
// This is SAT, so we need all axes to collide
std::optional<Vector2> xCollision = test(MinX(), MaxX(), rhs.MinX(), rhs.MaxX());
if (!xCollision.has_value()) return std::nullopt;
std::optional<Vector2> yCollision = test(MinY(), MaxY(), rhs.MinY(), rhs.MaxY());
if (!yCollision.has_value()) return std::nullopt;
std::optional<Vector2> zCollision = test(MinZ(), MaxZ(), rhs.MinZ(), rhs.MaxZ());
if (!zCollision.has_value()) return std::nullopt;
// At this point all 3 optionals have a value ; x of each is the "min" value, y of each is the "max" value
return AABB{
Vector3{xCollision->x, yCollision->x, zCollision->x},
Vector3{xCollision->y, yCollision->y, zCollision->y}
};
}
bool AABB::IntersectLineAABB_CPP(const Vector3 &linePos, const Vector3 &lineDir, float &tNear, float &tFar) const
{
assert(lineDir.IsNormalized());
@@ -552,6 +597,22 @@ namespace J3ML::Geometry {
return AABB(minPoint+offset, maxPoint+offset);
}
void AABB::Scale(const Vector3 &scale) {
minPoint.x *= scale.x;
minPoint.y *= scale.y;
minPoint.z *= scale.z;
maxPoint.x *= scale.x;
maxPoint.y *= scale.y;
maxPoint.z *= scale.z;
}
AABB AABB::Scaled(const Vector3 &scale) const {
return AABB(
Vector3(minPoint.x*scale.y, minPoint.y*scale.y, minPoint.z*scale.z),
Vector3(maxPoint.x*scale.y, maxPoint.y*scale.y, maxPoint.z*scale.z)
);
}
AABB AABB::TransformAABB(const Matrix3x3 &transform) {
// TODO: assert(transform.IsColOrthogonal());
// TODO: assert(transform.HasUniformScale());