/// <summary> /// Determine whether two spheres intersect. /// </summary> /// <param name="firstSphere">The first sphere</param> /// <param name="secondSphere">The second sphere</param> public static bool SphereSphereCollision(SphereBody firstSphere, SphereBody secondSphere) { var maxDistanceSquared = Math.Pow(firstSphere.Radius + secondSphere.Radius, 2); var distanceSquared = Vector3.DistanceSquared(firstSphere.Position, secondSphere.Position); return(distanceSquared < maxDistanceSquared); }
/// <summary> /// Determine whether a box and a sphere intersect. /// </summary> /// <param name="box">Box physics object</param> /// <param name="sphere">Sphere physics object</param> public static bool BoxSphereCollision(BoxBody box, SphereBody sphere) { // reference frame: box at (0, 0, 0), sides aligned with axes var sphereCoordsRelative = sphere.Position - box.Position; // to transform coordinate system to have box be axis-aligned, we apply // the reverse of the rotation to the sphere coordinates var inverse = new Quaternion(box.Rotation.X, box.Rotation.Y, box.Rotation.Z, -box.Rotation.W); var sphereCoordsTransformed = Vector3.Transform(sphereCoordsRelative, inverse); // to check collision, we need to know if the shortest distance between the box // and the center of the sphere is smaller than the radius of the sphere // X coordinate of closest point = sphere.X if sphere.x is between the minimum // and maximum x coordinate of the box - same for y and z var boxMinX = -box.Size.X / 2; var boxMaxX = +box.Size.X / 2; var boxMinY = -box.Size.Y / 2; var boxMaxY = +box.Size.Y / 2; var boxMinZ = -box.Size.Z / 2; var boxMaxZ = +box.Size.Z / 2; var closestPointToSphereX = Math.Clamp(sphereCoordsTransformed.X, boxMinX, boxMaxX); var closestPointToSphereY = Math.Clamp(sphereCoordsTransformed.Y, boxMinY, boxMaxY); var closestPointToSphereZ = Math.Clamp(sphereCoordsTransformed.Z, boxMinZ, boxMaxZ); return(Vector3.DistanceSquared(sphereCoordsTransformed, new Vector3(closestPointToSphereX, closestPointToSphereY, closestPointToSphereZ)) < Math.Pow(sphere.Radius, 2)); }
/// <summary> /// Creates a sphere body. /// </summary> /// <param name="simulation">The simulation to use.</param> /// <param name="position">The position of the body.</param> /// <param name="radius">The radius of the sphere.</param> /// <returns>The sphere body that was created.</returns> public static SphereBody Create(PhysicsSimulation simulation, Vector3 position, float radius) { var obj = new SphereBody(simulation); obj.Position = position; obj.Radius = radius; simulation.Register(obj); return(obj); }
/// <summary> /// Determine whether a capsule and a sphere intersect. /// </summary> /// <param name="capsule">Capsule physics object</param> /// <param name="sphere">Sphere physics object</param> public static bool CapsuleSphereCollision(CapsuleBody capsule, SphereBody sphere) { // reference frame: capsule at (0, 0, 0), pointing in positive y direction var sphereCoordsRelative = sphere.Position - capsule.Position; // to transform coordinate system to have capsule be axis-aligned, we apply // the reverse of the rotation to the sphere coordinates var inverse = new Quaternion(capsule.Rotation.X, capsule.Rotation.Y, capsule.Rotation.Z, -capsule.Rotation.W); var sphereCoordsTransformed = Vector3.Transform(sphereCoordsRelative, inverse); // coordinates of the line in the centre of the cylinder part const int capsuleMinY = 0; var capsuleMaxY = capsule.Height; const int closestPointToSphereX = 0; var closestPointToSphereY = Math.Clamp(sphereCoordsTransformed.Y, capsuleMinY, capsuleMaxY); const int closestPointToSphereZ = 0; return(Vector3.DistanceSquared(sphereCoordsTransformed, new Vector3(closestPointToSphereX, closestPointToSphereY, closestPointToSphereZ)) < Math.Pow(capsule.Radius + sphere.Radius, 2)); }