/// <summary> /// Workhorse for circle-circle collisions, compares origin distance /// to the sum of the two circles' radii, returns a Manifold. /// </summary> /// private static Manifold TestCircles( VoltWorld world, VoltCircle shapeA, VoltShape shapeB, Vector2 overrideBCenter, // For testing vertices in circles float overrideBRadius) { Vector2 r = overrideBCenter - shapeA.worldSpaceOrigin; float min = shapeA.radius + overrideBRadius; float distSq = r.sqrMagnitude; if (distSq >= min * min) { return(null); } float dist = Mathf.Sqrt(distSq); float distInv = 1.0f / dist; Vector2 pos = shapeA.worldSpaceOrigin + (0.5f + distInv * (shapeA.radius - min / 2.0f)) * r; // Build the collision Manifold Manifold manifold = world.AllocateManifold().Assign(world, shapeA, shapeB); manifold.AddContact(pos, distInv * r, dist - min); return(manifold); }
private static Manifold Polygon_Polygon( VoltWorld world, VoltPolygon polyA, VoltPolygon polyB) { Axis a1, a2; if (Collision.FindMinSepAxis(polyA, polyB, out a1) == false) { return(null); } if (Collision.FindMinSepAxis(polyB, polyA, out a2) == false) { return(null); } // We will use poly1's axis, so we may need to swap if (a2.Width > a1.Width) { VoltUtil.Swap(ref polyA, ref polyB); VoltUtil.Swap(ref a1, ref a2); } // Build the collision Manifold Manifold manifold = world.AllocateManifold().Assign(world, polyA, polyB); Collision.FindVerts(polyA, polyB, a1.Normal, a1.Width, manifold); return(manifold); }
/// <summary> /// Workhorse for circle-circle collisions, compares origin distance /// to the sum of the two circles' radii, returns a Manifold. /// </summary> /// private static Manifold TestCircles( VoltWorld world, VoltCircle shapeA, VoltShape shapeB, VoltVector2 overrideBCenter, // For testing vertices in circles Fix64 overrideBRadius) { VoltVector2 r = overrideBCenter - shapeA.worldSpaceOrigin; Fix64 min = shapeA.radius + overrideBRadius; Fix64 distSq = r.sqrMagnitude; if (distSq >= min * min) { return(null); } Fix64 dist = VoltMath.Sqrt(distSq); // 최소값을 지정하여 divide by zero 방지 Fix64 distInv = Fix64.One / VoltMath.Max(dist, min / (Fix64)10); VoltVector2 pos = shapeA.worldSpaceOrigin + (Fix64.One / (Fix64)2 + distInv * (shapeA.radius - min / (Fix64)2)) * r; // Build the collision Manifold Manifold manifold = world.AllocateManifold().Assign(world, shapeA, shapeB); manifold.AddContact(pos, distInv * r, dist - min); return(manifold); }
private static Manifold Circle_Polygon( VoltWorld world, VoltCircle circ, VoltPolygon poly) { // Get the axis on the polygon closest to the circle's origin float penetration; int index = Collision.FindAxisMaxPenetration( circ.worldSpaceOrigin, circ.radius, poly, out penetration); if (index < 0) { return(null); } Vector2 a, b; poly.GetEdge(index, out a, out b); Axis axis = poly.GetWorldAxis(index); // If the circle is past one of the two vertices, check it like // a circle-circle intersection where the vertex has radius 0 float d = VoltMath.Cross(axis.Normal, circ.worldSpaceOrigin); if (d > VoltMath.Cross(axis.Normal, a)) { return(Collision.TestCircles(world, circ, poly, a, 0.0f)); } if (d < VoltMath.Cross(axis.Normal, b)) { return(Collision.TestCircles(world, circ, poly, b, 0.0f)); } // Build the collision Manifold Manifold manifold = world.AllocateManifold().Assign(world, circ, poly); Vector2 pos = circ.worldSpaceOrigin - (circ.radius + penetration / 2) * axis.Normal; manifold.AddContact(pos, -axis.Normal, penetration); return(manifold); }
/// <summary> /// Workhorse for circle-circle collisions, compares origin distance /// to the sum of the two circles' radii, returns a Manifold. /// </summary> /// private static Manifold TestCircles( VoltWorld world, VoltCircle shapeA, VoltShape shapeB, Vector2 overrideBCenter, // For testing vertices in circles float overrideBRadius) { Vector2 r = overrideBCenter - shapeA.worldSpaceOrigin; float min = shapeA.radius + overrideBRadius; float distSq = r.sqrMagnitude; if (distSq >= min * min) return null; float dist = Mathf.Sqrt(distSq); float distInv = 1.0f / dist; Vector2 pos = shapeA.worldSpaceOrigin + (0.5f + distInv * (shapeA.radius - min / 2.0f)) * r; // Build the collision Manifold Manifold manifold = world.AllocateManifold().Assign(world, shapeA, shapeB); manifold.AddContact(pos, distInv * r, dist - min); return manifold; }
private static Manifold Polygon_Polygon( VoltWorld world, VoltPolygon polyA, VoltPolygon polyB) { Axis a1, a2; if (Collision.FindMinSepAxis(polyA, polyB, out a1) == false) return null; if (Collision.FindMinSepAxis(polyB, polyA, out a2) == false) return null; // We will use poly1's axis, so we may need to swap if (a2.Width > a1.Width) { VoltUtil.Swap(ref polyA, ref polyB); VoltUtil.Swap(ref a1, ref a2); } // Build the collision Manifold Manifold manifold = world.AllocateManifold().Assign(world, polyA, polyB); Collision.FindVerts(polyA, polyB, a1.Normal, a1.Width, manifold); return manifold; }
private static Manifold Circle_Polygon( VoltWorld world, VoltCircle circ, VoltPolygon poly) { // Get the axis on the polygon closest to the circle's origin float penetration; int index = Collision.FindAxisMaxPenetration( circ.worldSpaceOrigin, circ.radius, poly, out penetration); if (index < 0) return null; Vector2 a, b; poly.GetEdge(index, out a, out b); Axis axis = poly.GetWorldAxis(index); // If the circle is past one of the two vertices, check it like // a circle-circle intersection where the vertex has radius 0 float d = VoltMath.Cross(axis.Normal, circ.worldSpaceOrigin); if (d > VoltMath.Cross(axis.Normal, a)) return Collision.TestCircles(world, circ, poly, a, 0.0f); if (d < VoltMath.Cross(axis.Normal, b)) return Collision.TestCircles(world, circ, poly, b, 0.0f); // Build the collision Manifold Manifold manifold = world.AllocateManifold().Assign(world, circ, poly); Vector2 pos = circ.worldSpaceOrigin - (circ.radius + penetration / 2) * axis.Normal; manifold.AddContact(pos, -axis.Normal, penetration); return manifold; }