forked from MoonsideGames/MoonWorks
some more collision fast paths
parent
f8146b799a
commit
35ded250ed
|
@ -13,23 +13,41 @@ namespace MoonWorks.Collision
|
|||
|
||||
public static bool TestCollision(IShape2D shapeA, Transform2D transformA, IShape2D shapeB, Transform2D transformB)
|
||||
{
|
||||
if (shapeA is Rectangle rectangleA && shapeB is Rectangle rectangleB && transformA.Rotation == 0 && transformB.Rotation == 0)
|
||||
// If we can use a fast path check, let's do that!
|
||||
if (shapeA is Rectangle rectangleA && shapeB is Rectangle rectangleB && transformA.IsAxisAligned && transformB.IsAxisAligned)
|
||||
{
|
||||
return TestRectangleOverlap(rectangleA, transformA, rectangleB, transformB);
|
||||
}
|
||||
else if (shapeA is Point && shapeB is Rectangle && transformB.Rotation == 0)
|
||||
else if (shapeA is Point && shapeB is Rectangle && transformB.IsAxisAligned)
|
||||
{
|
||||
return TestPointRectangleOverlap((Point) shapeA, transformA, (Rectangle) shapeB, transformB);
|
||||
}
|
||||
else if (shapeA is Rectangle && shapeB is Point && transformA.Rotation == 0)
|
||||
else if (shapeA is Rectangle && shapeB is Point && transformA.IsAxisAligned)
|
||||
{
|
||||
return TestPointRectangleOverlap((Point) shapeB, transformB, (Rectangle) shapeA, transformA);
|
||||
}
|
||||
else if (shapeA is Circle circleA && shapeB is Circle circleB && transformA.Scale.X == transformA.Scale.Y && transformB.Scale.X == transformB.Scale.Y)
|
||||
else if (shapeA is Rectangle && shapeB is Circle && transformA.IsAxisAligned && transformB.IsUniformScale)
|
||||
{
|
||||
return TestCircleRectangleOverlap((Circle) shapeB, transformB, (Rectangle) shapeA, transformA);
|
||||
}
|
||||
else if (shapeA is Circle && shapeB is Rectangle && transformA.IsUniformScale && transformB.IsAxisAligned)
|
||||
{
|
||||
return TestCircleRectangleOverlap((Circle) shapeA, transformA, (Rectangle) shapeB, transformB);
|
||||
}
|
||||
else if (shapeA is Circle && shapeB is Point && transformA.IsUniformScale)
|
||||
{
|
||||
return TestCirclePointOverlap((Circle) shapeA, transformA, (Point) shapeB, transformB);
|
||||
}
|
||||
else if (shapeA is Point && shapeB is Circle && transformB.IsUniformScale)
|
||||
{
|
||||
return TestCirclePointOverlap((Circle) shapeB, transformB, (Point) shapeA, transformA);
|
||||
}
|
||||
else if (shapeA is Circle circleA && shapeB is Circle circleB && transformA.IsUniformScale && transformB.IsUniformScale)
|
||||
{
|
||||
return TestCircleOverlap(circleA, transformA, circleB, transformB);
|
||||
}
|
||||
|
||||
// Sad, we can't do a fast path optimization. Time for a simplex reduction.
|
||||
return FindCollisionSimplex(shapeA, transformA, shapeB, transformB).Item1;
|
||||
}
|
||||
|
||||
|
@ -49,6 +67,36 @@ namespace MoonWorks.Collision
|
|||
return transformedPoint.X > AABB.Left && transformedPoint.X < AABB.Right && transformedPoint.Y < AABB.Bottom && transformedPoint.Y > AABB.Top;
|
||||
}
|
||||
|
||||
public static bool TestCirclePointOverlap(Circle circle, Transform2D circleTransform, Point point, Transform2D pointTransform)
|
||||
{
|
||||
var circleCenter = circleTransform.Position;
|
||||
var circleRadius = circle.Radius * circleTransform.Scale.X;
|
||||
|
||||
var distanceX = circleCenter.X - pointTransform.Position.X;
|
||||
var distanceY = circleCenter.Y - pointTransform.Position.Y;
|
||||
|
||||
return (distanceX * distanceX) + (distanceY * distanceY) < (circleRadius * circleRadius);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// NOTE: The rectangle must be axis aligned, and the scaling of the circle must be uniform.
|
||||
/// </summary>
|
||||
public static bool TestCircleRectangleOverlap(Circle circle, Transform2D circleTransform, Rectangle rectangle, Transform2D rectangleTransform)
|
||||
{
|
||||
var circleCenter = circleTransform.Position;
|
||||
var circleRadius = circle.Radius * circleTransform.Scale.X;
|
||||
var AABB = rectangle.TransformedAABB(rectangleTransform);
|
||||
|
||||
var closestX = Math.MathHelper.Clamp(circleCenter.X, AABB.Left, AABB.Right);
|
||||
var closestY = Math.MathHelper.Clamp(circleCenter.Y, AABB.Top, AABB.Bottom);
|
||||
|
||||
var distanceX = circleCenter.X - closestX;
|
||||
var distanceY = circleCenter.Y - closestY;
|
||||
|
||||
var distanceSquared = (distanceX * distanceX) + (distanceY * distanceY);
|
||||
return distanceSquared < (circleRadius * circleRadius);
|
||||
}
|
||||
|
||||
public static bool TestCircleOverlap(Circle circleA, Transform2D transformA, Circle circleB, Transform2D transformB)
|
||||
{
|
||||
var radiusA = circleA.Radius * transformA.Scale.X;
|
||||
|
|
|
@ -8,6 +8,17 @@ namespace MoonWorks.Math
|
|||
|
||||
public Matrix3x2 TransformMatrix { get; }
|
||||
|
||||
public bool IsAxisAligned => Rotation % MathHelper.PiOver2 == 0;
|
||||
public bool IsUniformScale => Scale.X == Scale.Y;
|
||||
|
||||
public Transform2D()
|
||||
{
|
||||
Position = Vector2.Zero;
|
||||
Rotation = 0;
|
||||
Scale = Vector2.One;
|
||||
TransformMatrix = CreateTransformMatrix(Position, Rotation, Scale);
|
||||
}
|
||||
|
||||
public Transform2D(Vector2 position)
|
||||
{
|
||||
Position = position;
|
||||
|
|
Loading…
Reference in New Issue