ray: add ray-sphere intersection test

This commit is contained in:
Danny Robson 2015-04-13 21:47:51 +10:00
parent 7e2baf6751
commit 8863ebafe9
3 changed files with 40 additions and 3 deletions

25
ray.cpp
View File

@ -71,6 +71,31 @@ util::ray<S,T>::intersect (AABB<S,T> r) const
} }
///----------------------------------------------------------------------------
/// returns the smallest distance from ray origin to a sphere intersection
///
/// returns NaN on miss
template <size_t S, typename T>
T
util::ray<S,T>::intersect (sphere<S,T> 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<T>::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<T>::quiet_NaN ();
}
///---------------------------------------------------------------------------- ///----------------------------------------------------------------------------
/// returns the closest parameter along the ray to a given point /// returns the closest parameter along the ray to a given point
template <size_t S, typename T> template <size_t S, typename T>

View File

@ -18,9 +18,11 @@
#define __UTIL_RAY_HPP #define __UTIL_RAY_HPP
#include "point.hpp" #include "point.hpp"
#include "vector.hpp"
#include "plane.hpp"
#include "aabb.hpp" #include "aabb.hpp"
#include "plane.hpp"
#include "sphere.hpp"
#include "vector.hpp"
namespace util { namespace util {
template <size_t S, typename T> template <size_t S, typename T>
@ -30,6 +32,7 @@ namespace util {
T intersect (plane<S,T>) const; T intersect (plane<S,T>) const;
T intersect (AABB<S,T>) const; T intersect (AABB<S,T>) const;
T intersect (sphere<S,T>) const;
T closest (point<S,T>) const; T closest (point<S,T>) const;

View File

@ -40,7 +40,16 @@ test_intersect_aabb (util::TAP::logger &tap)
void void
test_intersect_sphere (util::TAP::logger &tap) 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");
} }