1 #include "IntersectionTest.hpp"
3 #include "geometry/const.hpp"
4 #include "geometry/primitive.hpp"
7 #include <glm/gtx/io.hpp>
8 #include <glm/gtx/transform.hpp>
10 CPPUNIT_TEST_SUITE_REGISTRATION(gong::geometry::test::IntersectionTest);
17 void IntersectionTest::setUp() {
20 void IntersectionTest::tearDown() {
24 void IntersectionTest::testSimpleRayBoxIntersection() {
25 Ray ray{ { 0, 0, 0 }, { 1, 0, 0 }, { } }; // at origin, pointing right
27 AABB box{ { -1, -1, -1 }, { 1, 1, 1 } }; // 2x2x2 cube centered around origin
29 const float delta = std::numeric_limits<float>::epsilon();
33 CPPUNIT_ASSERT_MESSAGE(
34 "ray at origin not intersecting box at origin",
35 Intersection(ray, box, distance)
38 // move ray outside the box, but have it still point at it
39 // should be 4 units to the left now
41 CPPUNIT_ASSERT_MESSAGE(
42 "ray pointing at box doesn't intersect",
43 Intersection(ray, box, distance)
45 CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
46 "intersection distance way off",
50 // move ray to the other side, so it's pointing away now
52 CPPUNIT_ASSERT_MESSAGE(
53 "ray pointing away from box still intersects",
54 !Intersection(ray, box, distance)
57 // 45 deg down from 4 units away, so should be about 4 * sqrt(2)
58 ray.orig = { -5.0f, 4.5f, 0.0f };
59 ray.dir = { 0.70710678118654752440f, -0.70710678118654752440f, 0.0f };
61 CPPUNIT_ASSERT_MESSAGE(
62 "ray pointing at box doesn't intersect",
63 Intersection(ray, box, distance)
65 CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
66 "intersection distance way off",
67 5.65685424949238019520f, distance, delta
71 void IntersectionTest::testRayBoxIntersection() {
72 Ray ray{ { 0, 0, 0 }, { 1, 0, 0 }, { } }; // at origin, pointing right
73 AABB box{ { -1, -1, -1 }, { 1, 1, 1 } }; // 2x2x2 cube centered around origin
74 glm::mat4 M(1); // no transformation
76 const float delta = std::numeric_limits<float>::epsilon();
81 CPPUNIT_ASSERT_MESSAGE(
82 "ray at origin not intersecting box at origin",
83 Intersection(ray, box, M, &distance)
85 // normal undefined, so can't test
87 // move ray outside the box, but have it still point at it
88 // should be 4 units to the left now
90 CPPUNIT_ASSERT_MESSAGE(
91 "ray pointing at box to the right doesn't intersect",
92 Intersection(ray, box, M, &distance, &normal)
94 CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
95 "intersection distance way off",
98 CPPUNIT_ASSERT_EQUAL_MESSAGE(
99 "wrong surface normal at intersection point",
100 glm::vec3(-1, 0, 0), normal
103 // move ray to the other side, so it's pointing away now
105 CPPUNIT_ASSERT_MESSAGE(
106 "ray pointing away from box to the left still intersects",
107 !Intersection(ray, box, M)
112 CPPUNIT_ASSERT_MESSAGE(
113 "ray pointing at box to the left does not intersect",
114 Intersection(ray, box, M, &distance, &normal)
116 CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
117 "intersection distance way off",
118 4.0f, distance, delta
120 CPPUNIT_ASSERT_EQUAL_MESSAGE(
121 "wrong surface normal at intersection point",
122 glm::vec3(1, 0, 0), normal
126 ray.orig = { 0, -5, 0 };
127 ray.dir = { 0, 1, 0 };
128 CPPUNIT_ASSERT_MESSAGE(
129 "ray pointing at box above does not intersect",
130 Intersection(ray, box, M, &distance, &normal)
132 CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
133 "intersection distance way off",
134 4.0f, distance, delta
136 CPPUNIT_ASSERT_EQUAL_MESSAGE(
137 "wrong surface normal at intersection point",
138 glm::vec3(0, -1, 0), normal
143 CPPUNIT_ASSERT_MESSAGE(
144 "ray pointing away from box above still intersects",
145 !Intersection(ray, box, M)
150 CPPUNIT_ASSERT_MESSAGE(
151 "ray pointing at box below does not intersect",
152 Intersection(ray, box, M, &distance, &normal)
154 CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
155 "intersection distance way off",
156 4.0f, distance, delta
158 CPPUNIT_ASSERT_EQUAL_MESSAGE(
159 "wrong surface normal at intersection point",
160 glm::vec3(0, 1, 0), normal
164 ray.orig = { 0, 0, -5 };
165 ray.dir = { 0, 0, 1 };
166 CPPUNIT_ASSERT_MESSAGE(
167 "ray pointing at box in front does not intersect",
168 Intersection(ray, box, M, &distance, &normal)
170 CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
171 "intersection distance way off",
172 4.0f, distance, delta
174 CPPUNIT_ASSERT_EQUAL_MESSAGE(
175 "wrong surface normal at intersection point",
176 glm::vec3(0, 0, -1), normal
181 CPPUNIT_ASSERT_MESSAGE(
182 "ray pointing away from box in front still intersects",
183 !Intersection(ray, box, M)
188 CPPUNIT_ASSERT_MESSAGE(
189 "ray pointing at box behind does not intersect",
190 Intersection(ray, box, M, &distance, &normal)
192 CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
193 "intersection distance way off",
194 4.0f, distance, delta
196 CPPUNIT_ASSERT_EQUAL_MESSAGE(
197 "wrong surface normal at intersection point",
198 glm::vec3(0, 0, 1), normal
201 // 45 deg down from 4 units away, so should be about 4 * sqrt(2)
202 ray.orig = { -5.0f, 4.5f, 0.0f };
203 ray.dir = { 0.70710678118654752440f, -0.70710678118654752440f, 0.0f };
204 CPPUNIT_ASSERT_MESSAGE(
205 "ray pointing at box doesn't intersect",
206 Intersection(ray, box, M, &distance, &normal)
208 CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
209 "intersection distance way off",
210 5.65685424949238019520f, distance, delta
212 CPPUNIT_ASSERT_EQUAL_MESSAGE(
213 "wrong surface normal at intersection point",
214 glm::vec3(-1, 0, 0), normal
218 void IntersectionTest::testBoxBoxIntersection() {
219 const float delta = std::numeric_limits<float>::epsilon();
223 AABB box{ { -1, -1, -1 }, { 1, 1, 1 } }; // 2x2x2 cube centered around origin
224 glm::mat4 Ma(1); // identity
225 glm::mat4 Mb(1); // identity
226 // they're identical, so should probably intersect ^^
228 CPPUNIT_ASSERT_MESSAGE(
229 "identical OBBs don't intersect",
230 Intersection(box, Ma, box, Mb, depth, normal)
232 // depth is two, but normal can be any
233 // (will probably be the first axis of box a, but any is valid)
234 CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
235 "penetration depth of coincidental 2x2x2 boxes is not 2",
239 Ma = glm::translate(glm::vec3(-2, 0, 0)); // 2 to the left
240 Mb = glm::translate(glm::vec3(2, 0, 0)); // 2 to the right
241 CPPUNIT_ASSERT_MESSAGE(
242 "distant OBBs intersect (2 apart, no rotation)",
243 !Intersection(box, Ma, box, Mb, depth, normal)
245 // depth and normal undefined for non-intersecting objects
247 Ma = glm::rotate(PI_0p25, glm::vec3(0, 0, 1)); // rotated 45° around Z
248 Mb = glm::translate(glm::vec3(2.4, 0, 0)); // 2.4 to the right
249 // they should barely touch. intersect by about sqrt(2) - 1.4 if my head works
250 CPPUNIT_ASSERT_MESSAGE(
251 "OBBs don't intersect (one rotated by 45°)",
252 Intersection(box, Ma, box, Mb, depth, normal)
254 CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
255 "bad penetration depth (with rotation)",
256 0.01421356237309504880f, depth, delta
258 CPPUNIT_ASSERT_EQUAL_MESSAGE(
259 "bad intersection normal (with rotation)",
260 glm::vec3(1, 0, 0), glm::abs(normal) // normal can be in + or - x, therefore abs()
263 Mb = glm::translate(glm::vec3(3, 0, 0)); // 3 to the right
264 CPPUNIT_ASSERT_MESSAGE(
265 "OBBs intersect (one rotated by 45°)",
266 !Intersection(box, Ma, box, Mb, depth, normal)