AABB Collision Detection with Intersection Points (Incl. Rotation)

public struct Line {
	public Vector2 a;
	public Vector2 b;

	public Line(float x1, float y1, float x2, float y2) {
		a = new Vector2(x1, y1);
		b = new Vector2(x2, y2);
	}

	public void Rotate(float rad, Vector2 center) {
		Rotate(rad, ref a, center);
		Rotate(rad, ref b, center);
	}

	private void Rotate(float rad, ref Vector2 point, Vector2 center) {
		point = Vector2.Transform(point - center, Matrix.CreateRotationZ(rad)) + center;
	}

	public bool Intersect(Line line, out Vector2 ? intersectionPoint) {
		intersectionPoint = null;

		float a1 = b.Y - a.Y;
		float b1 = a.X - b.X;
		float c1 = a1 * a.X + b1 * a.Y;

		float a2 = line.b.Y - line.a.Y;
		float b2 = line.a.X - line.b.X;
		float c2 = a2 * line.a.X + b2 * line.a.Y;

		//If the lines are parallel, no collision possible.
		float det = a1 * b2 - a2 * b1;
		if (det == 0) return false;

		float x = (b2 * c1 - b1 * c2) / det;
		float y = (a1 * c2 - a2 * c1) / det;

		if (OnLine(this, x, y) && OnLine(line, x, y)) {
			intersectionPoint = new Vector2(x, y);
			return true;
		}

		return false;
	}

	public static bool OnLine(Line line, float x, float y) {
		return Math.Min(line.a.X, line.b.X) <= x && x <= Math.Max(line.a.X, line.b.X) && Math.Min(line.a.Y, line.b.Y) <= y && y <= Math.Max(line.a.Y, line.b.Y);
	}
}
public struct SRectangle {
	public Line left;
	public Line top;
	public Line right;
	public Line bottom;

	public void Rotate(float rad, Vector2 center) {
		left.Rotate(rad, center);
		top.Rotate(rad, center);
		right.Rotate(rad, center);
		bottom.Rotate(rad, center);
	}

	public static SRectangle FromRectangle(Rectangle rectangle, Vector2 origin, float rotation) {
		Line left = new Line(rectangle.X, rectangle.Y, rectangle.X, rectangle.Y + rectangle.Height);
		Line top = new Line(rectangle.X, rectangle.Y, rectangle.X + rectangle.Width, rectangle.Y);
		Line right = new Line(rectangle.X + rectangle.Width, rectangle.Y, rectangle.X + rectangle.Width, rectangle.Y + rectangle.Height);
		Line bottom = new Line(rectangle.X, rectangle.Y + rectangle.Height, rectangle.X + rectangle.Width, rectangle.Y + rectangle.Height);

		left.a.X -= origin.X;
		left.a.Y -= origin.Y;
		left.b.X -= origin.X;
		left.b.Y -= origin.Y;
		top.a.X -= origin.X;
		top.a.Y -= origin.Y;
		top.b.X -= origin.X;
		top.b.Y -= origin.Y;
		right.a.X -= origin.X;
		right.a.Y -= origin.Y;
		right.b.X -= origin.X;
		right.b.Y -= origin.Y;
		bottom.a.X -= origin.X;
		bottom.a.Y -= origin.Y;
		bottom.b.X -= origin.X;
		bottom.b.Y -= origin.Y;

		origin.X += rectangle.X - rectangle.Width / 2;
		origin.Y += rectangle.Y - rectangle.Height / 2;

		left.Rotate(rotation, origin);
		right.Rotate(rotation, origin);
		top.Rotate(rotation, origin);
		bottom.Rotate(rotation, origin);

		return new SRectangle() {
			left = left,
			right = right,
			top = top,
			bottom = bottom
		};
	}
}
public static bool AABB_AABB(SmartRectangle x, SmartRectangle y, out Vector2[] collisionPoints) {
	List < Vector2 > cp = new List < Vector2 > ();

	/* Left against y */
	if (x.left.Intersect(y.left, out Vector2 ? llcp)) cp.Add(llcp.Value);
	if (x.left.Intersect(y.top, out Vector2 ? ltcp)) cp.Add(ltcp.Value);
	if (x.left.Intersect(y.right, out Vector2 ? lrcp)) cp.Add(lrcp.Value);
	if (x.left.Intersect(y.bottom, out Vector2 ? lbcp)) cp.Add(lbcp.Value);
	/* Top against y */
	if (x.top.Intersect(y.left, out Vector2 ? tlcp)) cp.Add(tlcp.Value);
	if (x.top.Intersect(y.top, out Vector2 ? ttcp)) cp.Add(ttcp.Value);
	if (x.top.Intersect(y.right, out Vector2 ? trcp)) cp.Add(trcp.Value);
	if (x.top.Intersect(y.bottom, out Vector2 ? tbcp)) cp.Add(tbcp.Value);
	/* Right against y */
	if (x.right.Intersect(y.left, out Vector2 ? rlcp)) cp.Add(rlcp.Value);
	if (x.right.Intersect(y.top, out Vector2 ? rtcp)) cp.Add(rtcp.Value);
	if (x.right.Intersect(y.right, out Vector2 ? rrcp)) cp.Add(rrcp.Value);
	if (x.right.Intersect(y.bottom, out Vector2 ? rbcp)) cp.Add(rbcp.Value);
	/* Bottom against y */
	if (x.bottom.Intersect(y.left, out Vector2 ? blcp)) cp.Add(blcp.Value);
	if (x.bottom.Intersect(y.top, out Vector2 ? btcp)) cp.Add(btcp.Value);
	if (x.bottom.Intersect(y.right, out Vector2 ? brcp)) cp.Add(brcp.Value);
	if (x.bottom.Intersect(y.bottom, out Vector2 ? bbcp)) cp.Add(bbcp.Value);

	collisionPoints = cp.ToArray();
	return cp.Count > 0;
}

Hinterlasse einen Kommentar

Please Login to comment
  Subscribe  
Notify of