From bef0aa49299200fd96b34e9f2f26753f184a1208 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Fri, 13 Apr 2018 18:46:37 +1000 Subject: [PATCH] sphere: move ray tests into sphere's unit --- CMakeLists.txt | 1 + geom/ray.hpp | 31 +------------------------ geom/sphere.hpp | 34 +++++++++++++++++++++++++++- test/geom/ray.cpp | 20 ---------------- test/geom/sphere.cpp | 54 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 89 insertions(+), 51 deletions(-) create mode 100644 test/geom/sphere.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 463588e0..845eaa80 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -494,6 +494,7 @@ if (TESTS) geom/aabb geom/ray geom/frustum + geom/sphere hash/checksum hash/crc hash/fasthash diff --git a/geom/ray.hpp b/geom/ray.hpp index 50ea98c1..88ecfc0b 100644 --- a/geom/ray.hpp +++ b/geom/ray.hpp @@ -11,7 +11,7 @@ * See the License for the specific language governing permissions and * limitations under the License. * - * Copyright 2015 Danny Robson + * Copyright 2015-2018 Danny Robson */ #ifndef __UTIL_GEOM_RAY_HPP @@ -19,7 +19,6 @@ #include "aabb.hpp" #include "plane.hpp" -#include "sphere.hpp" #include "../vector.hpp" #include "../point.hpp" @@ -108,34 +107,6 @@ namespace util::geom { } - /////////////////////////////////////////////////////////////////////////// - /// returns the smallest distance from a ray to a sphere intersection - /// - /// returns NaN on miss - /// returns NaN if behind - template - constexpr T - distance (const ray r, const sphere s) - { - const T b = dot (r.direction, r.origin - s.centre); - const T c = dot (r.origin - s.centre, r.origin - s.centre) - s.radius * s.radius; - - const T D = b * b - c; - - // no intersection - 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 (); - } - - //------------------------------------------------------------------------- // convenience method to test a ray intersects an aabb template diff --git a/geom/sphere.hpp b/geom/sphere.hpp index 8f0c683a..480c6c3e 100644 --- a/geom/sphere.hpp +++ b/geom/sphere.hpp @@ -11,7 +11,7 @@ * See the License for the specific language governing permissions and * limitations under the License. * - * Copyright 2015 Danny Robson + * Copyright 2015-2018 Danny Robson */ #ifndef __UTIL_GEOM_SPHERE_HPP @@ -19,6 +19,8 @@ #include "../point.hpp" +#include "ray.hpp" + /////////////////////////////////////////////////////////////////////////////// namespace util::geom { @@ -30,6 +32,36 @@ namespace util::geom { typedef sphere<2,float> sphere2f; typedef sphere<3,float> sphere3f; + + + /////////////////////////////////////////////////////////////////////////// + /// returns the smallest distance from a ray to a sphere intersection + /// + /// returns NaN on miss + /// returns NaN if behind + template + constexpr T + distance (const ray r, const sphere s) + { + const T b = dot (r.direction, r.origin - s.centre); + const T c = dot (r.origin - s.centre, r.origin - s.centre) - s.radius * s.radius; + + const T D = b * b - c; + + // no intersection + if (D < 0) + return INFINITY; + + auto t_ = std::sqrt (D); + auto t0 = -b + t_; + auto t1 = -b - t_; + + return t1 >= 0 ? t1 : + t0 >= 0 ? t0 : + INFINITY; + } + + } #endif diff --git a/test/geom/ray.cpp b/test/geom/ray.cpp index ecd3c43d..164d3885 100644 --- a/test/geom/ray.cpp +++ b/test/geom/ray.cpp @@ -47,25 +47,6 @@ test_intersect_aabb (util::TAP::logger &tap) } -//----------------------------------------------------------------------------- -void -test_intersect_sphere (util::TAP::logger &tap) -{ - using util::geom::sphere3f; - - const sphere3f s = {{0.f, 0.f, 0.f}, 1.f}; - - const ray3f r0 {util::point3f {0.f, 2.f, 0.f}, util::vector3f {0.f, -1.f, 0.f}}; - tap.expect_eq (distance (r0, s), 1.f, "ray-sphere simple"); - - const ray3f r1 {util::point3f {0.f, 1.f, 0.f}, util::vector3f {0.f, 1.f, 0.f}}; - tap.expect_eq (distance (r1, s), 0.f, "ray-sphere adjacent"); - - const ray3f r2 {util::point3f {0.f, 2.f, 0.f}, util::vector3f {0.f, 1.f, 0.f}}; - tap.expect_nan (distance (r2, s), "ray-sphere no-intersect"); -} - - //----------------------------------------------------------------------------- int main (void) @@ -74,7 +55,6 @@ main (void) test_intersect_plane (tap); test_intersect_aabb (tap); - test_intersect_sphere (tap); return tap.status (); } diff --git a/test/geom/sphere.cpp b/test/geom/sphere.cpp new file mode 100644 index 00000000..64a1a06f --- /dev/null +++ b/test/geom/sphere.cpp @@ -0,0 +1,54 @@ +#include "tap.hpp" + +#include "geom/sphere.hpp" + +using util::geom::ray2f; +using util::geom::ray3f; + + +/////////////////////////////////////////////////////////////////////////////// +void +test_intersect (util::TAP::logger &tap) +{ + using util::geom::sphere3f; + + static const struct { + float d; + sphere3f s; + ray3f r; + const char *message; + } TESTS[] = { + { + 1.f, + { util::point3f {0.f}, 1.f }, + { util::point3f {0, 2, 0}, util::vector3f {0,-1,0} }, + "straight towards unit-origin sphere" + }, + { + 0.f, + { util::point3f {0}, 1.f }, + { util::point3f {0,1,0}, util::vector3f {0,1,0} }, + "ray origin coincides with unit-origin sphere", + }, + { + INFINITY, + { util::point3f {0}, 1 }, + { util::point3f {0,2,0}, util::vector3f {0,1,0} }, + "offset ray never intersects unit-origin sphere" + } + }; + + for (const auto &[d,s,r,msg]: TESTS) { + tap.expect_eq (d, distance (r, s), "%!", msg); + } +} + + +/////////////////////////////////////////////////////////////////////////////// +int +main () +{ + util::TAP::logger tap; + test_intersect (tap); + return tap.status (); +} \ No newline at end of file