public bool MinimumTranslationVectorWithContainment(Vector2[] vertices1, Vector2[] vertices2, out MinimumTranslationVector?mtv) { double overlap = Double.PositiveInfinity; Vector2 smallest = default(Vector2); Vector2[] axes1 = GetAxes(vertices1); Vector2[] axes2 = GetAxes(vertices2); bool MTVWC(Vector2[] axes) { for (int i = 0; i < axes.Length; i++) { Vector2 axis = axes[i]; Projection p1 = Project(vertices1, axis); Projection p2 = Project(vertices2, axis); if (!p1.Overlap(p2)) { return(false); } else { double o = p1.GetOverlap(p2); if (p1.Contains(p2) || p2.Contains(p1)) { double mins = Math.Abs(p1.Min - p2.Min); double maxs = Math.Abs(p1.Max - p2.Max); o += mins < maxs ? mins : maxs; } if (o < overlap) { overlap = o; smallest = axis; } } } return(true); } if (MTVWC(axes1) == false) { mtv = default(MinimumTranslationVector?); return(false); } if (MTVWC(axes2) == false) { mtv = default(MinimumTranslationVector?); return(false); } mtv = new MinimumTranslationVector(smallest, overlap); return(true); }
public bool MinimumTranslationVector(Vector2[] vertices1, Vector2[] vertices2, out MinimumTranslationVector?mtv) { double overlap = Double.PositiveInfinity; Vector2 smallest = default(Vector2); Vector2[] axes1 = GetAxes(vertices1); Vector2[] axes2 = GetAxes(vertices2); bool MTV(Vector2[] axes) { for (int i = 0; i < axes.Length; i++) { Vector2 axis = axes[i]; Projection p1 = Project(vertices1, axis); Projection p2 = Project(vertices2, axis); if (!p1.Overlap(p2)) { return(false); } else { double o = p1.GetOverlap(p2); if (o < overlap) { overlap = o; smallest = axis; } } } return(true); } if (MTV(axes1) == false) { mtv = default(MinimumTranslationVector?); return(false); } if (MTV(axes2) == false) { mtv = default(MinimumTranslationVector?); return(false); } mtv = new MinimumTranslationVector(smallest, overlap); return(true); }
private static bool OverlapsOnAxisOfShape(float[] verts1, int offset1, int count1, float[] verts2, int offset2, int count2, MinimumTranslationVector mtv, bool shapesShifted) { int endA = offset1 + count1; int endB = offset2 + count2; // get axis of polygon A for (int i = offset1; i < endA; i += 2) { float x1 = verts1[i]; float y1 = verts1[i + 1]; float x2 = verts1[(i + 2) % count1]; float y2 = verts1[(i + 3) % count1]; // Get the Axis for the 2 vertices float axisX = y1 - y2; float axisY = -(x1 - x2); float len = (float)Math.Sqrt(axisX * axisX + axisY * axisY); // We got a normalized Vector axisX /= len; axisY /= len; float minA = float.MaxValue; float maxA = -float.MaxValue; // project shape a on axis for (int v = offset1; v < endA; v += 2) { float p = verts1[v] * axisX + verts1[v + 1] * axisY; minA = Math.Min(minA, p); maxA = Math.Max(maxA, p); } float minB = float.MaxValue; float maxB = -float.MaxValue; // project shape b on axis for (int v = offset2; v < endB; v += 2) { float p = verts2[v] * axisX + verts2[v + 1] * axisY; minB = Math.Min(minB, p); maxB = Math.Max(maxB, p); } // There is a gap if (maxA < minB || maxB < minA) { return(false); } else { if (mtv != null) { float o = Math.Min(maxA, maxB) - Math.Max(minA, minB); bool aContainsB = minA <minB && maxA> maxB; bool bContainsA = minB <minA && maxB> maxA; // if it contains one or another float mins = 0; float maxs = 0; if (aContainsB || bContainsA) { mins = Math.Abs(minA - minB); maxs = Math.Abs(maxA - maxB); o += Math.Min(mins, maxs); } if (mtv.depth > o) { mtv.depth = o; bool condition; if (shapesShifted) { condition = minA < minB; axisX = condition ? axisX : -axisX; axisY = condition ? axisY : -axisY; } else { condition = minA > minB; axisX = condition ? axisX : -axisX; axisY = condition ? axisY : -axisY; } if (aContainsB || bContainsA) { condition = mins > maxs; axisX = condition ? axisX : -axisX; axisY = condition ? axisY : -axisY; } mtv.normal.X = axisX; mtv.normal.Y = axisY; } } } } return(true); }
/// <summary> /// Check whether polygons defined by the given vertex arrays overlap (clockwise or counter-clockwise wound doesn't matter). If /// they do, optionally obtain a Minimum Translation Vector indicating the minimum magnitude vector required to push the polygon /// defined by verts1 out of the collision with the polygon defined by verts2. /// </summary> /// <param name="verts1">Vertices of the first polygon.</param> /// <param name="offset1">the offset of the verts1 array</param> /// <param name="count1">the amount that is added to the offset1</param> /// <param name="verts2">Vertices of the second polygon.</param> /// <param name="offset2">the offset of the verts2 array</param> /// <param name="count2">the amount that is added to the offset2</param> /// <param name="mtv">A Minimum Translation Vector to fill in the case of a collision, or null (optional).</param> /// <returns>Whether polygons overlap.</returns> public static bool OverlapConvexPolygons(float[] verts1, int offset1, int count1, float[] verts2, int offset2, int count2, MinimumTranslationVector mtv) { bool overlaps; if (mtv != null) { mtv.depth = float.MaxValue; mtv.normal.X = 0; mtv.normal.Y = 0; } overlaps = OverlapsOnAxisOfShape(verts2, offset2, count2, verts1, offset1, count1, mtv, true); if (overlaps) { overlaps = OverlapsOnAxisOfShape(verts1, offset1, count1, verts2, offset2, count2, mtv, false); } if (!overlaps) { if (mtv != null) { mtv.depth = 0; mtv.normal.X = 0; mtv.normal.Y = 0; } return(false); } return(true); }
/// <remarks>@see#overlapConvexPolygons(float[], int, int, float[], int, int, MinimumTranslationVector)</remarks> public static bool OverlapConvexPolygons(float[] verts1, float[] verts2, MinimumTranslationVector mtv) { return(OverlapConvexPolygons(verts1, 0, verts1.Length, verts2, 0, verts2.Length, mtv)); }
/// <summary> /// Check whether convex polygons overlap (clockwise or counter-clockwise wound doesn't matter). If they do, optionally obtain /// a Minimum Translation Vector indicating the minimum magnitude vector required to push the polygon p1 out of collision with /// polygon p2. /// </summary> /// <param name="p1">The first polygon.</param> /// <param name="p2">The second polygon.</param> /// <param name="mtv">A Minimum Translation Vector to fill in the case of a collision, or null (optional).</param> /// <returns>Whether polygons overlap.</returns> public static bool OverlapConvexPolygons(Polygon p1, Polygon p2, MinimumTranslationVector mtv) { return(OverlapConvexPolygons(p1.GetTransformedVertices(), p2.GetTransformedVertices(), mtv)); }