]> git.localhorst.tv Git - blobs.git/blobdiff - tst/math/IntersectTest.cpp
use matrix translations in ray/sphere test
[blobs.git] / tst / math / IntersectTest.cpp
index dc6667aaed3c03b05cc254bcbb31f04f03975feb..904d682325d89915c8a08d042fa68d82879d75eb 100644 (file)
@@ -177,8 +177,8 @@ void IntersectTest::testBoxBoxIntersection() {
        glm::dvec3 normal(0);
 
        AABB box{ { -1, -1, -1 }, { 1, 1, 1 } }; // 2x2x2 cube centered around origin
-       glm::mat4 Ma(1); // identity
-       glm::mat4 Mb(1); // identity
+       glm::dmat4 Ma(1); // identity
+       glm::dmat4 Mb(1); // identity
        // they're identical, so should probably intersect ^^
 
        CPPUNIT_ASSERT_MESSAGE(
@@ -209,11 +209,11 @@ void IntersectTest::testBoxBoxIntersection() {
        );
        CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
                "bad penetration depth (with rotation)",
-               0.0142134428024292, depth, delta
+               0.014213562373095, depth, delta
        );
        AssertEqual(
                "bad intersection normal (with rotation)",
-               glm::dvec3(1, 0, 0), abs(normal) // normal can be in + or - x, therefore abs()
+               glm::dvec3(1, 0, 0), glm::abs(normal) // normal can be in + or - x, therefore abs()
        );
 
        Mb = glm::translate(glm::dvec3(3, 0, 0)); // 3 to the right
@@ -223,6 +223,102 @@ void IntersectTest::testBoxBoxIntersection() {
        );
 }
 
+void IntersectTest::testRaySphereIntersection() {
+       const double epsilon = std::numeric_limits<double>::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)
+       );
+}
+
 }
 }
 }