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::testSimpleRayBox() {
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::testRayBox() {
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::testBoxBox() {
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)
270 void IntersectionTest::testSpherePlane() {
271 const float delta = std::numeric_limits<float>::epsilon();
273 // unit sphere at origin
274 Sphere sphere{{ 0.0f, 0.0f, 0.0f }, 1.0f};
275 // horizontal plane at origin (the XZ plane)
276 Plane plane{{ 0.0f, 1.0f, 0.0f }, 0.0f };
280 CPPUNIT_ASSERT_MESSAGE(
281 "sphere at origin does not intersect plane at origin",
282 Intersection(sphere, plane, depth, normal)
284 CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
285 "bad penetration depth of sphere with plane",
288 // normal is actually undefined in this case, but either will work
289 CPPUNIT_ASSERT_MESSAGE(
290 "bad contact normal of sphere intersecting plane",
291 normal == glm::vec3(0.0f, 1.0f, 0.0f) || normal == glm::vec3(0.0f, -1.0f, 0.0f)
294 // center above, but still intersecting
295 sphere.origin.y = 0.5f;
296 CPPUNIT_ASSERT_MESSAGE(
297 "sphere does not intersect plane",
298 Intersection(sphere, plane, depth, normal)
300 CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
301 "bad penetration depth of sphere with plane",
304 CPPUNIT_ASSERT_EQUAL_MESSAGE(
305 "bad contact normal of sphere intersecting plane",
306 glm::vec3(0.0f, 1.0f, 0.0f), normal
309 // center below, but still intersecting
310 sphere.origin.y = -0.5f;
311 CPPUNIT_ASSERT_MESSAGE(
312 "sphere does not intersect plane",
313 Intersection(sphere, plane, depth, normal)
315 CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
316 "bad penetration depth of sphere with plane",
319 CPPUNIT_ASSERT_EQUAL_MESSAGE(
320 "bad contact normal of sphere intersecting plane",
321 glm::vec3(0.0f, -1.0f, 0.0f), normal
324 // sphere completely above
325 sphere.origin.y = 1.5f;
326 CPPUNIT_ASSERT_MESSAGE(
327 "sphere above plane intersects",
328 !Intersection(sphere, plane, depth, normal)
331 // sphere completely below
332 sphere.origin.y = -1.5f;
333 CPPUNIT_ASSERT_MESSAGE(
334 "sphere below plane intersects",
335 !Intersection(sphere, plane, depth, normal)
339 void IntersectionTest::testSphereHalfSpace() {
340 const float delta = std::numeric_limits<float>::epsilon();
342 // unit sphere at origin
343 Sphere sphere{{ 0.0f, 0.0f, 0.0f }, 1.0f};
344 // horizontal plane at origin (the XZ plane)
345 Plane plane{{ 0.0f, 1.0f, 0.0f }, 0.0f };
348 CPPUNIT_ASSERT_MESSAGE(
349 "sphere at origin does not intersect half space to origin",
350 Intersection(sphere, plane, depth)
352 CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
353 "bad penetration depth of sphere with half space",
357 sphere.origin.y = 0.5f;
358 CPPUNIT_ASSERT_MESSAGE(
359 "sphere does not intersect half space",
360 Intersection(sphere, plane, depth)
362 CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
363 "bad penetration depth of sphere with half space",
367 sphere.origin.y = -0.5f;
368 CPPUNIT_ASSERT_MESSAGE(
369 "sphere does not intersect half space",
370 Intersection(sphere, plane, depth)
372 CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
373 "bad penetration depth of sphere with half space",
377 sphere.origin.y = -1.5f;
378 CPPUNIT_ASSERT_MESSAGE(
379 "sphere inside half space does not intersect",
380 Intersection(sphere, plane, depth)
382 CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
383 "bad penetration depth of sphere with half space",
387 sphere.origin.y = 1.5f;
388 CPPUNIT_ASSERT_MESSAGE(
389 "sphere outside half space intersects",
390 !Intersection(sphere, plane, depth)