Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/tests/core/math/test_aabb.h
10278 views
1
/**************************************************************************/
2
/* test_aabb.h */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10
/* */
11
/* Permission is hereby granted, free of charge, to any person obtaining */
12
/* a copy of this software and associated documentation files (the */
13
/* "Software"), to deal in the Software without restriction, including */
14
/* without limitation the rights to use, copy, modify, merge, publish, */
15
/* distribute, sublicense, and/or sell copies of the Software, and to */
16
/* permit persons to whom the Software is furnished to do so, subject to */
17
/* the following conditions: */
18
/* */
19
/* The above copyright notice and this permission notice shall be */
20
/* included in all copies or substantial portions of the Software. */
21
/* */
22
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29
/**************************************************************************/
30
31
#pragma once
32
33
#include "core/math/aabb.h"
34
35
#include "tests/test_macros.h"
36
37
namespace TestAABB {
38
39
TEST_CASE("[AABB] Constructor methods") {
40
constexpr AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
41
constexpr AABB aabb_copy = AABB(aabb);
42
43
CHECK_MESSAGE(
44
aabb == aabb_copy,
45
"AABBs created with the same dimensions but by different methods should be equal.");
46
}
47
48
TEST_CASE("[AABB] String conversion") {
49
CHECK_MESSAGE(
50
String(AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6))) == "[P: (-1.5, 2.0, -2.5), S: (4.0, 5.0, 6.0)]",
51
"The string representation should match the expected value.");
52
}
53
54
TEST_CASE("[AABB] Basic getters") {
55
constexpr AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
56
CHECK_MESSAGE(
57
aabb.get_position().is_equal_approx(Vector3(-1.5, 2, -2.5)),
58
"get_position() should return the expected value.");
59
CHECK_MESSAGE(
60
aabb.get_size().is_equal_approx(Vector3(4, 5, 6)),
61
"get_size() should return the expected value.");
62
CHECK_MESSAGE(
63
aabb.get_end().is_equal_approx(Vector3(2.5, 7, 3.5)),
64
"get_end() should return the expected value.");
65
CHECK_MESSAGE(
66
aabb.get_center().is_equal_approx(Vector3(0.5, 4.5, 0.5)),
67
"get_center() should return the expected value.");
68
}
69
70
TEST_CASE("[AABB] Basic setters") {
71
AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
72
aabb.set_end(Vector3(100, 0, 100));
73
CHECK_MESSAGE(
74
aabb.is_equal_approx(AABB(Vector3(-1.5, 2, -2.5), Vector3(101.5, -2, 102.5))),
75
"set_end() should result in the expected AABB.");
76
77
aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
78
aabb.set_position(Vector3(-1000, -2000, -3000));
79
CHECK_MESSAGE(
80
aabb.is_equal_approx(AABB(Vector3(-1000, -2000, -3000), Vector3(4, 5, 6))),
81
"set_position() should result in the expected AABB.");
82
83
aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
84
aabb.set_size(Vector3(0, 0, -50));
85
CHECK_MESSAGE(
86
aabb.is_equal_approx(AABB(Vector3(-1.5, 2, -2.5), Vector3(0, 0, -50))),
87
"set_size() should result in the expected AABB.");
88
}
89
90
TEST_CASE("[AABB] Volume getters") {
91
AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
92
CHECK_MESSAGE(
93
aabb.get_volume() == doctest::Approx(120),
94
"get_volume() should return the expected value with positive size.");
95
CHECK_MESSAGE(
96
aabb.has_volume(),
97
"Non-empty volumetric AABB should have a volume.");
98
99
aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(-4, 5, 6));
100
CHECK_MESSAGE(
101
aabb.get_volume() == doctest::Approx(-120),
102
"get_volume() should return the expected value with negative size (1 component).");
103
104
aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(-4, -5, 6));
105
CHECK_MESSAGE(
106
aabb.get_volume() == doctest::Approx(120),
107
"get_volume() should return the expected value with negative size (2 components).");
108
109
aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(-4, -5, -6));
110
CHECK_MESSAGE(
111
aabb.get_volume() == doctest::Approx(-120),
112
"get_volume() should return the expected value with negative size (3 components).");
113
114
aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 0, 6));
115
CHECK_MESSAGE(
116
!aabb.has_volume(),
117
"Non-empty flat AABB should not have a volume.");
118
119
CHECK_MESSAGE(
120
!AABB().has_volume(),
121
"Empty AABB should not have a volume.");
122
}
123
124
TEST_CASE("[AABB] Surface getters") {
125
AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
126
CHECK_MESSAGE(
127
aabb.has_surface(),
128
"Non-empty volumetric AABB should have an surface.");
129
130
aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 0, 6));
131
CHECK_MESSAGE(
132
aabb.has_surface(),
133
"Non-empty flat AABB should have a surface.");
134
135
aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 0, 0));
136
CHECK_MESSAGE(
137
aabb.has_surface(),
138
"Non-empty linear AABB should have a surface.");
139
140
CHECK_MESSAGE(
141
!AABB().has_surface(),
142
"Empty AABB should not have an surface.");
143
}
144
145
TEST_CASE("[AABB] Intersection") {
146
constexpr AABB aabb_big = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
147
148
AABB aabb_small = AABB(Vector3(-1.5, 2, -2.5), Vector3(1, 1, 1));
149
CHECK_MESSAGE(
150
aabb_big.intersects(aabb_small),
151
"intersects() with fully contained AABB (touching the edge) should return the expected result.");
152
153
aabb_small = AABB(Vector3(0.5, 1.5, -2), Vector3(1, 1, 1));
154
CHECK_MESSAGE(
155
aabb_big.intersects(aabb_small),
156
"intersects() with partially contained AABB (overflowing on Y axis) should return the expected result.");
157
158
aabb_small = AABB(Vector3(10, -10, -10), Vector3(1, 1, 1));
159
CHECK_MESSAGE(
160
!aabb_big.intersects(aabb_small),
161
"intersects() with non-contained AABB should return the expected result.");
162
163
aabb_small = AABB(Vector3(-1.5, 2, -2.5), Vector3(1, 1, 1));
164
CHECK_MESSAGE(
165
aabb_big.intersection(aabb_small).is_equal_approx(aabb_small),
166
"intersection() with fully contained AABB (touching the edge) should return the expected result.");
167
168
aabb_small = AABB(Vector3(0.5, 1.5, -2), Vector3(1, 1, 1));
169
CHECK_MESSAGE(
170
aabb_big.intersection(aabb_small).is_equal_approx(AABB(Vector3(0.5, 2, -2), Vector3(1, 0.5, 1))),
171
"intersection() with partially contained AABB (overflowing on Y axis) should return the expected result.");
172
173
aabb_small = AABB(Vector3(10, -10, -10), Vector3(1, 1, 1));
174
CHECK_MESSAGE(
175
aabb_big.intersection(aabb_small).is_equal_approx(AABB()),
176
"intersection() with non-contained AABB should return the expected result.");
177
178
CHECK_MESSAGE(
179
aabb_big.intersects_plane(Plane(Vector3(0, 1, 0), 4)),
180
"intersects_plane() should return the expected result.");
181
CHECK_MESSAGE(
182
aabb_big.intersects_plane(Plane(Vector3(0, -1, 0), -4)),
183
"intersects_plane() should return the expected result.");
184
CHECK_MESSAGE(
185
!aabb_big.intersects_plane(Plane(Vector3(0, 1, 0), 200)),
186
"intersects_plane() should return the expected result.");
187
188
CHECK_MESSAGE(
189
aabb_big.intersects_segment(Vector3(1, 3, 0), Vector3(0, 3, 0)),
190
"intersects_segment() should return the expected result.");
191
CHECK_MESSAGE(
192
aabb_big.intersects_segment(Vector3(0, 3, 0), Vector3(0, -300, 0)),
193
"intersects_segment() should return the expected result.");
194
CHECK_MESSAGE(
195
aabb_big.intersects_segment(Vector3(-50, 3, -50), Vector3(50, 3, 50)),
196
"intersects_segment() should return the expected result.");
197
CHECK_MESSAGE(
198
!aabb_big.intersects_segment(Vector3(-50, 25, -50), Vector3(50, 25, 50)),
199
"intersects_segment() should return the expected result.");
200
CHECK_MESSAGE(
201
aabb_big.intersects_segment(Vector3(0, 3, 0), Vector3(0, 3, 0)),
202
"intersects_segment() should return the expected result with segment of length 0.");
203
CHECK_MESSAGE(
204
!aabb_big.intersects_segment(Vector3(0, 300, 0), Vector3(0, 300, 0)),
205
"intersects_segment() should return the expected result with segment of length 0.");
206
CHECK_MESSAGE( // Simple ray intersection test.
207
aabb_big.intersects_ray(Vector3(-100, 3, 0), Vector3(1, 0, 0)),
208
"intersects_ray() should return true when ray points directly to AABB from outside.");
209
CHECK_MESSAGE( // Ray parallel to an edge.
210
!aabb_big.intersects_ray(Vector3(10, 10, 0), Vector3(0, 1, 0)),
211
"intersects_ray() should return false for ray parallel and outside of AABB.");
212
CHECK_MESSAGE( // Ray origin inside aabb.
213
aabb_big.intersects_ray(Vector3(1, 1, 1), Vector3(0, 1, 0)),
214
"intersects_ray() should return true for rays originating inside the AABB.");
215
CHECK_MESSAGE( // Ray pointing away from aabb.
216
!aabb_big.intersects_ray(Vector3(-10, 0, 0), Vector3(-1, 0, 0)),
217
"intersects_ray() should return false when ray points away from AABB.");
218
CHECK_MESSAGE( // Ray along a diagonal of aabb.
219
aabb_big.intersects_ray(Vector3(0, 0, 0), Vector3(1, 1, 1)),
220
"intersects_ray() should return true for rays along the AABB diagonal.");
221
CHECK_MESSAGE( // Ray originating at aabb edge.
222
aabb_big.intersects_ray(aabb_big.position, Vector3(-1, 0, 0)),
223
"intersects_ray() should return true for rays starting on AABB's edge.");
224
CHECK_MESSAGE( // Ray with zero direction inside.
225
aabb_big.intersects_ray(Vector3(-1, 3, -2), Vector3(0, 0, 0)),
226
"intersects_ray() should return true because its inside.");
227
CHECK_MESSAGE( // Ray with zero direction outside.
228
!aabb_big.intersects_ray(Vector3(-1000, 3, -2), Vector3(0, 0, 0)),
229
"intersects_ray() should return false for being outside.");
230
231
// Finding ray intersections.
232
constexpr AABB aabb_simple = AABB(Vector3(), Vector3(1, 1, 1));
233
bool inside = false;
234
Vector3 intersection_point;
235
Vector3 intersection_normal;
236
237
// Borders.
238
aabb_simple.find_intersects_ray(Vector3(0.5, 0, 0.5), Vector3(0, 1, 0), inside, &intersection_point, &intersection_normal);
239
CHECK_MESSAGE(inside == false, "find_intersects_ray() should return outside on borders.");
240
CHECK_MESSAGE(intersection_point.is_equal_approx(Vector3(0.5, 0, 0.5)), "find_intersects_ray() border intersection point incorrect.");
241
CHECK_MESSAGE(intersection_normal.is_equal_approx(Vector3(0, -1, 0)), "find_intersects_ray() border intersection normal incorrect.");
242
aabb_simple.find_intersects_ray(Vector3(0.5, 1, 0.5), Vector3(0, -1, 0), inside, &intersection_point, &intersection_normal);
243
CHECK_MESSAGE(inside == false, "find_intersects_ray() should return outside on borders.");
244
CHECK_MESSAGE(intersection_point.is_equal_approx(Vector3(0.5, 1, 0.5)), "find_intersects_ray() border intersection point incorrect.");
245
CHECK_MESSAGE(intersection_normal.is_equal_approx(Vector3(0, 1, 0)), "find_intersects_ray() border intersection normal incorrect.");
246
247
// Inside.
248
aabb_simple.find_intersects_ray(Vector3(0.5, 0.1, 0.5), Vector3(0, 1, 0), inside, &intersection_point, &intersection_normal);
249
CHECK_MESSAGE(inside == true, "find_intersects_ray() should return inside when inside.");
250
CHECK_MESSAGE(intersection_point.is_equal_approx(Vector3(0.5, 0, 0.5)), "find_intersects_ray() inside backtracking intersection point incorrect.");
251
CHECK_MESSAGE(intersection_normal.is_equal_approx(Vector3(0, -1, 0)), "find_intersects_ray() inside intersection normal incorrect.");
252
253
// Zero sized AABB.
254
constexpr AABB aabb_zero = AABB(Vector3(), Vector3(1, 0, 1));
255
aabb_zero.find_intersects_ray(Vector3(0.5, 0, 0.5), Vector3(0, 1, 0), inside, &intersection_point, &intersection_normal);
256
CHECK_MESSAGE(inside == false, "find_intersects_ray() should return outside on borders of zero sized AABB.");
257
CHECK_MESSAGE(intersection_point.is_equal_approx(Vector3(0.5, 0, 0.5)), "find_intersects_ray() border intersection point incorrect for zero sized AABB.");
258
CHECK_MESSAGE(intersection_normal.is_equal_approx(Vector3(0, -1, 0)), "find_intersects_ray() border intersection normal incorrect for zero sized AABB.");
259
aabb_zero.find_intersects_ray(Vector3(0.5, 0, 0.5), Vector3(0, -1, 0), inside, &intersection_point, &intersection_normal);
260
CHECK_MESSAGE(inside == false, "find_intersects_ray() should return outside on borders of zero sized AABB.");
261
CHECK_MESSAGE(intersection_point.is_equal_approx(Vector3(0.5, 0, 0.5)), "find_intersects_ray() border intersection point incorrect for zero sized AABB.");
262
CHECK_MESSAGE(intersection_normal.is_equal_approx(Vector3(0, 1, 0)), "find_intersects_ray() border intersection normal incorrect for zero sized AABB.");
263
aabb_zero.find_intersects_ray(Vector3(0.5, -1, 0.5), Vector3(0, 1, 0), inside, &intersection_point, &intersection_normal);
264
CHECK_MESSAGE(inside == false, "find_intersects_ray() should return outside on borders of zero sized AABB.");
265
CHECK_MESSAGE(intersection_point.is_equal_approx(Vector3(0.5, 0, 0.5)), "find_intersects_ray() border intersection point incorrect for zero sized AABB.");
266
CHECK_MESSAGE(intersection_normal.is_equal_approx(Vector3(0, -1, 0)), "find_intersects_ray() border intersection normal incorrect for zero sized AABB.");
267
}
268
269
TEST_CASE("[AABB] Merging") {
270
constexpr AABB aabb_big = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
271
272
AABB aabb_small = AABB(Vector3(-1.5, 2, -2.5), Vector3(1, 1, 1));
273
CHECK_MESSAGE(
274
aabb_big.merge(aabb_small).is_equal_approx(aabb_big),
275
"merge() with fully contained AABB (touching the edge) should return the expected result.");
276
277
aabb_small = AABB(Vector3(0.5, 1.5, -2), Vector3(1, 1, 1));
278
CHECK_MESSAGE(
279
aabb_big.merge(aabb_small).is_equal_approx(AABB(Vector3(-1.5, 1.5, -2.5), Vector3(4, 5.5, 6))),
280
"merge() with partially contained AABB (overflowing on Y axis) should return the expected result.");
281
282
aabb_small = AABB(Vector3(10, -10, -10), Vector3(1, 1, 1));
283
CHECK_MESSAGE(
284
aabb_big.merge(aabb_small).is_equal_approx(AABB(Vector3(-1.5, -10, -10), Vector3(12.5, 17, 13.5))),
285
"merge() with non-contained AABB should return the expected result.");
286
}
287
288
TEST_CASE("[AABB] Encloses") {
289
constexpr AABB aabb_big = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
290
291
CHECK_MESSAGE(
292
aabb_big.encloses(aabb_big),
293
"encloses() with itself should return the expected result.");
294
295
AABB aabb_small = AABB(Vector3(-1.5, 2, -2.5), Vector3(1, 1, 1));
296
CHECK_MESSAGE(
297
aabb_big.encloses(aabb_small),
298
"encloses() with fully contained AABB (touching the edge) should return the expected result.");
299
300
aabb_small = AABB(Vector3(1.5, 6, 2.5), Vector3(1, 1, 1));
301
CHECK_MESSAGE(
302
aabb_big.encloses(aabb_small),
303
"encloses() with fully contained AABB (touching the edge) should return the expected result.");
304
305
aabb_small = AABB(Vector3(0.5, 1.5, -2), Vector3(1, 1, 1));
306
CHECK_MESSAGE(
307
!aabb_big.encloses(aabb_small),
308
"encloses() with partially contained AABB (overflowing on Y axis) should return the expected result.");
309
310
aabb_small = AABB(Vector3(10, -10, -10), Vector3(1, 1, 1));
311
CHECK_MESSAGE(
312
!aabb_big.encloses(aabb_small),
313
"encloses() with non-contained AABB should return the expected result.");
314
}
315
316
TEST_CASE("[AABB] Get endpoints") {
317
constexpr AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
318
CHECK_MESSAGE(
319
aabb.get_endpoint(0).is_equal_approx(Vector3(-1.5, 2, -2.5)),
320
"The endpoint at index 0 should match the expected value.");
321
CHECK_MESSAGE(
322
aabb.get_endpoint(1).is_equal_approx(Vector3(-1.5, 2, 3.5)),
323
"The endpoint at index 1 should match the expected value.");
324
CHECK_MESSAGE(
325
aabb.get_endpoint(2).is_equal_approx(Vector3(-1.5, 7, -2.5)),
326
"The endpoint at index 2 should match the expected value.");
327
CHECK_MESSAGE(
328
aabb.get_endpoint(3).is_equal_approx(Vector3(-1.5, 7, 3.5)),
329
"The endpoint at index 3 should match the expected value.");
330
CHECK_MESSAGE(
331
aabb.get_endpoint(4).is_equal_approx(Vector3(2.5, 2, -2.5)),
332
"The endpoint at index 4 should match the expected value.");
333
CHECK_MESSAGE(
334
aabb.get_endpoint(5).is_equal_approx(Vector3(2.5, 2, 3.5)),
335
"The endpoint at index 5 should match the expected value.");
336
CHECK_MESSAGE(
337
aabb.get_endpoint(6).is_equal_approx(Vector3(2.5, 7, -2.5)),
338
"The endpoint at index 6 should match the expected value.");
339
CHECK_MESSAGE(
340
aabb.get_endpoint(7).is_equal_approx(Vector3(2.5, 7, 3.5)),
341
"The endpoint at index 7 should match the expected value.");
342
343
ERR_PRINT_OFF;
344
CHECK_MESSAGE(
345
aabb.get_endpoint(8).is_equal_approx(Vector3()),
346
"The endpoint at invalid index 8 should match the expected value.");
347
CHECK_MESSAGE(
348
aabb.get_endpoint(-1).is_equal_approx(Vector3()),
349
"The endpoint at invalid index -1 should match the expected value.");
350
ERR_PRINT_ON;
351
}
352
353
TEST_CASE("[AABB] Get longest/shortest axis") {
354
constexpr AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
355
CHECK_MESSAGE(
356
aabb.get_longest_axis() == Vector3(0, 0, 1),
357
"get_longest_axis() should return the expected value.");
358
CHECK_MESSAGE(
359
aabb.get_longest_axis_index() == Vector3::AXIS_Z,
360
"get_longest_axis_index() should return the expected value.");
361
CHECK_MESSAGE(
362
aabb.get_longest_axis_size() == 6,
363
"get_longest_axis_size() should return the expected value.");
364
365
CHECK_MESSAGE(
366
aabb.get_shortest_axis() == Vector3(1, 0, 0),
367
"get_shortest_axis() should return the expected value.");
368
CHECK_MESSAGE(
369
aabb.get_shortest_axis_index() == Vector3::AXIS_X,
370
"get_shortest_axis_index() should return the expected value.");
371
CHECK_MESSAGE(
372
aabb.get_shortest_axis_size() == 4,
373
"get_shortest_axis_size() should return the expected value.");
374
}
375
376
TEST_CASE("[AABB] Get support") {
377
constexpr AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
378
CHECK_MESSAGE(
379
aabb.get_support(Vector3(1, 0, 0)) == Vector3(2.5, 2, -2.5),
380
"get_support() should return the expected value.");
381
CHECK_MESSAGE(
382
aabb.get_support(Vector3(0.5, 1, 1)) == Vector3(2.5, 7, 3.5),
383
"get_support() should return the expected value.");
384
CHECK_MESSAGE(
385
aabb.get_support(Vector3(0.5, 1, -400)) == Vector3(2.5, 7, -2.5),
386
"get_support() should return the expected value.");
387
CHECK_MESSAGE(
388
aabb.get_support(Vector3(0, -1, 0)) == Vector3(-1.5, 2, -2.5),
389
"get_support() should return the expected value.");
390
CHECK_MESSAGE(
391
aabb.get_support(Vector3(0, -0.1, 0)) == Vector3(-1.5, 2, -2.5),
392
"get_support() should return the expected value.");
393
CHECK_MESSAGE(
394
aabb.get_support(Vector3()) == Vector3(-1.5, 2, -2.5),
395
"get_support() should return the AABB position when given a zero vector.");
396
}
397
398
TEST_CASE("[AABB] Grow") {
399
constexpr AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
400
CHECK_MESSAGE(
401
aabb.grow(0.25).is_equal_approx(AABB(Vector3(-1.75, 1.75, -2.75), Vector3(4.5, 5.5, 6.5))),
402
"grow() with positive value should return the expected AABB.");
403
CHECK_MESSAGE(
404
aabb.grow(-0.25).is_equal_approx(AABB(Vector3(-1.25, 2.25, -2.25), Vector3(3.5, 4.5, 5.5))),
405
"grow() with negative value should return the expected AABB.");
406
CHECK_MESSAGE(
407
aabb.grow(-10).is_equal_approx(AABB(Vector3(8.5, 12, 7.5), Vector3(-16, -15, -14))),
408
"grow() with large negative value should return the expected AABB.");
409
}
410
411
TEST_CASE("[AABB] Has point") {
412
constexpr AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
413
CHECK_MESSAGE(
414
aabb.has_point(Vector3(-1, 3, 0)),
415
"has_point() with contained point should return the expected value.");
416
CHECK_MESSAGE(
417
aabb.has_point(Vector3(2, 3, 0)),
418
"has_point() with contained point should return the expected value.");
419
CHECK_MESSAGE(
420
!aabb.has_point(Vector3(-20, 0, 0)),
421
"has_point() with non-contained point should return the expected value.");
422
423
CHECK_MESSAGE(
424
aabb.has_point(Vector3(-1.5, 3, 0)),
425
"has_point() with positive size should include point on near face (X axis).");
426
CHECK_MESSAGE(
427
aabb.has_point(Vector3(2.5, 3, 0)),
428
"has_point() with positive size should include point on far face (X axis).");
429
CHECK_MESSAGE(
430
aabb.has_point(Vector3(0, 2, 0)),
431
"has_point() with positive size should include point on near face (Y axis).");
432
CHECK_MESSAGE(
433
aabb.has_point(Vector3(0, 7, 0)),
434
"has_point() with positive size should include point on far face (Y axis).");
435
CHECK_MESSAGE(
436
aabb.has_point(Vector3(0, 3, -2.5)),
437
"has_point() with positive size should include point on near face (Z axis).");
438
CHECK_MESSAGE(
439
aabb.has_point(Vector3(0, 3, 3.5)),
440
"has_point() with positive size should include point on far face (Z axis).");
441
}
442
443
TEST_CASE("[AABB] Expanding") {
444
constexpr AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
445
CHECK_MESSAGE(
446
aabb.expand(Vector3(-1, 3, 0)).is_equal_approx(aabb),
447
"expand() with contained point should return the expected AABB.");
448
CHECK_MESSAGE(
449
aabb.expand(Vector3(2, 3, 0)).is_equal_approx(aabb),
450
"expand() with contained point should return the expected AABB.");
451
CHECK_MESSAGE(
452
aabb.expand(Vector3(-1.5, 3, 0)).is_equal_approx(aabb),
453
"expand() with contained point on negative edge should return the expected AABB.");
454
CHECK_MESSAGE(
455
aabb.expand(Vector3(2.5, 3, 0)).is_equal_approx(aabb),
456
"expand() with contained point on positive edge should return the expected AABB.");
457
CHECK_MESSAGE(
458
aabb.expand(Vector3(-20, 0, 0)).is_equal_approx(AABB(Vector3(-20, 0, -2.5), Vector3(22.5, 7, 6))),
459
"expand() with non-contained point should return the expected AABB.");
460
}
461
462
TEST_CASE("[AABB] Finite number checks") {
463
constexpr Vector3 x(0, 1, 2);
464
constexpr Vector3 infinite(Math::NaN, Math::NaN, Math::NaN);
465
466
CHECK_MESSAGE(
467
AABB(x, x).is_finite(),
468
"AABB with all components finite should be finite");
469
470
CHECK_FALSE_MESSAGE(
471
AABB(infinite, x).is_finite(),
472
"AABB with one component infinite should not be finite.");
473
CHECK_FALSE_MESSAGE(
474
AABB(x, infinite).is_finite(),
475
"AABB with one component infinite should not be finite.");
476
477
CHECK_FALSE_MESSAGE(
478
AABB(infinite, infinite).is_finite(),
479
"AABB with two components infinite should not be finite.");
480
}
481
482
} // namespace TestAABB
483
484