+bool Intersection(
+ const Sphere &a,
+ const Sphere &b,
+ float &dist,
+ glm::vec3 &norm
+) noexcept {
+ glm::vec3 diff(b.origin - a.origin);
+ float dist2 = glm::length2(diff);
+ if (dist2 < std::numeric_limits<float>::epsilon()) {
+ // origins coincide, use smaller of the diameters for
+ // depth and pick arbitrary normal
+ dist = 2.0f * std::min(a.radius, b.radius);
+ norm = glm::vec3(1.0f, 0.0f, 0.0f);
+ return true;
+ }
+ if (dist2 < (a.radius + b.radius) * (a.radius + b.radius)) {
+ dist = std::sqrt(dist2);
+ norm = diff / dist;
+ dist = a.radius - (dist - b.radius);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool Intersection(
+ const Sphere &sphere,
+ const Plane &plane,
+ float &dist,
+ glm::vec3 &norm
+) noexcept {
+ float sig_dist = SignedDistance(sphere.origin, plane);
+ dist = sphere.radius - std::abs(sig_dist);
+ if (dist > 0.0f) {
+ norm = sig_dist > 0.0f ? plane.normal : -plane.normal;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool Intersection(
+ const Sphere &sphere,
+ const Plane &plane,
+ float &dist
+) noexcept {
+ dist = sphere.radius - SignedDistance(sphere.origin, plane);
+ return dist > 0.0f;
+}
+
+}