X-Git-Url: https://git.localhorst.tv/?a=blobdiff_plain;f=tst%2Fmath%2FIntersectTest.cpp;h=904d682325d89915c8a08d042fa68d82879d75eb;hb=HEAD;hp=2ed07fb2fe7e5e1792817da61d1aa8318f597392;hpb=0e061ce526fe46dd3e894223e5d646eb2e30f826;p=blobs.git diff --git a/tst/math/IntersectTest.cpp b/tst/math/IntersectTest.cpp index 2ed07fb..904d682 100644 --- a/tst/math/IntersectTest.cpp +++ b/tst/math/IntersectTest.cpp @@ -223,6 +223,102 @@ void IntersectTest::testBoxBoxIntersection() { ); } +void IntersectTest::testRaySphereIntersection() { + const double epsilon = std::numeric_limits::epsilon(); + Ray ray{ { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 } }; // at origin, pointing right + Sphere sphere{ { 0.0, 0.0, 0.0 }, 1.0 }; // unit sphere at origin + + glm::dvec3 normal(0.0); + double dist = 0.0; + CPPUNIT_ASSERT_MESSAGE( + "ray at origin does not intersect sphere at origin", + Intersect(ray, sphere, normal, dist) + ); + CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( + "distance along ray to unit sphere, both at origin, is not 1", + 1.0, dist, epsilon + ); + AssertEqual( + "bad intersection normal", + glm::dvec3(1.0, 0.0, 0.0), normal + ); + + ray.Origin({ 0.5, 0.0, 0.0 }); // a tad to the right + CPPUNIT_ASSERT_MESSAGE( + "ray does not intersect sphere at origin", + Intersect(ray, sphere, normal, dist) + ); + CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( + "distance along ray to unit sphere at origin is not 0.5", + 0.5, dist, epsilon + ); + AssertEqual( + "bad intersection normal", + glm::dvec3(1.0, 0.0, 0.0), normal + ); + + // corner case: ray origin exactly on sphere (should "intersect") + ray = glm::translate(glm::dvec3(0.5, 0, 0)) * ray; + CPPUNIT_ASSERT_MESSAGE( + "ray touching sphere does not intersect it", + Intersect(ray, sphere, normal, dist) + ); + CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( + "distance along ray touching unit sphere is not 0.0", + 0.0, dist, epsilon + ); + AssertEqual( + "bad intersection normal", + glm::dvec3(1.0, 0.0, 0.0), normal + ); + + ray.Origin({ 2.0, 0.0, 0.0 }); // move outside + CPPUNIT_ASSERT_MESSAGE( + "ray pointing away from sphere intersects it for some reason", + !Intersect(ray, sphere, normal, dist) + ); + + ray.Direction({ -1.0, 0.0, 0.0 }); // flip it around + CPPUNIT_ASSERT_MESSAGE( + "negative X ray does not intersect sphere", + Intersect(ray, sphere, normal, dist) + ); + CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( + "distance along ray to unit sphere at origin is not 1", + 1.0, dist, epsilon + ); + AssertEqual( + "bad intersection normal", + glm::dvec3(1.0, 0.0, 0.0), normal + ); + + // sphere at 3,0,0; ray at 0,4,0 pointing directly at it + // should be 5 units apart, minus one for the radius + ray.Origin({ 0.0, 4.0, 0.0 }); + ray.Direction(glm::normalize(glm::dvec3(3.0, -4.0, 0.0))); + sphere = glm::translate(glm::dvec3(3.0, 0, 0)) * sphere; + sphere.origin = { 3.0, 0.0, 0.0 }; + CPPUNIT_ASSERT_MESSAGE( + "diagonal ray does not intersect sphere", + Intersect(ray, sphere, normal, dist) + ); + CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( + "distance along ray to unit sphere is not 4", + 4.0, dist, epsilon + ); + AssertEqual( + "bad intersection normal", + glm::normalize(glm::dvec3(-3.0, 4.0, 0.0)), normal + ); + + // point the ray straight down, so it misses + ray.Direction({ 0.0, -1.0, 0.0}); + CPPUNIT_ASSERT_MESSAGE( + "vertical ray should not intersect sphere", + !Intersect(ray, sphere, normal, dist) + ); +} + } } }