/// <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, TSVector2 overrideBCenter, // For testing vertices in circles FP overrideBRadius) { TSVector2 r = overrideBCenter - shapeA.worldSpaceOrigin; FP min = shapeA.radius + overrideBRadius; FP distSq = r.sqrMagnitude; if (distSq >= min * min) { return(null); } FP dist = TSMath.Sqrt(distSq); FP distInv = 1.0f / dist; TSVector2 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); }
internal Manifold Assign( VoltWorld world, VoltShape shapeA, VoltShape shapeB) { this.world = world; this.ShapeA = shapeA; this.ShapeB = shapeB; this.Restitution = TSMath.Sqrt(shapeA.Restitution * shapeB.Restitution); this.Friction = TSMath.Sqrt(shapeA.Friction * shapeB.Friction); this.used = 0; return(this); }
/// <summary> /// Checks a ray against a circle with a given origin and square radius. /// </summary> internal static bool CircleRayCast( VoltShape shape, TSVector2 shapeOrigin, FP sqrRadius, ref VoltRayCast ray, ref VoltRayResult result) { TSVector2 toOrigin = shapeOrigin - ray.origin; if (toOrigin.sqrMagnitude < sqrRadius) { result.SetContained(shape); return(true); } FP slope = TSVector2.Dot(toOrigin, ray.direction); if (slope < 0) { return(false); } FP sqrSlope = slope * slope; FP d = sqrRadius + sqrSlope - TSVector2.Dot(toOrigin, toOrigin); if (d < 0) { return(false); } FP dist = slope - TSMath.Sqrt(d); if (dist < 0 || dist > ray.distance) { return(false); } // N.B.: For historical raycasts this normal will be wrong! // Must be either transformed back to world or invalidated later. TSVector2 normal = (dist * ray.direction - toOrigin).normalized; result.Set(shape, dist, normal); return(true); }