public static bool TestPolygonVsPolygon(Polygon polygon1, Polygon polygon2, out ShapeCollision shapeCollision, bool flip = false) { if (!CheckPolygons(polygon1, polygon2, out ShapeCollision tmp1, flip) || !CheckPolygons(polygon2, polygon1, out ShapeCollision tmp2, flip)) { shapeCollision = new ShapeCollision(); return(false); } ShapeCollision result; ShapeCollision other; if (System.Math.Abs(tmp1.Overlap) < System.Math.Abs(tmp2.Overlap)) { result = tmp1; other = tmp2; } else { result = tmp2; other = tmp1; } result.OtherOverlap = other.Overlap; result.Separation = other.Separation; result.Normal = other.Normal; shapeCollision = result; return(true); } //testPolygonVsPolygon
public override void Draw(SpriteBatch spriteBatch, GameTime gameTime) { if (SelectedGameObjects.Count > 0) { foreach (var selectedGameObject in SelectedGameObjects) { if (SimulationGame.VisibleArea.Contains(selectedGameObject.Position)) { var worldDrawPosition = Rectangle.Empty; if (selectedGameObject is AmbientObject) { var gameObject = (AmbientObject)selectedGameObject; worldDrawPosition = new Rectangle((int)(gameObject.Position.X - gameObject.GetObjectType().SpriteOrigin.X), (int)(gameObject.Position.Y - gameObject.GetObjectType().SpriteOrigin.Y), gameObject.GetObjectType().SpriteBounds.X, gameObject.GetObjectType().SpriteBounds.Y); } else if (selectedGameObject is AmbientHitableObject) { var gameObject = (AmbientHitableObject)selectedGameObject; worldDrawPosition = new Rectangle((int)(gameObject.Position.X - gameObject.GetObjectType().SpriteOrigin.X), (int)(gameObject.Position.Y - gameObject.GetObjectType().SpriteOrigin.Y), gameObject.GetObjectType().SpriteBounds.X, gameObject.GetObjectType().SpriteBounds.Y); } else if (selectedGameObject is LivingEntity) { var gameObject = (LivingEntity)selectedGameObject; worldDrawPosition = new Rectangle((int)(gameObject.Position.X - gameObject.GetObjectType().SpriteOrigin.X), (int)(gameObject.Position.Y - gameObject.GetObjectType().SpriteOrigin.Y), gameObject.GetObjectType().SpriteBounds.X, gameObject.GetObjectType().SpriteBounds.Y); } var uiPosition = SimulationGame.ConvertWorldPositionToUIPosition(worldDrawPosition.X, worldDrawPosition.Y); SimulationGame.PrimitiveDrawer.Rectangle(new Rectangle((int)uiPosition.X, (int)uiPosition.Y, worldDrawPosition.Width, worldDrawPosition.Height), Color.Yellow); } } } else if (SelectedBlockType != null) { var uiPosition = SimulationGame.ConvertWorldPositionToUIPosition(SelectedBlockPosition.X * WorldGrid.BlockSize.X, SelectedBlockPosition.Y * WorldGrid.BlockSize.Y); SimulationGame.PrimitiveDrawer.Rectangle(new Rectangle((int)uiPosition.X, (int)uiPosition.Y, WorldGrid.BlockSize.X, WorldGrid.BlockSize.Y), Color.Blue); } else if (SelectedWorldLink != null) { var uiPosition = SimulationGame.ConvertWorldPositionToUIPosition(SelectedWorldLink.FromBlock.X * WorldGrid.BlockSize.X, SelectedWorldLink.FromBlock.Y * WorldGrid.BlockSize.Y); SimulationGame.PrimitiveDrawer.Rectangle(new Rectangle((int)uiPosition.X, (int)uiPosition.Y, WorldGrid.BlockSize.X, WorldGrid.BlockSize.Y), Color.Orange); } if (startDragPosition != null) { var _startDragPosition = startDragPosition ?? Point.Zero; var uiStartDragPosition = SimulationGame.ConvertWorldPositionToUIPosition(_startDragPosition.X, _startDragPosition.Y).ToPoint(); var selectionRect = ShapeCollision.ConvertLineToRect(uiStartDragPosition, SimulationGame.MouseState.Position); if (selectionRect.Width > 20 || selectionRect.Height > 20) { SimulationGame.PrimitiveDrawer.Rectangle(selectionRect.ToXnaRectangle(), Color.White); } } }
public ShapeCollision clone() { var clone = new ShapeCollision(); clone.copy_from(this); return(clone); }
private void handleOnMouseMove(MouseMoveEvent mouseMoveEvent) { if (mouseMoveEvent.LeftButtonDown && startDragPosition == null) { startDragPosition = SimulationGame.RealWorldMousePosition.ToPoint(); } if (mouseMoveEvent.LeftButtonDown == false && startDragPosition != null) { selectGameObjects(ShapeCollision.ConvertLineToRect(startDragPosition ?? Point.Zero, SimulationGame.RealWorldMousePosition.ToPoint())); startDragPosition = null; } }
public void copy_from(ShapeCollision other) { overlap = other.overlap; separationX = other.separationX; separationY = other.separationY; unitVectorX = other.unitVectorX; unitVectorY = other.unitVectorY; otherOverlap = other.otherOverlap; otherSeparationX = other.otherSeparationX; otherSeparationY = other.otherSeparationY; otherUnitVectorX = other.otherUnitVectorX; otherUnitVectorY = other.otherUnitVectorY; shape1 = other.shape1; shape2 = other.shape2; }
////////////////private static bool Intersect(Vector2[] polygon1, Vector2[] polygon2) ////////////////{ //////////////// var pointsA = polygon1; //////////////// var edgesA = BuildEdges(pointsA); //////////////// int edgeCountA = edgesA.Length; //////////////// var pointsB = polygon2; //////////////// var edgesB = BuildEdges(pointsB); //////////////// int edgeCountB = edgesB.Length; //////////////// Vector2 edge; //////////////// // Loop through all the edges of both polygons //////////////// for (int edgeIndex = 0; edgeIndex < edgeCountA + edgeCountB; edgeIndex++) //////////////// { //////////////// if (edgeIndex < edgeCountA) //////////////// { //////////////// edge = edgesA[edgeIndex]; //////////////// } //////////////// else //////////////// { //////////////// edge = edgesB[edgeIndex - edgeCountA]; //////////////// } //////////////// // ===== 1. Find if the polygons are currently intersecting ===== //////////////// // Find the axis perpendicular to the current edge //////////////// Vector2 axis = new Vector2(-edge.y, edge.x); //////////////// axis.Normalize(); //////////////// // Find the projection of the polygon on the current axis //////////////// float minA = 0; float minB = 0; float maxA = 0; float maxB = 0; //////////////// ProjectPolygon(axis, pointsA, ref minA, ref maxA); //////////////// ProjectPolygon(axis, pointsB, ref minB, ref maxB); //////////////// // Check if the polygon projections are currentlty intersecting //////////////// //if (IntervalDistance(minA, maxA, minB, maxB) <= 0.000001) return true; //////////////// if (Intersects(minA, maxA, minB, maxB, true)) //////////////// return true; //////////////// } //////////////// return false; ////////////////} ////////////////private static Vector2[] BuildEdges(Vector2[] points/*,Vector2 offset*/) ////////////////{ //////////////// Vector2 p1; //////////////// Vector2 p2; //////////////// List<Vector2> edges = new List<Vector2>(points.Length - 1); //////////////// for (int i = 0; i < points.Length; i++) //////////////// { //////////////// p1 = points[i]; //////////////// if (i + 1 >= points.Length) //////////////// { //////////////// p2 = points[0]; //////////////// } //////////////// else //////////////// { //////////////// p2 = points[i + 1]; //////////////// } //////////////// //edges.Add(offset+p2 - p1); //////////////// edges.Add(p2 - p1); //////////////// } //////////////// return edges.ToArray(); ////////////////} ////////////////// Calculate the distance between [minA, maxA] and [minB, maxB] ////////////////// The distance will be negative if the intervals overlap ////////////////private static float IntervalDistance(float minA, float maxA, float minB, float maxB) ////////////////{ //////////////// if (minA < minB) //////////////// { //////////////// return minB - maxA; //////////////// } //////////////// else //////////////// { //////////////// return minA - maxB; //////////////// } ////////////////} ////////////////public static bool Intersects(float min1, float max1, float min2, float max2, bool strict, bool correctMinMax = true) ////////////////{ //////////////// if (correctMinMax) //////////////// { //////////////// float tmp1 = min1, tmp2 = max1; //////////////// min1 = Math.Min(tmp1, tmp2); //////////////// max1 = Math.Max(tmp1, tmp2); //////////////// tmp1 = min2; //////////////// tmp2 = max2; //////////////// min2 = Math.Min(tmp1, tmp2); //////////////// max2 = Math.Max(tmp1, tmp2); //////////////// } //////////////// if (strict) //////////////// return (min1 <= min2 && max1 > min2) || (min2 <= min1 && max2 > min1); //////////////// else //////////////// return (min1 <= min2 && max1 >= min2) || (min2 <= min1 && max2 >= min1); ////////////////} ////////////////// Calculate the projection of a polygon on an axis and returns it as a [min, max] interval ////////////////private static void ProjectPolygon(Vector2 axis, Vector2[] polygon, ref float min, ref float max) ////////////////{ //////////////// // To project a point on an axis use the dot product //////////////// //float d = Vector2.Dot(axis, polygon[0]); //////////////// float d = DotProduct(axis, polygon[0]); //////////////// min = d; //////////////// max = d; //////////////// for (int i = 0; i < polygon.Length; i++) //////////////// { //////////////// d = DotProduct(polygon[i], axis); //////////////// if (d < min) //////////////// { //////////////// min = d; //////////////// } //////////////// else //////////////// { //////////////// if (d > max) //////////////// { //////////////// max = d; //////////////// } //////////////// } //////////////// } ////////////////} ////////////////public static float DotProduct(Vector2 vectorA, Vector2 vectorB) ////////////////{ //////////////// return vectorA.x * vectorB.x + vectorA.y * vectorB.y; ////////////////} private static bool Intersect(Vector2[] polygon1, Vector2[] polygon2) { var into = new ShapeCollision(); var flip = false; var tmp1 = checkPolygons(polygon1, polygon2, flip); var tmp2 = checkPolygons(polygon2, polygon1, !flip); if (tmp1 == null) { return(false); } if (tmp2 == null) { return(false); } ShapeCollision result = null; ShapeCollision other = null; if (System.Math.Abs(tmp1.overlap) < System.Math.Abs(tmp2.overlap)) { result = tmp1; other = tmp2; } else { result = tmp2; other = tmp1; } result.otherOverlap = other.overlap; result.otherSeparationX = other.separationX; result.otherSeparationY = other.separationY; result.otherUnitVectorX = other.unitVectorX; result.otherUnitVectorY = other.unitVectorY; into.copy_from(result); result = other = null; //return Math.Abs(into.otherOverlap) > 0.00001; return(true); }
/** Internal api - test a circle against a circle */ public static ShapeCollision testCircleVsCircle(Circle circleA, Circle circleB, bool flip = false) { var result = new ShapeCollision(); var circle1 = flip ? circleB : circleA; var circle2 = flip ? circleA : circleB; //add both radii together to get the colliding distance var totalRadius = circle1.transformedRadius + circle2.transformedRadius; //find the distance between the two circles using Pythagorean theorem. No square roots for optimization var distancesq = Util.vec_lengthsq(circle1.x - circle2.x, circle1.y - circle2.y); //if your distance is less than the totalRadius square(because distance is squared) if (distancesq < totalRadius * totalRadius) { //find the difference. Square roots are needed here. float difference = (float)(totalRadius - System.Math.Sqrt(distancesq)); result.shape1 = circle1; result.shape2 = circle2; var unitVecX = circle1.x - circle2.x; var unitVecY = circle1.y - circle2.y; var unitVecLen = Util.vec_length(unitVecX, unitVecY); unitVecX = Util.vec_normalize(unitVecLen, unitVecX); unitVecY = Util.vec_normalize(unitVecLen, unitVecY); result.unitVectorX = unitVecX; result.unitVectorY = unitVecY; //find the movement needed to separate the circles result.separationX = result.unitVectorX * difference; result.separationY = result.unitVectorY * difference; //the magnitude of the overlap result.overlap = Util.vec_length(result.separationX, result.separationY); return(result); } //if distancesq < r^2 return(null); }
public static ShapeCollision testPolygonVsPolygon(Polygon polygon1, Polygon polygon2, bool flip = false) { var output = new ShapeCollision(); if ((tmp1 = checkPolygons(polygon1, polygon2, flip)) == null) { return(null); } //i dont need collision data /* * if ( (tmp2 = checkPolygons(polygon2, polygon1, !flip)) == null) { * return null; * } * * ShapeCollision result = null; * ShapeCollision other = null; * * if (System.Math.Abs(tmp1.overlap) < System.Math.Abs(tmp2.overlap)) { * result = tmp1; * other = tmp2; * } else { * result = tmp2; * other = tmp1; * } * * result.otherOverlap = other.overlap; * result.otherSeparationX = other.separationX; * result.otherSeparationY = other.separationY; * result.otherUnitVectorX = other.unitVectorX; * result.otherUnitVectorY = other.unitVectorY; * * output.copy_from(result); * result = other = null; */ ShapeCollision result = tmp1; return(result); } //testPolygonVsPolygon
public static ShapeCollision testPolygonVsPolygon(Polygon polygon1, Polygon polygon2, bool flip = false) { var output = new ShapeCollision(); if ((tmp1 = checkPolygons(polygon1, polygon2, flip)) == null) { return(null); } if ((tmp2 = checkPolygons(polygon2, polygon1, !flip)) == null) { return(null); } ShapeCollision result = null; ShapeCollision other = null; if (System.Math.Abs(tmp1.overlap) < System.Math.Abs(tmp2.overlap)) { result = tmp1; other = tmp2; } else { result = tmp2; other = tmp1; } result.otherOverlap = other.overlap; result.otherSeparationX = other.separationX; result.otherSeparationY = other.separationY; result.otherUnitVectorX = other.unitVectorX; result.otherUnitVectorY = other.unitVectorY; output.copy_from(result); result = other = null; return(result); } //testPolygonVsPolygon
/** Internal api - test a circle against a circle */ public static bool TestCircleVsCircle(Circle circleA, Circle circleB, out ShapeCollision shapeCollision, bool flip = false) { shapeCollision = new ShapeCollision(); Circle circle1 = flip ? circleB : circleA; Circle circle2 = flip ? circleA : circleB; //add both radii together to get the colliding distance float totalRadius = circle1.TransformedRadius + circle2.TransformedRadius; //find the distance between the two circles using Pythagorean theorem. No square roots for optimization float distancesq = (circle1.Position - circle2.Position).LengthSquared(); //if your distance is less than the totalRadius square(because distance is squared) if (distancesq < totalRadius * totalRadius) { //find the difference. Square roots are needed here. float difference = (float)(totalRadius - System.Math.Sqrt(distancesq)); shapeCollision.Shape1 = circle1; shapeCollision.Shape2 = circle2; Vector2 normal = circle1.Position - circle2.Position; normal.Normalize(); shapeCollision.Normal = normal; //find the movement needed to separate the circles shapeCollision.Separation *= difference; //the magnitude of the overlap shapeCollision.Overlap = shapeCollision.Separation.Length(); return(true); } //if distancesq < r^2 return(false); }
public override bool CollidesWithCircle(Circle circle, out ShapeCollision shapeCollision, bool flip = false) => Sat2D.TestCircleVsCircle(this, circle, out shapeCollision, flip);
/** Internal api - test a circle against a polygon */ public static bool TestCircleVsPolygon(Circle circle, Polygon polygon, out ShapeCollision shapeCollision, bool flip = false) { shapeCollision = new ShapeCollision(); var verts = polygon.TransformedVertices; float testDistance = float.MaxValue; Vector2 closest = Vector2.Zero; for (int i = 0; i < verts.Count; i++) { float distance = (circle.Position - verts[i]).LengthSquared(); if (distance < testDistance) { testDistance = distance; closest = verts[i]; } } Vector2 normalAxis = closest - circle.Position; normalAxis.Normalize(); //project all its points, 0 outside the loop float test = 0.0f; float min1 = Vector2.Dot(normalAxis, verts[0]); float max1 = min1; for (int j = 1; j < verts.Count; j++) { test = Vector2.Dot(normalAxis, verts[j]); if (test < min1) { min1 = test; } if (test > max1) { max1 = test; } } // project the circle float max2 = circle.TransformedRadius; float min2 = -circle.TransformedRadius; float offset = Vector2.Dot(normalAxis, -circle.Position); min1 += offset; max1 += offset; float test1 = min1 - max2; float test2 = min2 - max1; //if either test is greater than 0, there is a gap, we can give up now. if (test1 > 0 || test2 > 0) { return(false); } // circle distance check float distMin = -(max2 - min1); if (flip) { distMin *= -1; } shapeCollision.Overlap = distMin; shapeCollision.Normal = normalAxis; float closestDist = System.Math.Abs(distMin); // find the normal axis for each point and project for (int i = 0; i < verts.Count; i++) { normalAxis = FindNormalAxis(verts, i); normalAxis.Normalize(); // project the polygon(again? yes, circles vs. polygon require more testing...) min1 = Vector2.Dot(normalAxis, verts[0]); max1 = min1; //set max and min //project all the other points(see, cirlces v. polygons use lots of this...) for (int j = 1; j < verts.Count; j++) { test = Vector2.Dot(normalAxis, verts[j]); if (test < min1) { min1 = test; } if (test > max1) { max1 = test; } } // project the circle(again) max2 = circle.TransformedRadius; //max is radius min2 = -circle.TransformedRadius; //min is negative radius //offset points offset = Vector2.Dot(normalAxis, -circle.Position); min1 += offset; max1 += offset; // do the test, again test1 = min1 - max2; test2 = min2 - max1; //failed.. quit now if (test1 > 0 || test2 > 0) { return(false); } distMin = -(max2 - min1); if (flip) { distMin *= -1; } if (System.Math.Abs(distMin) < closestDist) { shapeCollision.Normal = normalAxis; shapeCollision.Overlap = distMin; closestDist = System.Math.Abs(distMin); } } //for //if you made it here, there is a collision!!!!! if (flip) { shapeCollision.Shape1 = polygon; shapeCollision.Shape2 = circle; } else { shapeCollision.Shape1 = circle; shapeCollision.Shape2 = polygon; } shapeCollision.Separation *= shapeCollision.Overlap; if (!flip) { shapeCollision.Normal = -shapeCollision.Normal; } return(true); }
/** Internal api - implementation details for testPolygonVsPolygon */ public static ShapeCollision checkPolygons(Polygon polygon1, Polygon polygon2, bool flip = false) { var result = new ShapeCollision(); // TODO: This is unused, check original source var test1 = 0.0f; var test2 = 0.0f; var testNum = 0.0f; var min1 = 0.0f; var max1 = 0.0f; var min2 = 0.0f; var max2 = 0.0f; var closest = float.MaxValue; var axisX = 0.0f; var axisY = 0.0f; var verts1 = polygon1.transformedVertices; var verts2 = polygon2.transformedVertices; var count1 = verts1.Length; var count2 = verts2.Length; // loop to begin projection for (var i = 0; i < count1; i++) { axisX = findNormalAxisX(verts1, i); axisY = findNormalAxisY(verts1, i); var aLen = Util.vec_length(axisX, axisY); axisX = Util.vec_normalize(aLen, axisX); axisY = Util.vec_normalize(aLen, axisY); // project polygon1 min1 = Util.vec_dot(axisX, axisY, verts1[0].x, verts1[0].y); max1 = min1; for (var j = 1; j < count1; j++) { testNum = Util.vec_dot(axisX, axisY, verts1[j].x, verts1[j].y); if (testNum < min1) { min1 = testNum; } if (testNum > max1) { max1 = testNum; } } // project polygon2 min2 = Util.vec_dot(axisX, axisY, verts2[0].x, verts2[0].y); max2 = min2; for (var j = 1; j < count2; j++) { testNum = Util.vec_dot(axisX, axisY, verts2[j].x, verts2[j].y); if (testNum < min2) { min2 = testNum; } if (testNum > max2) { max2 = testNum; } } test1 = min1 - max2; test2 = min2 - max1; if (test1 > 0 || test2 > 0) { return(null); } var distMin = -(max2 - min1); if (flip) { distMin *= -1; } if (System.Math.Abs(distMin) < closest) { result.unitVectorX = axisX; result.unitVectorY = axisY; result.overlap = distMin; closest = System.Math.Abs(distMin); } break; } result.shape1 = flip ? polygon2 : polygon1; result.shape2 = flip ? polygon1 : polygon2; result.separationX = -result.unitVectorX * result.overlap; result.separationY = -result.unitVectorY * result.overlap; if (flip) { result.unitVectorX = -result.unitVectorX; result.unitVectorY = -result.unitVectorY; } return(result); }
/** Internal api - test a circle against a polygon */ public static ShapeCollision testCircleVsPolygon(Circle circle, Polygon polygon, bool flip = false) { var result = new ShapeCollision(); var verts = polygon.transformedVertices; var circleX = circle.x; var circleY = circle.y; float testDistance = float.MaxValue; var distance = 0.0f; var closestX = 0.0f; var closestY = 0.0f; for (var i = 0; i < verts.Length; i++) { distance = Util.vec_lengthsq(circleX - verts[i].x, circleY - verts[i].y); if (distance < testDistance) { testDistance = distance; closestX = verts[i].x; closestY = verts[i].y; } } var normalAxisX = closestX - circleX; var normalAxisY = closestY - circleY; var normAxisLen = Util.vec_length(normalAxisX, normalAxisY); normalAxisX = Util.vec_normalize(normAxisLen, normalAxisX); normalAxisY = Util.vec_normalize(normAxisLen, normalAxisY); //project all its points, 0 outside the loop var test = 0.0f; var min1 = Util.vec_dot(normalAxisX, normalAxisY, verts[0].x, verts[0].y); var max1 = min1; for (var j = 1; j < verts.Length; j++) { test = Util.vec_dot(normalAxisX, normalAxisY, verts[j].x, verts[j].y); if (test < min1) { min1 = test; } if (test > max1) { max1 = test; } } // project the circle var max2 = circle.transformedRadius; var min2 = -circle.transformedRadius; var offset = Util.vec_dot(normalAxisX, normalAxisY, -circleX, -circleY); min1 += offset; max1 += offset; var test1 = min1 - max2; var test2 = min2 - max1; //if either test is greater than 0, there is a gap, we can give up now. if (test1 > 0 || test2 > 0) { return(null); } // circle distance check var distMin = -(max2 - min1); if (flip) { distMin *= -1; } result.overlap = distMin; result.unitVectorX = normalAxisX; result.unitVectorY = normalAxisY; var closest = System.Math.Abs(distMin); // find the normal axis for each point and project for (var i = 0; i < verts.Length; i++) { normalAxisX = findNormalAxisX(verts, i); normalAxisY = findNormalAxisY(verts, i); var aLen = Util.vec_length(normalAxisX, normalAxisY); normalAxisX = Util.vec_normalize(aLen, normalAxisX); normalAxisY = Util.vec_normalize(aLen, normalAxisY); // project the polygon(again? yes, circles vs. polygon require more testing...) min1 = Util.vec_dot(normalAxisX, normalAxisY, verts[0].x, verts[0].y); max1 = min1; //set max and min //project all the other points(see, cirlces v. polygons use lots of this...) for (var j = 1; j < verts.Length; j++) { test = Util.vec_dot(normalAxisX, normalAxisY, verts[j].x, verts[j].y); if (test < min1) { min1 = test; } if (test > max1) { max1 = test; } } // project the circle(again) max2 = circle.transformedRadius; //max is radius min2 = -circle.transformedRadius; //min is negative radius //offset points offset = Util.vec_dot(normalAxisX, normalAxisY, -circleX, -circleY); min1 += offset; max1 += offset; // do the test, again test1 = min1 - max2; test2 = min2 - max1; //failed.. quit now if (test1 > 0 || test2 > 0) { return(null); } distMin = -(max2 - min1); if (flip) { distMin *= -1; } if (System.Math.Abs(distMin) < closest) { result.unitVectorX = normalAxisX; result.unitVectorY = normalAxisY; result.overlap = distMin; closest = System.Math.Abs(distMin); } } //for //if you made it here, there is a collision!!!!! if (flip) { result.shape1 = polygon; result.shape2 = circle; } else { result.shape1 = circle; result.shape2 = polygon; } result.separationX = result.unitVectorX * result.overlap; result.separationY = result.unitVectorY * result.overlap; if (!flip) { result.unitVectorX = -result.unitVectorX; result.unitVectorY = -result.unitVectorY; } return(result); }
public override bool CollidesWithPolygon(Polygon polygon, out ShapeCollision shapeCollision, bool flip = false) => Sat2D.TestCircleVsPolygon(this, polygon, out shapeCollision, flip);
private static ShapeCollision checkPolygons(Vector2[] polygon1, Vector2[] polygon2, bool flip = false) { var result = new ShapeCollision(); // TODO: This is unused, check original source var offset = 0.0f; var test1 = 0.0f; var test2 = 0.0f; var testNum = 0.0f; var min1 = 0.0f; var max1 = 0.0f; var min2 = 0.0f; var max2 = 0.0f; var closest = float.MaxValue; var axisX = 0.0f; var axisY = 0.0f; var verts1 = polygon1; var verts2 = polygon2; var founded = false; // loop to begin projection for (var i = 0; i < verts1.Length; i++) { axisX = findNormalAxisX(verts1, i); axisY = findNormalAxisY(verts1, i); var aLen = vec_length(axisX, axisY); axisX = vec_normalize(aLen, axisX); axisY = vec_normalize(aLen, axisY); // project polygon1 min1 = vec_dot(axisX, axisY, verts1[0].x, verts1[0].y); max1 = min1; for (var j = 1; i < verts1.Length; i++) { testNum = vec_dot(axisX, axisY, verts1[j].x, verts1[j].y); if (testNum < min1) { min1 = testNum; } if (testNum > max1) { max1 = testNum; } } // project polygon2 min2 = vec_dot(axisX, axisY, verts2[0].x, verts2[0].y); max2 = min2; for (var j = 1; i < verts2.Length; i++) { testNum = vec_dot(axisX, axisY, verts2[j].x, verts2[j].y); if (testNum < min2) { min2 = testNum; } if (testNum > max2) { max2 = testNum; } } test1 = min1 - max2; test2 = min2 - max1; if (test1 > 0 || test2 > 0) { return(null); } //if (test1 > 0 || test2 > 0) continue; //founded = true; var distMin = -(max2 - min1); if (flip) { distMin *= -1; } if (System.Math.Abs(distMin) < closest) { result.unitVectorX = axisX; result.unitVectorY = axisY; result.overlap = distMin; closest = System.Math.Abs(distMin); } } //if (!founded) // return null; result.shape1 = flip ? polygon2 : polygon1; result.shape2 = flip ? polygon1 : polygon2; result.separationX = -result.unitVectorX * result.overlap; result.separationY = -result.unitVectorY * result.overlap; if (flip) { result.unitVectorX = -result.unitVectorX; result.unitVectorY = -result.unitVectorY; } return(result); }
public override bool CollidesWith(Shape shape, out ShapeCollision shapeCollision) => shape.CollidesWithCircle(this, out shapeCollision, true);
public override bool CollidesWithCircle(Circle circle, out ShapeCollision shapeCollision, bool flip = false) => Sat2D.TestCircleVsPolygon(circle, this, out shapeCollision, !flip);