]> git.localhorst.tv Git - blank.git/commitdiff
box/box intersection test
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Tue, 23 Jun 2015 12:54:00 +0000 (14:54 +0200)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Tue, 23 Jun 2015 12:54:00 +0000 (14:54 +0200)
only boolean test for now

src/model/geometry.cpp
src/model/geometry.hpp
tst/model/GeometryTest.cpp
tst/model/GeometryTest.hpp

index ed9b4b7ed5339d5805fb33287b491c6ef2e5eb6d..b08d59fe5b556ebcdbc680b568cf36358f89a5f7 100644 (file)
@@ -65,6 +65,71 @@ bool Intersection(
        return true;
 }
 
+
+bool Intersection(
+       const AABB &a_box,
+       const glm::mat4 &a_m,
+       const AABB &b_box,
+       const glm::mat4 &b_m
+) noexcept {
+       glm::vec3 a_corners[8] = {
+               glm::vec3(a_m * glm::vec4(a_box.min.x, a_box.min.y, a_box.min.z, 1)),
+               glm::vec3(a_m * glm::vec4(a_box.min.x, a_box.min.y, a_box.max.z, 1)),
+               glm::vec3(a_m * glm::vec4(a_box.min.x, a_box.max.y, a_box.min.z, 1)),
+               glm::vec3(a_m * glm::vec4(a_box.min.x, a_box.max.y, a_box.max.z, 1)),
+               glm::vec3(a_m * glm::vec4(a_box.max.x, a_box.min.y, a_box.min.z, 1)),
+               glm::vec3(a_m * glm::vec4(a_box.max.x, a_box.min.y, a_box.max.z, 1)),
+               glm::vec3(a_m * glm::vec4(a_box.max.x, a_box.max.y, a_box.min.z, 1)),
+               glm::vec3(a_m * glm::vec4(a_box.max.x, a_box.max.y, a_box.max.z, 1)),
+       };
+
+       glm::vec3 b_corners[8] = {
+               glm::vec3(b_m * glm::vec4(b_box.min.x, b_box.min.y, b_box.min.z, 1)),
+               glm::vec3(b_m * glm::vec4(b_box.min.x, b_box.min.y, b_box.max.z, 1)),
+               glm::vec3(b_m * glm::vec4(b_box.min.x, b_box.max.y, b_box.min.z, 1)),
+               glm::vec3(b_m * glm::vec4(b_box.min.x, b_box.max.y, b_box.max.z, 1)),
+               glm::vec3(b_m * glm::vec4(b_box.max.x, b_box.min.y, b_box.min.z, 1)),
+               glm::vec3(b_m * glm::vec4(b_box.max.x, b_box.min.y, b_box.max.z, 1)),
+               glm::vec3(b_m * glm::vec4(b_box.max.x, b_box.max.y, b_box.min.z, 1)),
+               glm::vec3(b_m * glm::vec4(b_box.max.x, b_box.max.y, b_box.max.z, 1)),
+       };
+
+       glm::vec3 axes[6] = {
+               glm::vec3(a_m * glm::vec4(1, 0, 0, 0)),
+               glm::vec3(a_m * glm::vec4(0, 1, 0, 0)),
+               glm::vec3(a_m * glm::vec4(0, 0, 1, 0)),
+               glm::vec3(b_m * glm::vec4(1, 0, 0, 0)),
+               glm::vec3(b_m * glm::vec4(0, 1, 0, 0)),
+               glm::vec3(b_m * glm::vec4(0, 0, 1, 0)),
+       };
+
+       for (const glm::vec3 &axis : axes) {
+               float a_min = std::numeric_limits<float>::infinity();
+               float a_max = -std::numeric_limits<float>::infinity();
+               for (const glm::vec3 &corner : a_corners) {
+                       float val = glm::dot(corner, axis);
+                       a_min = std::min(a_min, val);
+                       a_max = std::max(a_max, val);
+               }
+
+               float b_min = std::numeric_limits<float>::infinity();
+               float b_max = -std::numeric_limits<float>::infinity();
+               for (const glm::vec3 &corner : b_corners) {
+                       float val = glm::dot(corner, axis);
+                       b_min = std::min(b_min, val);
+                       b_max = std::max(b_max, val);
+               }
+
+               if (a_max < b_min || b_max < a_min) return false;
+       }
+
+       // TODO: find intersection point and normals
+       // normal could be deduced from the axis with the lowest min?
+
+       return true;
+}
+
+
 bool CullTest(const AABB &box, const glm::mat4 &MVP) noexcept {
        // transform corners into clip space
        glm::vec4 corners[8] = {
index d6e3d2847782e2b1d882e49d7e5cf3fa7e77386a..f4498f5fa743ec734edc84aa90a87eb1d55757ab 100644 (file)
@@ -36,6 +36,12 @@ bool Intersection(
        float *dist = nullptr,
        glm::vec3 *normal = nullptr) noexcept;
 
+bool Intersection(
+       const AABB &a_box,
+       const glm::mat4 &a_m,
+       const AABB &b_box,
+       const glm::mat4 &b_m) noexcept;
+
 bool CullTest(const AABB &box, const glm::mat4 &MVP) noexcept;
 
 }
index 51985aef7a70e38df8df09051d44911adf02cd72..71830c6176930f31421e31af7afb052dff937292 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <limits>
 #include <glm/gtx/io.hpp>
+#include <glm/gtx/transform.hpp>
 
 CPPUNIT_TEST_SUITE_REGISTRATION(blank::test::GeometryTest);
 
@@ -18,7 +19,7 @@ void GeometryTest::tearDown() {
 }
 
 
-void GeometryTest::testRayAABBIntersection() {
+void GeometryTest::testRayBoxIntersection() {
        Ray ray{ { 0, 0, 0 }, { 1, 0, 0 } }; // at origin, pointing right
        AABB box{ { -1, -1, -1 }, { 1, 1, 1 } }; // 2x2x2 cube centered around origin
        glm::mat4 M(1); // no transformation
@@ -62,5 +63,38 @@ void GeometryTest::testRayAABBIntersection() {
        );
 }
 
+void GeometryTest::testBoxBoxIntersection() {
+       AABB box{ { -1, -1, -1 }, { 1, 1, 1 } }; // 2x2x2 cube centered around origin
+       glm::mat4 Ma(1); // identity
+       glm::mat4 Mb(1); // identity
+       // they're identical, so should probably intersect ^^
+
+       CPPUNIT_ASSERT_MESSAGE(
+               "identical OBBs don't intersect",
+               Intersection(box, Ma, box, Mb)
+       );
+
+       Ma = glm::translate(glm::vec3(-2, 0, 0)); // 2 to the left
+       Mb = glm::translate(glm::vec3(2, 0, 0)); // 2 to the right
+       CPPUNIT_ASSERT_MESSAGE(
+               "distant OBBs intersect (2 apart, no rotation)",
+               !Intersection(box, Ma, box, Mb)
+       );
+
+       Ma = glm::rotate(PI_0p25, glm::vec3(0, 0, 1)); // rotated 45° around Z
+       Mb = glm::translate(glm::vec3(2.4, 0, 0)); // 2.4 to the right
+       // they should barely touch. intersect by about 0.01 if my head works
+       CPPUNIT_ASSERT_MESSAGE(
+               "OBBs don't intersect (one rotated by 45°)",
+               Intersection(box, Ma, box, Mb)
+       );
+
+       Mb = glm::translate(glm::vec3(3, 0, 0)); // 3 to the right
+       CPPUNIT_ASSERT_MESSAGE(
+               "OBBs intersect (one rotated by 45°)",
+               !Intersection(box, Ma, box, Mb)
+       );
+}
+
 }
 }
index 2ee85b1ebffde55c086c6f3ff6abc8b03f88ecac..7ba2d2d4019c16f4c1e47a9bd6b50577f1eaab95 100644 (file)
@@ -12,7 +12,8 @@ class GeometryTest
 
 CPPUNIT_TEST_SUITE(GeometryTest);
 
-CPPUNIT_TEST(testRayAABBIntersection);
+CPPUNIT_TEST(testRayBoxIntersection);
+CPPUNIT_TEST(testBoxBoxIntersection);
 
 CPPUNIT_TEST_SUITE_END();
 
@@ -20,7 +21,8 @@ public:
        void setUp();
        void tearDown();
 
-       void testRayAABBIntersection();
+       void testRayBoxIntersection();
+       void testBoxBoxIntersection();
 
 };