Skip to content

Instantly share code, notes, and snippets.

@prime31
Forked from anonymous/gist:8bb64b0556fecd13769f
Created December 10, 2015 18:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save prime31/ab89f2d0b759dc11a315 to your computer and use it in GitHub Desktop.
Save prime31/ab89f2d0b759dc11a315 to your computer and use it in GitHub Desktop.
Swept AABB Collisions C#
public static bool TestAABBSweep(Vector2 extents1, Vector2 centre1, Vector2 velocity1, Vector2 extents2, Vector2 centre2, Vector2 velocity2, out float t0, out float t1)
{
var aabb1 = new AABB(centre1, extents1);
var aabb2 = new AABB(centre2, extents2);
//Check if the boxes are currently overlapping
if (aabb1.Overlaps(aabb2))
{
t0 = t1 = 0;
return true;
}
//The problem is solved in A's frame of reference so get relative velocity (in normalized time)
var relativeVelocity = velocity2 - velocity1;
//First and last time of overlap along each axis
var firstOverlapTime = new Vector2(float.MinValue);
var lastOverlapTime = new Vector2(float.MaxValue);
var overlapX = false;
var overlapY = false;
//Find the first possible times of overlap...
if (relativeVelocity.X < 0)
{
if (aabb1.MinX < aabb2.MaxX)
{
overlapX = true;
firstOverlapTime.X = (aabb1.MaxX - aabb2.MinX) / relativeVelocity.X;
}
}
else if (relativeVelocity.X > 0)
{
if (aabb2.MinX < aabb1.MaxX)
{
overlapX = true;
firstOverlapTime.X = (aabb1.MinX - aabb2.MaxX) / relativeVelocity.X;
}
}
else if (aabb1.MinX <= aabb2.MaxX && aabb1.MaxX >= aabb2.MinX)
{
overlapX = true;
firstOverlapTime.X = 0.0f;
lastOverlapTime.X = 1.0f;
}
if (relativeVelocity.Y < 0)
{
if (aabb1.MinY < aabb2.MaxY)
{
overlapY = true;
firstOverlapTime.Y = (aabb1.MaxY - aabb2.MinY) / relativeVelocity.Y;
}
}
else if (relativeVelocity.Y > 0)
{
if (aabb2.MinY < aabb1.MaxY)
{
overlapY = true;
firstOverlapTime.Y = (aabb1.MinY - aabb2.MaxY) / relativeVelocity.Y;
}
}
else if (aabb1.MinY <= aabb2.MaxY && aabb1.MaxY >= aabb2.MinY)
{
overlapY = true;
firstOverlapTime.Y = 0.0f;
lastOverlapTime.Y = 1.0f;
}
//...and the last possible time of overlap
if (aabb2.MaxX > aabb1.MinX && relativeVelocity.X < 0)
lastOverlapTime.X = (aabb1.MinX - aabb2.MaxX) / relativeVelocity.X;
else if (aabb1.MaxX > aabb2.MinX && relativeVelocity.X > 0)
lastOverlapTime.X = (aabb1.MaxX - aabb2.MinX) / relativeVelocity.X;
if (aabb2.MaxY > aabb1.MinY && relativeVelocity.Y < 0)
lastOverlapTime.Y = (aabb1.MinY - aabb2.MaxY) / relativeVelocity.Y;
else if (aabb1.MaxY > aabb2.MinY && relativeVelocity.Y > 0)
lastOverlapTime.Y = (aabb1.MaxY - aabb2.MinY) / relativeVelocity.Y;
if (overlapX == false || overlapY == false)
{
t0 = t1 = 0;
return false;
}
//Possible first time of overlap is the largest of the axis values
t0 = Math.Max(firstOverlapTime.X, firstOverlapTime.Y);
//So then the possible last time of overlap is the smallest of the overlaps values
t1 = Math.Min(lastOverlapTime.X, lastOverlapTime.Y);
//They could have only collided if the first time of overlap occurred before the last time of overlap
return t0 >= 0 && t0 <= 1 && t0 <= t1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment