From 8863ebafe9eac3901e750470ce6a3225beb8165a Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Mon, 13 Apr 2015 21:47:51 +1000 Subject: [PATCH] ray: add ray-sphere intersection test --- ray.cpp | 25 +++++++++++++++++++++++++ ray.hpp | 7 +++++-- test/ray.cpp | 11 ++++++++++- 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/ray.cpp b/ray.cpp index 078b9945..1910fbfa 100644 --- a/ray.cpp +++ b/ray.cpp @@ -71,6 +71,31 @@ util::ray::intersect (AABB r) const } +///---------------------------------------------------------------------------- +/// returns the smallest distance from ray origin to a sphere intersection +/// +/// returns NaN on miss +template +T +util::ray::intersect (sphere s) const +{ + T b = dot (d, p - s.c); + T c = dot (p - s.c, p - s.c) - s.r * s.r; + + T D = b * b - c; + if (D < 0) + return std::numeric_limits::quiet_NaN (); + + auto t_ = std::sqrt (D); + auto t0 = -b + t_; + auto t1 = -b - t_; + + return t1 >= 0 ? t1 : + t0 >= 0 ? t0 : + std::numeric_limits::quiet_NaN (); +} + + ///---------------------------------------------------------------------------- /// returns the closest parameter along the ray to a given point template diff --git a/ray.hpp b/ray.hpp index bbe97fc1..e79502b1 100644 --- a/ray.hpp +++ b/ray.hpp @@ -18,9 +18,11 @@ #define __UTIL_RAY_HPP #include "point.hpp" -#include "vector.hpp" -#include "plane.hpp" + #include "aabb.hpp" +#include "plane.hpp" +#include "sphere.hpp" +#include "vector.hpp" namespace util { template @@ -30,6 +32,7 @@ namespace util { T intersect (plane) const; T intersect (AABB) const; + T intersect (sphere) const; T closest (point) const; diff --git a/test/ray.cpp b/test/ray.cpp index c2895d84..a42ebeab 100644 --- a/test/ray.cpp +++ b/test/ray.cpp @@ -40,7 +40,16 @@ test_intersect_aabb (util::TAP::logger &tap) void test_intersect_sphere (util::TAP::logger &tap) { - ; + const util::sphere3f s = {{0.f, 0.f, 0.f}, 1.f}; + + const util::ray3f r0 {{0.f, 2.f, 0.f}, {0.f, -1.f, 0.f}}; + tap.expect_eq (r0.intersect (s), 1.f, "ray-sphere simple"); + + const util::ray3f r1 {{0.f, 1.f, 0.f}, {0.f, 1.f, 0.f}}; + tap.expect_eq (r1.intersect (s), 0.f, "ray-sphere adjacent"); + + const util::ray3f r2 {{0.f, 2.f, 0.f}, {0.f, 1.f, 0.f}}; + tap.expect_nan (r2.intersect (s), "ray-sphere no-intersect"); }