]> git.localhorst.tv Git - blobs.git/blobdiff - src/math/geometry.cpp
allow clicking celestial bodies
[blobs.git] / src / math / geometry.cpp
index f822ad68e4de3529a14847a6b4d5ab38b5ffeedc..3afa944f479b0fc41905d5de6364ee6ca8068e5b 100644 (file)
@@ -41,15 +41,15 @@ bool Intersect(
                glm::dvec3(b_m[0]),
                glm::dvec3(b_m[1]),
                glm::dvec3(b_m[2]),
-               normalize(cross(glm::dvec3(a_m[0]), glm::dvec3(b_m[0]))),
-               normalize(cross(glm::dvec3(a_m[0]), glm::dvec3(b_m[1]))),
-               normalize(cross(glm::dvec3(a_m[0]), glm::dvec3(b_m[2]))),
-               normalize(cross(glm::dvec3(a_m[1]), glm::dvec3(b_m[0]))),
-               normalize(cross(glm::dvec3(a_m[1]), glm::dvec3(b_m[1]))),
-               normalize(cross(glm::dvec3(a_m[1]), glm::dvec3(b_m[2]))),
-               normalize(cross(glm::dvec3(a_m[2]), glm::dvec3(b_m[0]))),
-               normalize(cross(glm::dvec3(a_m[2]), glm::dvec3(b_m[1]))),
-               normalize(cross(glm::dvec3(a_m[2]), glm::dvec3(b_m[2]))),
+               glm::normalize(glm::cross(glm::dvec3(a_m[0]), glm::dvec3(b_m[0]))),
+               glm::normalize(glm::cross(glm::dvec3(a_m[0]), glm::dvec3(b_m[1]))),
+               glm::normalize(glm::cross(glm::dvec3(a_m[0]), glm::dvec3(b_m[2]))),
+               glm::normalize(glm::cross(glm::dvec3(a_m[1]), glm::dvec3(b_m[0]))),
+               glm::normalize(glm::cross(glm::dvec3(a_m[1]), glm::dvec3(b_m[1]))),
+               glm::normalize(glm::cross(glm::dvec3(a_m[1]), glm::dvec3(b_m[2]))),
+               glm::normalize(glm::cross(glm::dvec3(a_m[2]), glm::dvec3(b_m[0]))),
+               glm::normalize(glm::cross(glm::dvec3(a_m[2]), glm::dvec3(b_m[1]))),
+               glm::normalize(glm::cross(glm::dvec3(a_m[2]), glm::dvec3(b_m[2]))),
        };
 
        depth = std::numeric_limits<double>::infinity();
@@ -57,7 +57,7 @@ bool Intersect(
 
        int cur_axis = 0;
        for (const glm::dvec3 &axis : axes) {
-               if (any(isnan(axis))) {
+               if (glm::any(glm::isnan(axis))) {
                        // can result from the cross products if A and B have parallel axes
                        ++cur_axis;
                        continue;
@@ -65,7 +65,7 @@ bool Intersect(
                double a_min = std::numeric_limits<double>::infinity();
                double a_max = -std::numeric_limits<double>::infinity();
                for (const glm::dvec3 &corner : a_corners) {
-                       double val = dot(corner, axis);
+                       double val = glm::dot(corner, axis);
                        a_min = std::min(a_min, val);
                        a_max = std::max(a_max, val);
                }
@@ -73,7 +73,7 @@ bool Intersect(
                double b_min = std::numeric_limits<double>::infinity();
                double b_max = -std::numeric_limits<double>::infinity();
                for (const glm::dvec3 &corner : b_corners) {
-                       double val = dot(corner, axis);
+                       double val = glm::dot(corner, axis);
                        b_min = std::min(b_min, val);
                        b_max = std::max(b_max, val);
                }
@@ -148,5 +148,37 @@ bool Intersect(
        return true;
 }
 
+bool Intersect(
+       const Ray &r,
+       const Sphere &s,
+       glm::dvec3 &normal,
+       double &dist
+) noexcept {
+       const glm::dvec3 diff(s.origin - r.Origin());
+       if (glm::dot(diff, r.Direction()) < 0.0) {
+               if (glm::length2(diff) > s.radius * s.radius) return false;
+               if (std::abs(glm::length2(diff) - s.radius * s.radius) < std::numeric_limits<double>::epsilon() * s.radius) {
+                       normal = glm::normalize(-diff);
+                       dist = 0.0;
+                       return true;
+               }
+               const glm::dvec3 pc(r.Direction() * glm::dot(r.Direction(), diff) + r.Origin());
+               double idist = std::sqrt(s.radius * s.radius - glm::length2(pc - s.origin));
+               dist = idist - glm::length(pc - r.Origin());
+               normal = glm::normalize((r.Origin() + (r.Direction() * dist)) - s.origin);
+               return true;
+       }
+       const glm::dvec3 pc(r.Direction() * glm::dot(r.Direction(), diff) + r.Origin());
+       if (glm::length2(s.origin - pc) > s.radius * s.radius) return false;
+       double idist = std::sqrt(s.radius * s.radius - glm::length2(pc - s.origin));
+       if (glm::length2(diff) > s.radius * s.radius) {
+               dist = glm::length(pc - r.Origin()) - idist;
+       } else {
+               dist = glm::length(pc - r.Origin()) + idist;
+       }
+       normal = glm::normalize((r.Origin() + (r.Direction() * dist)) - s.origin);
+       return true;
+}
+
 }
 }