/// <summary> /// Given a CircleEntity and the vertices and position of a 2D Polygon, checks if the circle and the polygon are overlapping /// </summary> /// <param name="circle"> The circle entity in question </param> /// <param name="polyPosition"> The position of the polygon in question </param> /// <param name="poly"> The world space position of the vertices of the polygon </param> /// <param name="localPoly"> The local space position of the vertices of the polygon </param> /// <returns></returns> public static bool DetectCollision(CircleEntity circle, Vector polyPosition, Vector[] poly, Vector[] localPoly) { Vector relativeCirclePos = circle.position - polyPosition; float seperation = -10000; int face = -1234; //Console.WriteLine("MOVEMNT TICK"); for (int i = 0; i < poly.Length; i++) { //get the normal Vector normal = poly[i].GetNormal().Normalized(); Vector circleToPoint = relativeCirclePos - localPoly[i]; //dot the normal with the circle position float currentSeperation = Vector.Dot(normal, circleToPoint); //if result of dot is bigger than radius if (currentSeperation >= circle.Radius) { //Console.WriteLine("NO COL"); return(false); } //return //if its bigger than stored penetration if (currentSeperation > seperation) { //store current face //store current penetration face = i; seperation = currentSeperation; } } Vector v1 = poly[face]; int secondIndex = face + 1 >= poly.Length ? 0 : face + 1; Vector v2 = poly[secondIndex]; float v1Dot = Vector.Dot(circle.position - v1, v2 - v1); float v2Dot = Vector.Dot(circle.position - v2, v1 - v2); if (v1Dot <= 0) { if (Mathf.DistanceSquared(v1.x, v1.y, circle.position.x, circle.position.y) > circle.Radius * circle.Radius) { //Console.WriteLine("NO COL"); return(false); } } else if (v2Dot <= 0) { if (Mathf.DistanceSquared(v2.x, v2.y, circle.position.x, circle.position.y) > circle.Radius * circle.Radius) { //Console.WriteLine("NO COL"); return(false); } } return(true); }
/// <summary> /// Given a PolygonEntitiy and a Circle Entity, generates a manifold containing the information required to /// resolve the collision (if there was one to begin with). /// </summary> public static Manifold GenerateManifold(PolygonEntity poly, CircleEntity circle) { Manifold Result; Result.A = poly; Result.B = circle; Result.IsEmpty = false; Result.ContactPoint = new List <Vector>(); Vector relativeCirclePos = circle.position - poly.position; float seperation = -10000; int face = -1234; for (int i = 0; i < poly.GetVertices().Length; i++) { //get the normal Vector normal = poly.GetFaceNormal(i).Normalized(); Vector circleToPoint = relativeCirclePos - poly.GetLocalSpaceVertices()[i]; //dot the normal with the circle position float currentSeperation = Vector.Dot(normal, circleToPoint); //if result of dot is bigger than radius if (currentSeperation > circle.Radius) { return(GenerateEmptyManifold()); } //return //if its bigger than stored penetration if (currentSeperation > seperation) { face = i; seperation = currentSeperation; } } Vector v1 = poly.GetVertices()[face]; int secondIndex = face + 1 >= poly.GetVertices().Length ? 0 : face + 1; Vector v2 = poly.GetVertices()[secondIndex]; //if point is inside polygon if (seperation < EPSILON) { //normal is negative face normal Result.Normal = poly.GetFaceNormal(face).Normalized() * -1f; Result.PenetrationDepth = circle.Radius; Result.ContactPoint.Add(Result.Normal * circle.Radius + circle.position); //penetration depth is radius //contact point is -normal*radius + position } //determine which voronoi region the circle lies in //dot with first point float v1Dot = Vector.Dot(circle.position - v1, v2 - v1); float v2Dot = Vector.Dot(circle.position - v2, v1 - v2); Result.PenetrationDepth = circle.Radius - seperation; //dot with second point //penetration depth is radius-seperation //if dot with first point is negative if (v1Dot <= 0) { if (Mathf.DistanceSquared(v1.x, v1.y, circle.position.x, circle.position.y) > circle.Radius * circle.Radius) { return(GenerateEmptyManifold()); } Result.Normal = (v1 - poly.position).Normalized(); Result.ContactPoint.Add(v1); //normal is point-center //contact point is point } else if (v2Dot <= 0) { if (Mathf.DistanceSquared(v2.x, v2.y, circle.position.x, circle.position.y) > circle.Radius * circle.Radius) { return(GenerateEmptyManifold()); } Result.Normal = (v2 - poly.position).Normalized(); Result.ContactPoint.Add(v2); } else { Result.Normal = poly.GetFaceNormal(face).Normalized(); Result.ContactPoint.Add(Result.Normal * circle.Radius + circle.position); } return(Result); }