function getAABB(rect: Cuboid) { const result = { min: [rect.x, rect.y, rect.z], max: [rect.x + rect.w, rect.y + rect.h, rect.z + rect.d], }; // Swap the vertices if the min/max is reversed // because of orientation or whatever. for (let i = 0; i < 3; i++) { if (result.max[i] < result.min[i]) { // Swap const a = result.min[i]; result.min[i] = result.max[i]; result.max[i] = a; } } return result; } function squaredDistPointAABB(sphere: Sphere, rect: Cuboid) { let sqDist = 0; const p = [sphere.x, sphere.y, sphere.z]; const b = getAABB(rect); for (let i = 0; i < 3; i++) { // for each axis count any excess distance outside box extents let v = p[i]; if (v < b.min[i]) sqDist += (b.min[i] - v) * (b.min[i] - v); if (v > b.max[i]) sqDist += (v - b.max[i]) * (v - b.max[i]); } return sqDist; } export function sphereRectCollision( sphere: Sphere, rect: Cuboid ): [boolean, number] { // Compute squared distance between sphere center and AABB // the sqrt(dist) is fine to use as well, but this is faster. let sqDist = squaredDistPointAABB(sphere, rect); // Sphere and AABB intersect if the (squared) distance between them is // less than the (squared) sphere radius. return [sqDist <= sphere.radius * sphere.radius, sqDist]; }