/// <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); }
/// <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); }
/// <summary> /// Creates a new circle shape from a world-space origin. /// </summary> public VoltCircle CreateCircleWorldSpace( VoltVector2 worldSpaceOrigin, Fix64 radius, Fix64 density, Fix64 friction, Fix64 restitution) { VoltCircle circle = (VoltCircle)this.circlePool.Allocate(); circle.InitializeFromWorldSpace( worldSpaceOrigin, radius, density, friction, restitution); return(circle); }
private static Manifold Circle_Circle( VoltWorld world, VoltCircle circA, VoltCircle circB) { return (TestCircles( world, circA, circB, circB.worldSpaceOrigin, circB.radius)); }
/// <summary> /// Creates a new circle shape from a world-space origin. /// </summary> public VoltCircle CreateCircleWorldSpace( TSVector2 worldSpaceOrigin, FP radius, FP?density = null, FP?friction = null, FP?restitution = null) { VoltCircle circle = (VoltCircle)this.circlePool.Allocate(); circle.InitializeFromWorldSpace( worldSpaceOrigin, radius, density ?? VoltConfig.DEFAULT_DENSITY, friction ?? VoltConfig.DEFAULT_FRICTION, restitution ?? VoltConfig.DEFAULT_RESTITUTION); return(circle); }
/// <summary> /// Creates a new circle shape from a world-space origin. /// </summary> public VoltCircle CreateCircleWorldSpace( Vector2 worldSpaceOrigin, float radius, float density = VoltConfig.DEFAULT_DENSITY, float friction = VoltConfig.DEFAULT_FRICTION, float restitution = VoltConfig.DEFAULT_RESTITUTION) { VoltCircle circle = (VoltCircle)this.circlePool.Allocate(); circle.InitializeFromWorldSpace( worldSpaceOrigin, radius, density, friction, restitution); return(circle); }
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); }