Implementing LineSegment2DvsRect
This commit is contained in:
@@ -17,6 +17,24 @@
|
||||
namespace CaveGame::Core
|
||||
{
|
||||
|
||||
/// Enumeration flags indicating cardinal direction to 8 degrees of freedom.
|
||||
enum Face : unsigned int
|
||||
{
|
||||
NORTH = 1,
|
||||
SOUTH = 2,
|
||||
EAST = 4,
|
||||
WEST = 8,
|
||||
TOP = NORTH,
|
||||
BOTTOM = SOUTH,
|
||||
LEFT = EAST,
|
||||
RIGHT = WEST,
|
||||
NORTHEAST = NORTH | EAST,
|
||||
NORTHWEST = NORTH | WEST,
|
||||
SOUTHEAST = SOUTH | EAST,
|
||||
SOUTHWEST = SOUTH | WEST
|
||||
};
|
||||
|
||||
/// A structure containing the results of a raycast test.
|
||||
struct RaycastHit
|
||||
{
|
||||
bool Hit;
|
||||
@@ -24,17 +42,6 @@ namespace CaveGame::Core
|
||||
Vector2 SurfaceNormal;
|
||||
};
|
||||
|
||||
enum Face
|
||||
{
|
||||
NORTH,
|
||||
SOUTH,
|
||||
EAST,
|
||||
WEST,
|
||||
TOP = NORTH,
|
||||
BOTTOM = SOUTH,
|
||||
LEFT = EAST,
|
||||
RIGHT = WEST,
|
||||
};
|
||||
|
||||
// TODO: Implement J3ML::Geometry::LineSegment2D
|
||||
// TODO: Implement J3ML::Geometry::Ray2D
|
||||
@@ -54,67 +61,30 @@ namespace CaveGame::Core
|
||||
{
|
||||
struct LineSegTestResult
|
||||
{
|
||||
bool intersects;
|
||||
Vector2 intersection;
|
||||
Face face;
|
||||
bool intersects;
|
||||
|
||||
};
|
||||
|
||||
static LineSegTestResult LineSegment2DvsAABB2D(Vector2 linesegA, Vector2 linesegB, Vector2 rectCenter, Vector2 rectSize);
|
||||
|
||||
static LineSegTestResult LineSegment2DvsAABB2D(LineSegment2D seg, AABB2D rect)
|
||||
{
|
||||
|
||||
}
|
||||
static LineSegTestResult LineSegment2DvsAABB2D(LineSegment2D seg, AABB2D rect);
|
||||
static LineSegTestResult LineSegment2Dvs(Vector2 a1, Vector2 a2, Vector2 b1, Vector2 b2);
|
||||
|
||||
static LineSegTestResult LineSegment2Dvs(LineSegment2D s1, LineSegment2D s2)
|
||||
{
|
||||
static LineSegTestResult LineSegment2Dvs(LineSegment2D s1, LineSegment2D s2);
|
||||
|
||||
}
|
||||
|
||||
static LineSegTestResult LineSegment2Dvs(Vector2 a1, Vector2 a2, Vector2 b1, Vector2 b2)
|
||||
{
|
||||
static bool AABB2Dvs(const Vector2& posA, const Vector2& sizeA, const Vector2& posB, const Vector2& sizeB);
|
||||
|
||||
}
|
||||
static bool AABB2Dvs(AABB2D a, AABB2D b);
|
||||
|
||||
static bool AABB2Dvs(AABB2D a, AABB2D b)
|
||||
{
|
||||
|
||||
}
|
||||
static Vector2 SolveAABB(const Vector2& posA, const Vector2& sizeA, const Vector2& posB, const Vector2& sizeB);
|
||||
|
||||
static bool AABBvs(const Vector2& posA, const Vector2& sizeA, const Vector2& posB, const Vector2& sizeB)
|
||||
{
|
||||
float absDistanceX = J3ML::Math::Abs(posA.x - posB.x);
|
||||
float absDistanceY = J3ML::Math::Abs(posA.y - posB.y);
|
||||
static Vector2 GetNormalForAABB(const Vector2& separation, const Vector2& velocity);
|
||||
|
||||
float sumWidth = sizeA.x + sizeB.x;
|
||||
float sumHeight = sizeA.y + sizeB.y;
|
||||
|
||||
if (absDistanceY >= sumHeight || absDistanceX >= sumWidth)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static Vector2 SolveAABB(AABB2D a, AABB2D b)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static Vector2 SolveAABB(const Vector2& posA, const Vector2& sizeA, const Vector2& posB, const Vector2& posB)
|
||||
{
|
||||
float distanceX =
|
||||
}
|
||||
|
||||
static Vector2 GetNormalForAABB(const Vector2& separation, const Vector2& velocity)
|
||||
{
|
||||
float d = J3ML::Math::Sqrt(separation.x * separation.x + separation.y * separation.y);
|
||||
|
||||
float nx = separation.x / d;
|
||||
float ny = separation.y / d;
|
||||
|
||||
float ps = velocity.x * nx + velocity.y * ny;
|
||||
|
||||
if (ps <= 0)
|
||||
return {nx, ny};
|
||||
return {0, 0};
|
||||
}
|
||||
static Vector2 SolveAABB(const AABB2D& a, const AABB2D& b);
|
||||
}
|
||||
}
|
@@ -1 +1,160 @@
|
||||
#include <Core/SimpleAABBSolver.hpp>
|
||||
#include <Core/SimpleAABBSolver.hpp>
|
||||
|
||||
CaveGame::Core::Solver::LineSegTestResult CaveGame::Core::Solver::LineSegment2DvsAABB2D(Vector2 linesegA,
|
||||
Vector2 linesegB, Vector2 rectCenter, Vector2 rectSize)
|
||||
{
|
||||
|
||||
LineSegment2D seg = LineSegment2D(linesegA, linesegB);
|
||||
AABB2D aabb = AABB2D(rectCenter-rectSize, rectCenter+rectSize);
|
||||
|
||||
return LineSegment2DvsAABB2D(seg, aabb);
|
||||
|
||||
}
|
||||
|
||||
CaveGame::Core::Solver::LineSegTestResult CaveGame::Core::Solver::LineSegment2DvsAABB2D(LineSegment2D seg, AABB2D rect)
|
||||
{
|
||||
Vector2 intersection = Vector2::Zero;
|
||||
Face collidingface = TOP;
|
||||
|
||||
Vector2 rect_top_left = rect.minPoint;
|
||||
Vector2 rect_bottom_right = rect.maxPoint;
|
||||
Vector2 rect_bottom_left = {rect.minPoint.x, rect.maxPoint.y};
|
||||
Vector2 rect_top_right = {rect.maxPoint.x, rect.minPoint.y};
|
||||
|
||||
LineSegment2D rect_top = {rect_top_left, rect_top_right};
|
||||
LineSegment2D rect_left = {rect_top_left, rect_bottom_left};
|
||||
LineSegment2D rect_bottom = {rect_bottom_left, rect_bottom_right};
|
||||
LineSegment2D rect_right = {rect_top_right, rect_bottom_right};
|
||||
|
||||
auto top_hits = LineSegment2Dvs(seg, rect_top);
|
||||
auto bottom_hits = LineSegment2Dvs(seg, rect_bottom);
|
||||
auto left_hits = LineSegment2Dvs(seg, rect_top);
|
||||
auto right_hits = LineSegment2Dvs(seg, rect_right);
|
||||
|
||||
if (top_hits.intersects || bottom_hits.intersects || right_hits.intersects || left_hits.intersects)
|
||||
{
|
||||
intersection = seg.B;
|
||||
|
||||
if (top_hits.intersects && seg.A.Distance(top_hits.intersection) < seg.A.Distance(intersection))
|
||||
{
|
||||
intersection = top_hits.intersection;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CaveGame::Core::Solver::LineSegTestResult CaveGame::Core::Solver::LineSegment2Dvs(Vector2 a1, Vector2 a2, Vector2 b1,
|
||||
Vector2 b2)
|
||||
{
|
||||
Vector2 intersection = Vector2::Zero;
|
||||
|
||||
Vector2 b = a2 - a1;
|
||||
Vector2 d = b2 - b1;
|
||||
float bDotDPerp = b.x * d.y - b.y * d.x;
|
||||
|
||||
// If b dot d == 0, it means that the lines are parallel, and have infinite intersection points.
|
||||
if (bDotDPerp == 0.f)
|
||||
return {false};
|
||||
|
||||
Vector2 c = b1 - a1;
|
||||
|
||||
float t = (c.x * d.y - c.y * d.x) / bDotDPerp;
|
||||
if (t < 0.f || t > 1.f)
|
||||
return {false};
|
||||
|
||||
float u = (c.x * b.y - c.y * b.x) / bDotDPerp;
|
||||
if (u < 0.f || u > 1.f)
|
||||
return {false};
|
||||
|
||||
return {true, a1+t*b};
|
||||
}
|
||||
|
||||
CaveGame::Core::Solver::LineSegTestResult CaveGame::Core::Solver::LineSegment2Dvs(LineSegment2D s1, LineSegment2D s2)
|
||||
{
|
||||
return LineSegment2Dvs(s1.A, s1.B, s2.A, s2.B);
|
||||
}
|
||||
|
||||
bool CaveGame::Core::Solver::AABB2Dvs(const Vector2& posA, const Vector2& sizeA, const Vector2& posB,
|
||||
const Vector2& sizeB)
|
||||
{
|
||||
float absDistanceX = J3ML::Math::Abs(posA.x - posB.x);
|
||||
float absDistanceY = J3ML::Math::Abs(posA.y - posB.y);
|
||||
|
||||
float sumWidth = sizeA.x + sizeB.x;
|
||||
float sumHeight = sizeA.y + sizeB.y;
|
||||
|
||||
if (absDistanceY >= sumHeight || absDistanceX >= sumWidth)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CaveGame::Core::Solver::AABB2Dvs(AABB2D a, AABB2D b)
|
||||
{
|
||||
Vector2 posA = a.minPoint + Vector2(a.Width()/2.f, a.Height()/2.f);
|
||||
|
||||
Vector2 posB = a.minPoint + Vector2(b.Width()/2.f, b.Height()/2.f);
|
||||
|
||||
Vector2 sizeA = Vector2{a.Width(), a.Height()} / 2.f;
|
||||
Vector2 sizeB = Vector2{b.Width(), b.Height()} / 2.f;
|
||||
return AABB2Dvs(posA, sizeA, posB, sizeB);
|
||||
}
|
||||
|
||||
Vector2 CaveGame::Core::Solver::SolveAABB(const Vector2& posA, const Vector2& sizeA, const Vector2& posB,
|
||||
const Vector2& sizeB)
|
||||
{
|
||||
float distanceX = posA.x - posB.x;
|
||||
float distanceY = posA.y - posB.y;
|
||||
|
||||
float absDistanceX = J3ML::Math::Abs(distanceX);
|
||||
float absDistanceY = J3ML::Math::Abs(distanceY);
|
||||
|
||||
float sumWidth = sizeA.x + sizeB.x;
|
||||
float sumHeight = sizeA.y + sizeB.y;
|
||||
|
||||
float sx = sumWidth - absDistanceX;
|
||||
float sy = sumHeight - absDistanceY;
|
||||
|
||||
if (sx > sy)
|
||||
{
|
||||
if (sy > 0)
|
||||
sx = 0;
|
||||
} else {
|
||||
if (sx > 0)
|
||||
sy = 0;
|
||||
}
|
||||
|
||||
if (distanceX < 0)
|
||||
{
|
||||
sx = -sx;
|
||||
}
|
||||
if (distanceY < 0)
|
||||
sy = -sy;
|
||||
|
||||
return {sx, sy};
|
||||
}
|
||||
|
||||
Vector2 CaveGame::Core::Solver::GetNormalForAABB(const Vector2& separation, const Vector2& velocity)
|
||||
{
|
||||
float d = J3ML::Math::Sqrt(separation.x * separation.x + separation.y * separation.y);
|
||||
|
||||
float nx = separation.x / d;
|
||||
float ny = separation.y / d;
|
||||
|
||||
float ps = velocity.x * nx + velocity.y * ny;
|
||||
|
||||
if (ps <= 0)
|
||||
return {nx, ny};
|
||||
return {0, 0};
|
||||
}
|
||||
|
||||
Vector2 CaveGame::Core::Solver::SolveAABB(const AABB2D& a, const AABB2D& b)
|
||||
{
|
||||
Vector2 posA = a.minPoint + Vector2(a.Width()/2.f, a.Height()/2.f);
|
||||
|
||||
Vector2 posB = a.minPoint + Vector2(b.Width()/2.f, b.Height()/2.f);
|
||||
|
||||
Vector2 sizeA = Vector2{a.Width(), a.Height()} / 2.f;
|
||||
Vector2 sizeB = Vector2{b.Width(), b.Height()} / 2.f;
|
||||
return SolveAABB(posA, sizeA, posB, sizeB);
|
||||
}
|
||||
|
Reference in New Issue
Block a user