// David Eberly, Geometric Tools, Redmond WA 98052 // Copyright (c) 1998-2020 // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt // https://www.geometrictools.com/License/Boost/LICENSE_1_0.txt // Version: 4.0.2019.08.13 #pragma once #include #include #include #include // The queries consider the spheres to be solids. namespace WwiseGTE { template class TIQuery, Sphere3> { public: struct Result { bool intersect; }; Result operator()(Sphere3 const& sphere0, Sphere3 const& sphere1) { Result result; Vector3 diff = sphere1.center - sphere0.center; Real rSum = sphere0.radius + sphere1.radius; result.intersect = (Dot(diff, diff) <= rSum * rSum); return result; } }; template class FIQuery, Sphere3> { public: struct Result { bool intersect; // The type of intersection. // 0: spheres are disjoint and separated // 1: spheres touch at point, each sphere outside the other // 2: spheres intersect in a circle // 3: sphere0 strictly contained in sphere1 // 4: sphere0 contained in sphere1, share common point // 5: sphere1 strictly contained in sphere0 // 6: sphere1 contained in sphere0, share common point int type; Vector3 point; // types 1, 4, 6 Circle3 circle; // type 2 }; Result operator()(Sphere3 const& sphere0, Sphere3 const& sphere1) { Result result; // The plane of intersection must have C1-C0 as its normal // direction. Vector3 C1mC0 = sphere1.center - sphere0.center; Real sqrLen = Dot(C1mC0, C1mC0); Real r0 = sphere0.radius, r1 = sphere1.radius; Real rSum = r0 + r1; Real rSumSqr = rSum * rSum; if (sqrLen > rSumSqr) { // The spheres are disjoint/separated. result.intersect = false; result.type = 0; return result; } if (sqrLen == rSumSqr) { // The spheres are just touching with each sphere outside the // other. Normalize(C1mC0); result.intersect = true; result.type = 1; result.point = sphere0.center + r0 * C1mC0; return result; } Real rDif = r0 - r1; Real rDifSqr = rDif * rDif; if (sqrLen < rDifSqr) { // One sphere is strictly contained in the other. Compute a // point in the intersection set. result.intersect = true; result.type = (rDif <= (Real)0 ? 3 : 5); result.point = ((Real)0.5) * (sphere0.center + sphere1.center); return result; } if (sqrLen == rDifSqr) { // One sphere is contained in the other sphere but with a // single point of contact. Normalize(C1mC0); result.intersect = true; if (rDif <= (Real)0) { result.type = 4; result.point = sphere1.center + r1 * C1mC0; } else { result.type = 6; result.point = sphere0.center + r0 * C1mC0; } return result; } // Compute t for which the circle of intersection has center // K = C0 + t*(C1 - C0). Real t = ((Real)0.5) * ((Real)1 + rDif * rSum / sqrLen); // Compute the center and radius of the circle of intersection. result.circle.center = sphere0.center + t * C1mC0; result.circle.radius = std::sqrt(std::max(r0 * r0 - t * t * sqrLen, (Real)0)); // Compute the normal for the plane of the circle. Normalize(C1mC0); result.circle.normal = C1mC0; // The intersection is a circle. result.intersect = true; result.type = 2; return result; } }; }