diff --git a/src/GameUtils/Types/Geometry/AABB.cs b/src/GameUtils/Types/Geometry/AABB.cs index 93615f3..36de442 100644 --- a/src/GameUtils/Types/Geometry/AABB.cs +++ b/src/GameUtils/Types/Geometry/AABB.cs @@ -148,6 +148,8 @@ public bool Intersects(Line line, out Vector2[] intersectionPoints) #pragma warning disable S3267 // LINQ would reintroduce allocations on a hot collision path public bool Intersects(Polygon2D polygon) { + if (!Intersects(polygon.BoundingBox)) return false; + // 1. Fast bounds check: compute polygon bounds on the fly if (polygon.Vertices.Length > 0) { diff --git a/src/GameUtils/Types/Geometry/Circle.cs b/src/GameUtils/Types/Geometry/Circle.cs index adaefe7..4862f5a 100644 --- a/src/GameUtils/Types/Geometry/Circle.cs +++ b/src/GameUtils/Types/Geometry/Circle.cs @@ -63,6 +63,8 @@ public bool Intersects(Line line) #pragma warning disable S3267 // LINQ would reintroduce allocations on a hot collision path public bool Intersects(Polygon2D polygon) { + if (!Intersects(polygon.BoundingBox)) return false; + foreach (var v in polygon.Vertices) { if (Contains(v)) return true; diff --git a/src/GameUtils/Types/Geometry/Polygon2D.cs b/src/GameUtils/Types/Geometry/Polygon2D.cs index c0cca8c..bf54300 100644 --- a/src/GameUtils/Types/Geometry/Polygon2D.cs +++ b/src/GameUtils/Types/Geometry/Polygon2D.cs @@ -24,8 +24,15 @@ public readonly struct Polygon2D /// Normals of each edge of the polygon /// public readonly Vector2[] Normals; + + private readonly AABB[] _boundingBox; #pragma warning restore S3887 + /// + /// The axis-aligned bounding box of the polygon + /// + public AABB BoundingBox => _boundingBox[0]; + /// /// Creates a new polygon from the specified vertices. If is true, the vertices will be sorted clockwise before creating the polygon. /// @@ -42,11 +49,18 @@ public Polygon2D(Vector2[] vertices, bool sort = true) Edges = new Line[Vertices.Length]; Normals = new Vector2[Vertices.Length]; + var min = new Vector2(float.MaxValue); + var max = new Vector2(float.MinValue); + for (var i = 0; i < Vertices.Length; i++) { Edges[i] = new Line(Vertices[i], Vertices[(i + 1) % Vertices.Length]); Normals[i] = Vector2.Normalize(new Vector2(Edges[i].End.Y - Edges[i].Start.Y, Edges[i].Start.X - Edges[i].End.X)); + min = Vector2.Min(min, Vertices[i]); + max = Vector2.Max(max, Vertices[i]); } + + _boundingBox = [new AABB(min, max)]; } private static Vector2[] SortClockwise(Vector2[] vertices) @@ -79,10 +93,23 @@ public bool Contains(Vector2 point) /// public void TranslateBy(Vector2 translation) { + var min = new Vector2(float.MaxValue); + var max = new Vector2(float.MinValue); + for (var i = 0; i < Vertices.Length; i++) { Vertices[i] += translation; + + min = Vector2.Min(min, Vertices[i]); + max = Vector2.Max(max, Vertices[i]); } + + for (var i = 0; i < Vertices.Length; i++) + { + Edges[i] = new Line(Vertices[i], Vertices[(i + 1) % Vertices.Length]); + } + + _boundingBox[0] = new AABB(min, max); } ///