]> git.localhorst.tv Git - blobs.git/blob - tst/math/IntersectTest.cpp
hooray for könig lookup
[blobs.git] / tst / math / IntersectTest.cpp
1 #include "IntersectTest.hpp"
2
3 #include "../assert.hpp"
4
5 #include "math/const.hpp"
6 #include "math/geometry.hpp"
7
8 #include <limits>
9 #include <glm/gtx/transform.hpp>
10
11 CPPUNIT_TEST_SUITE_REGISTRATION(blobs::math::test::IntersectTest);
12
13 using blobs::test::AssertEqual;
14
15
16 namespace blobs {
17 namespace math {
18 namespace test {
19
20 void IntersectTest::setUp() {
21 }
22
23 void IntersectTest::tearDown() {
24 }
25
26
27 void IntersectTest::testRayBoxIntersection() {
28         Ray ray{ { 0, 0, 0 }, { 1, 0, 0 } }; // at origin, pointing right
29         AABB box{ { -1, -1, -1 }, { 1, 1, 1 } }; // 2x2x2 cube centered around origin
30         glm::dmat4 M(1); // no transformation
31
32         const double delta = 1.0e-15;
33
34         double distance = 0;
35         glm::dvec3 normal(0);
36
37         CPPUNIT_ASSERT_MESSAGE(
38                 "ray at origin not intersecting box at origin",
39                 Intersect(ray, box, M, normal, distance)
40         );
41         // normal undefined, so can't test
42
43         // move ray outside the box, but have it still point at it
44         // should be 4 units to the left now
45         ray.Origin({ -5, 0, 0 });
46         CPPUNIT_ASSERT_MESSAGE(
47                 "ray pointing at box to the right doesn't intersect",
48                 Intersect(ray, box, M, normal, distance)
49         );
50         CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
51                 "intersection distance way off",
52                 4.0, distance, delta
53         );
54         AssertEqual(
55                 "wrong surface normal at intersection point",
56                 glm::dvec3(-1, 0, 0), normal
57         );
58
59         // move ray to the other side, so it's pointing away now
60         ray.Origin({ 5, 0, 0 });
61         CPPUNIT_ASSERT_MESSAGE(
62                 "ray pointing away from box to the left still intersects",
63                 !Intersect(ray, box, M, normal, distance)
64         );
65
66         // turn ray around
67         ray.Direction({ -1, 0, 0 });
68         CPPUNIT_ASSERT_MESSAGE(
69                 "ray pointing at box to the left does not intersect",
70                 Intersect(ray, box, M, normal, distance)
71         );
72         CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
73                 "intersection distance way off",
74                 4.0, distance, delta
75         );
76         AssertEqual(
77                 "wrong surface normal at intersection point",
78                 glm::dvec3(1, 0, 0), normal
79         );
80
81         // ray below
82         ray.Origin({ 0, -5, 0 });
83         ray.Direction({ 0, 1, 0 });
84         CPPUNIT_ASSERT_MESSAGE(
85                 "ray pointing at box above does not intersect",
86                 Intersect(ray, box, M, normal, distance)
87         );
88         CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
89                 "intersection distance way off",
90                 4.0, distance, delta
91         );
92         AssertEqual(
93                 "wrong surface normal at intersection point",
94                 glm::dvec3(0, -1, 0), normal
95         );
96
97         // turn ray around
98         ray.Direction({ 0, -1, 0 });
99         CPPUNIT_ASSERT_MESSAGE(
100                 "ray pointing away from box above still intersects",
101                 !Intersect(ray, box, M, normal, distance)
102         );
103
104         // move ray above
105         ray.Origin({ 0, 5, 0 });
106         CPPUNIT_ASSERT_MESSAGE(
107                 "ray pointing at box below does not intersect",
108                 Intersect(ray, box, M, normal, distance)
109         );
110         CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
111                 "intersection distance way off",
112                 4.0, distance, delta
113         );
114         AssertEqual(
115                 "wrong surface normal at intersection point",
116                 glm::dvec3(0, 1, 0), normal
117         );
118
119         // ray behind
120         ray.Origin({ 0, 0, -5 });
121         ray.Direction({ 0, 0, 1 });
122         CPPUNIT_ASSERT_MESSAGE(
123                 "ray pointing at box in front does not intersect",
124                 Intersect(ray, box, M, normal, distance)
125         );
126         CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
127                 "intersection distance way off",
128                 4.0, distance, delta
129         );
130         AssertEqual(
131                 "wrong surface normal at intersection point",
132                 glm::dvec3(0, 0, -1), normal
133         );
134
135         // turn ray around
136         ray.Direction({ 0, 0, -1 });
137         CPPUNIT_ASSERT_MESSAGE(
138                 "ray pointing away from box in front still intersects",
139                 !Intersect(ray, box, M, normal, distance)
140         );
141
142         // move ray in front
143         ray.Origin({ 0, 0, 5 });
144         CPPUNIT_ASSERT_MESSAGE(
145                 "ray pointing at box behind does not intersect",
146                 Intersect(ray, box, M, normal, distance)
147         );
148         CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
149                 "intersection distance way off",
150                 4.0, distance, delta
151         );
152         AssertEqual(
153                 "wrong surface normal at intersection point",
154                 glm::dvec3(0, 0, 1), normal
155         );
156
157         // 45 deg down from 4 units away, so should be about 4 * sqrt(2)
158         ray.Origin({ -5, 4.5, 0 });
159         ray.Direction({ 0.70710678118654752440, -0.70710678118654752440, 0 });
160         CPPUNIT_ASSERT_MESSAGE(
161                 "ray pointing at box doesn't intersect",
162                 Intersect(ray, box, M, normal, distance)
163         );
164         CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
165                 "intersection distance way off",
166                 5.65685424949238019520, distance, delta
167         );
168         AssertEqual(
169                 "wrong surface normal at intersection point",
170                 glm::dvec3(-1, 0, 0), normal
171         );
172 }
173
174 void IntersectTest::testBoxBoxIntersection() {
175         const double delta = std::numeric_limits<double>::epsilon();
176         double depth = 0;
177         glm::dvec3 normal(0);
178
179         AABB box{ { -1, -1, -1 }, { 1, 1, 1 } }; // 2x2x2 cube centered around origin
180         glm::dmat4 Ma(1); // identity
181         glm::dmat4 Mb(1); // identity
182         // they're identical, so should probably intersect ^^
183
184         CPPUNIT_ASSERT_MESSAGE(
185                 "identical OBBs don't intersect",
186                 Intersect(box, Ma, box, Mb, normal, depth)
187         );
188         // depth is two, but normal can be any
189         // (will probably be the first axis of box a, but any is valid)
190         CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
191                 "penetration depth of coincidental 2x2x2 boxes is not 2",
192                 2.0, depth, delta
193         );
194
195         Ma = glm::translate(glm::dvec3(-2, 0, 0)); // 2 to the left
196         Mb = glm::translate(glm::dvec3(2, 0, 0)); // 2 to the right
197         CPPUNIT_ASSERT_MESSAGE(
198                 "distant OBBs intersect (2 apart, no rotation)",
199                 !Intersect(box, Ma, box, Mb, normal, depth)
200         );
201         // depth and normal undefined for non-intersecting objects
202
203         Ma = glm::rotate(PI * 0.25, glm::dvec3(0, 0, 1)); // rotated 45° around Z
204         Mb = glm::translate(glm::dvec3(2.4, 0, 0)); // 2.4 to the right
205         // they should barely touch. intersect by about sqrt(2) - 1.4 if my head works
206         CPPUNIT_ASSERT_MESSAGE(
207                 "OBBs don't intersect (one rotated by 45°)",
208                 Intersect(box, Ma, box, Mb, normal, depth)
209         );
210         CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
211                 "bad penetration depth (with rotation)",
212                 0.014213562373095, depth, delta
213         );
214         AssertEqual(
215                 "bad intersection normal (with rotation)",
216                 glm::dvec3(1, 0, 0), glm::abs(normal) // normal can be in + or - x, therefore abs()
217         );
218
219         Mb = glm::translate(glm::dvec3(3, 0, 0)); // 3 to the right
220         CPPUNIT_ASSERT_MESSAGE(
221                 "OBBs intersect (one rotated by 45°)",
222                 !Intersect(box, Ma, box, Mb, normal, depth)
223         );
224 }
225
226 }
227 }
228 }