Unravel Engine C++ Reference
Loading...
Searching...
No Matches
bbox.cpp
Go to the documentation of this file.
1#include "bbox.h"
2#include <limits>
3
4namespace math
5{
6bbox bbox::empty(0, 0, 0, 0, 0, 0);
7
9{
10 // Initialize values
11 reset();
12}
13
14bbox::bbox(const vec3& vecMin, const vec3& vecMax)
15{
16 // Copy vector values
17 min = vecMin;
18 max = vecMax;
19}
20
21bbox::bbox(float xMin, float yMin, float zMin, float xMax, float yMax, float zMax)
22{
23 // Copy coordinate values
24 min = vec3(xMin, yMin, zMin);
25 max = vec3(xMax, yMax, zMax);
26}
27
29{
30 min = vec3(std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
31 max = vec3(-std::numeric_limits<float>::max(),
32 -std::numeric_limits<float>::max(),
33 -std::numeric_limits<float>::max());
34}
35
37{
38 if(min != vec3(std::numeric_limits<float>::max(),
39 std::numeric_limits<float>::max(),
40 std::numeric_limits<float>::max()) ||
41 max != vec3(-std::numeric_limits<float>::max(),
42 -std::numeric_limits<float>::max(),
43 -std::numeric_limits<float>::max()))
44 {
45 return true;
46 }
47
48 // Still at reset state.
49 return false;
50}
51
53{
54 return (glm::abs<float>(max.x - min.x) < glm::epsilon<float>() &&
55 glm::abs<float>(max.y - min.y) < glm::epsilon<float>() &&
56 glm::abs<float>(max.z - min.z) < glm::epsilon<float>());
57}
58
60{
61 plane bounds_plane;
62 memset(&bounds_plane, 0, sizeof(plane));
63
64 // Select the requested side
65 switch(side)
66 {
68 bounds_plane.data.y = 1;
69 bounds_plane.data.w = -max.y;
70 break;
72 bounds_plane.data.x = 1;
73 bounds_plane.data.w = -max.x;
74 break;
76 bounds_plane.data.z = 1;
77 bounds_plane.data.w = -max.z;
78 break;
80 bounds_plane.data.y = -1;
81 bounds_plane.data.w = min.y;
82 break;
84 bounds_plane.data.x = -1;
85 bounds_plane.data.w = min.x;
86 break;
88 bounds_plane.data.z = -1;
89 bounds_plane.data.w = min.z;
90 break;
91 } // End side Switch
92
93 // Return the plane
94 return bounds_plane;
95}
96
97void bbox::get_plane_points(volume_plane::e side, vec3 points_out[]) const
98{
99 // Select the requested side
100 switch(side)
101 {
103 points_out[0].x = min.x;
104 points_out[0].y = max.y;
105 points_out[0].z = min.z;
106 points_out[1].x = min.x;
107 points_out[1].y = max.y;
108 points_out[1].z = max.z;
109 points_out[2].x = max.x;
110 points_out[2].y = max.y;
111 points_out[2].z = max.z;
112 points_out[3].x = max.x;
113 points_out[3].y = max.y;
114 points_out[3].z = min.z;
115 break;
117 points_out[0].x = max.x;
118 points_out[0].y = min.y;
119 points_out[0].z = min.z;
120 points_out[1].x = max.x;
121 points_out[1].y = max.y;
122 points_out[1].z = min.z;
123 points_out[2].x = max.x;
124 points_out[2].y = max.y;
125 points_out[2].z = max.z;
126 points_out[3].x = max.x;
127 points_out[3].y = min.y;
128 points_out[3].z = max.z;
129 break;
131 points_out[0].x = max.x;
132 points_out[0].y = min.y;
133 points_out[0].z = max.z;
134 points_out[1].x = max.x;
135 points_out[1].y = max.y;
136 points_out[1].z = max.z;
137 points_out[2].x = min.x;
138 points_out[2].y = max.y;
139 points_out[2].z = max.z;
140 points_out[3].x = min.x;
141 points_out[3].y = min.y;
142 points_out[3].z = max.z;
143 break;
145 points_out[0].x = min.x;
146 points_out[0].y = min.y;
147 points_out[0].z = max.z;
148 points_out[1].x = min.x;
149 points_out[1].y = min.y;
150 points_out[1].z = min.z;
151 points_out[2].x = max.x;
152 points_out[2].y = min.y;
153 points_out[2].z = min.z;
154 points_out[3].x = max.x;
155 points_out[3].y = min.y;
156 points_out[3].z = max.z;
157 break;
159 points_out[0].x = min.x;
160 points_out[0].y = min.y;
161 points_out[0].z = max.z;
162 points_out[1].x = min.x;
163 points_out[1].y = max.y;
164 points_out[1].z = max.z;
165 points_out[2].x = min.x;
166 points_out[2].y = max.y;
167 points_out[2].z = min.z;
168 points_out[3].x = min.x;
169 points_out[3].y = min.y;
170 points_out[3].z = min.z;
171 break;
173 points_out[0].x = min.x;
174 points_out[0].y = min.y;
175 points_out[0].z = min.z;
176 points_out[1].x = min.x;
177 points_out[1].y = max.y;
178 points_out[1].z = min.z;
179 points_out[2].x = max.x;
180 points_out[2].y = max.y;
181 points_out[2].z = min.z;
182 points_out[3].x = max.x;
183 points_out[3].y = min.y;
184 points_out[3].z = min.z;
185 break;
186
187 } // End side Switch
188}
189
190bbox& bbox::from_points(const char* point_buffer,
191 unsigned int point_count,
192 unsigned int point_stride,
193 bool reset_bounds /* = true */)
194{
195 // Reset the box if requested
196 if(reset_bounds)
197 {
198 reset();
199 }
200
201 // Loop through all the points supplied and grow the box.
202 if((point_buffer != nullptr) && (point_count != 0u))
203 {
204 for(unsigned int v = 0; v < point_count; ++v, point_buffer += point_stride)
205 {
206 add_point(*reinterpret_cast<const vec3*>(point_buffer));
207 }
208
209 } // End if has data
210 return *this;
211}
212
213bbox& bbox::from_sphere(const vec3& center, float radius)
214{
215 min = center - vec3(radius, radius, radius);
216 max = center + vec3(radius, radius, radius);
217
218 return *this;
219}
220
222{
223 float rTemp;
224 if(max.x < min.x)
225 {
226 rTemp = max.x;
227 max.x = min.x;
228 min.x = rTemp;
229 }
230 if(max.y < min.y)
231 {
232 rTemp = max.y;
233 max.y = min.y;
234 min.y = rTemp;
235 }
236 if(max.z < min.z)
237 {
238 rTemp = max.z;
239 max.z = min.z;
240 min.z = rTemp;
241 }
242}
243
244bool bbox::intersect(const bbox& bounds) const
245{
246 return (min.x <= bounds.max.x) && (min.y <= bounds.max.y) && (min.z <= bounds.max.z) && (max.x >= bounds.min.x) &&
247 (max.y >= bounds.min.y) && (max.z >= bounds.min.z);
248}
249
250bool bbox::intersect(const bbox& bounds, bool& contained) const
251{
252 // Set to true by default
253 contained = true;
254
255 // Does the point fall outside any of the AABB planes?
256 if(bounds.min.x < min.x || bounds.min.x > max.x)
257 {
258 contained = false;
259 }
260 else if(bounds.min.y < min.y || bounds.min.y > max.y)
261 {
262 contained = false;
263 }
264 else if(bounds.min.z < min.z || bounds.min.z > max.z)
265 {
266 contained = false;
267 }
268 else if(bounds.max.x < min.x || bounds.max.x > max.x)
269 {
270 contained = false;
271 }
272 else if(bounds.max.y < min.y || bounds.max.y > max.y)
273 {
274 contained = false;
275 }
276 else if(bounds.max.z < min.z || bounds.max.z > max.z)
277 {
278 contained = false;
279 }
280
281 // Return immediately if it's fully contained
282 if(contained)
283 {
284 return true;
285 }
286
287 // Perform full intersection test
288 return (min.x <= bounds.max.x) && (min.y <= bounds.max.y) && (min.z <= bounds.max.z) && (max.x >= bounds.min.x) &&
289 (max.y >= bounds.min.y) && (max.z >= bounds.min.z);
290}
291
292bool bbox::intersect(const bbox& bounds, bbox& intersection) const
293{
294 intersection.min.x = glm::max(min.x, bounds.min.x);
295 intersection.min.y = glm::max(min.y, bounds.min.y);
296 intersection.min.z = glm::max(min.z, bounds.min.z);
297 intersection.max.x = glm::min(max.x, bounds.max.x);
298 intersection.max.y = glm::min(max.y, bounds.max.y);
299 intersection.max.z = glm::min(max.z, bounds.max.z);
300
301 // Test for intersection
302 if(intersection.min.x > intersection.max.x || intersection.min.y > intersection.max.y ||
303 intersection.min.z > intersection.max.z)
304 {
305 return false;
306 }
307
308 // Intersecting!
309 return true;
310}
311
312bool bbox::intersect(const bbox& bounds, const vec3& tolerance) const
313{
314 return ((min.x - tolerance.x) <= (bounds.max.x + tolerance.x)) &&
315 ((min.y - tolerance.y) <= (bounds.max.y + tolerance.y)) &&
316 ((min.z - tolerance.z) <= (bounds.max.z + tolerance.z)) &&
317 ((max.x + tolerance.x) >= (bounds.min.x - tolerance.x)) &&
318 ((max.y + tolerance.y) >= (bounds.min.y - tolerance.y)) &&
319 ((max.z + tolerance.z) >= (bounds.min.z - tolerance.z));
320}
321
322bool bbox::intersect(const vec3& origin, const vec3& velocity, float& t, bool restrict_range /* = true */) const
323{
324 float tMin = std::numeric_limits<float>::min();
325 float tMax = std::numeric_limits<float>::max();
326 float t1, t2, fTemp;
327
328 // If ray origin is inside bounding box, just return true (treat AABB as a
329 // solid box)
330 if(contains_point(origin))
331 {
332 t = 0.0f;
333 return true;
334
335 } // End if point in box
336
337 // X Slabs
338 // Is it pointing toward?
339 if(glm::abs<float>(velocity.x) > glm::epsilon<float>())
340 {
341 fTemp = 1.0f / velocity.x;
342 t1 = (max.x - origin.x) * fTemp;
343 t2 = (min.x - origin.x) * fTemp;
344
345 // Reorder if necessary
346 if(t1 > t2)
347 {
348 fTemp = t1;
349 t1 = t2;
350 t2 = fTemp;
351 }
352
353 // Compare and validate
354 if(t1 > tMin)
355 {
356 tMin = t1;
357 }
358 if(t2 < tMax)
359 {
360 tMax = t2;
361 }
362 if(tMin > tMax)
363 {
364 return false;
365 }
366 if(tMax < 0)
367 {
368 return false;
369 }
370
371 } // End if
372 else
373 {
374 // We cannot be intersecting in this case if the origin is outside of the
375 // slab
376 // if ( origin.x < (min.x - origin.x) || origin.x > (max.x - origin.x) )
377 if(origin.x < min.x || origin.x > max.x)
378 return false;
379
380 } // End else
381
382 // Y Slabs
383 // Is it pointing toward?
384 if(glm::abs<float>(velocity.y) > glm::epsilon<float>())
385 {
386 fTemp = 1.0f / velocity.y;
387 t1 = (max.y - origin.y) * fTemp;
388 t2 = (min.y - origin.y) * fTemp;
389
390 // Reorder if necessary
391 if(t1 > t2)
392 {
393 fTemp = t1;
394 t1 = t2;
395 t2 = fTemp;
396 }
397
398 // Compare and validate
399 if(t1 > tMin)
400 {
401 tMin = t1;
402 }
403 if(t2 < tMax)
404 {
405 tMax = t2;
406 }
407 if(tMin > tMax)
408 {
409 return false;
410 }
411 if(tMax < 0)
412 {
413 return false;
414 }
415
416 } // End if
417 else
418 {
419 // We cannot be intersecting in this case if the origin is outside of the
420 // slab
421 // if ( origin.y < (min.y - origin.y) || origin.y > (max.y - origin.y) )
422 if(origin.y < min.y || origin.y > max.y)
423 {
424 return false;
425 }
426
427 } // End else
428
429 // Z Slabs
430 // Is it pointing toward?
431 if(glm::abs<float>(velocity.z) > glm::epsilon<float>())
432 {
433 fTemp = 1.0f / velocity.z;
434 t1 = (max.z - origin.z) * fTemp;
435 t2 = (min.z - origin.z) * fTemp;
436
437 // Reorder if necessary
438 if(t1 > t2)
439 {
440 fTemp = t1;
441 t1 = t2;
442 t2 = fTemp;
443 }
444
445 // Compare and validate
446 if(t1 > tMin)
447 {
448 tMin = t1;
449 }
450 if(t2 < tMax)
451 {
452 tMax = t2;
453 }
454 if(tMin > tMax)
455 {
456 return false;
457 }
458 if(tMax < 0)
459 {
460 return false;
461 }
462
463 } // End if
464 else
465 {
466 // We cannot be intersecting in this case if the origin is outside of the
467 // slab
468 // if ( origin.z < (min.z - origin.z) || origin.z > (max.z - origin.z) )
469 if(origin.z < min.z || origin.z > max.z)
470 {
471 return false;
472 }
473
474 } // End else
475
476 // Pick the correct t value
477 if(tMin > 0)
478 {
479 t = tMin;
480 }
481 else
482 {
483 t = tMax;
484 }
485
486 // Outside our valid range? if yes, return no collide
487 if(t < 0.0f || (restrict_range && t > 1.0f))
488 {
489 return false;
490 }
491
492 // We intersected!
493 return true;
494}
495
496bool bbox::intersect(const vec3& v_tri0, const vec3& v_tri1, const vec3& v_tri2, const bbox& tri_bounds) const
497{
498 // Perform rough "broadphase" rejection by testing for intersection
499 // between the supplied triangle bounding box and the source box.
500 if(tri_bounds.min.x > max.x || tri_bounds.max.x < min.x || tri_bounds.min.y > max.y || tri_bounds.max.y < min.y ||
501 tri_bounds.min.z > max.z || tri_bounds.max.z < min.z)
502 {
503 return false;
504 }
505
506 // Move everything such that the box center is located at <0,0,0>
507 // and the entire test becomes relative to it.
508 const vec3 vCenter = get_center();
509 const vec3 vExtents = get_extents();
510 const vec3 v0 = v_tri0 - vCenter;
511 const vec3 v1 = v_tri1 - vCenter;
512 const vec3 v2 = v_tri2 - vCenter;
513
514 // Next we need to test to see if the triangle's plane intersects the
515 // source box. Begin by generating the plane itself. Note: We need
516 // the edge vectors for later tests, so keep them around.
517
518 vec3 vEdge0 = v1 - v0;
519 vec3 vEdge1 = v2 - v1;
520 vec3 vNormal = glm::cross(vEdge0, vEdge1);
521 float fPlaneDistance = -glm::dot(vNormal, v0);
522
523 // Calculate near / far extreme points
524 vec3 vNearPoint, vFarPoint;
525 if(vNormal.x > 0.0f)
526 {
527 vFarPoint.x = max.x;
528 vNearPoint.x = min.x;
529 }
530 else
531 {
532 vFarPoint.x = min.x;
533 vNearPoint.x = max.x;
534 }
535 if(vNormal.y > 0.0f)
536 {
537 vFarPoint.y = max.y;
538 vNearPoint.y = min.y;
539 }
540 else
541 {
542 vFarPoint.y = min.y;
543 vNearPoint.y = max.y;
544 }
545 if(vNormal.z > 0.0f)
546 {
547 vFarPoint.z = max.z;
548 vNearPoint.z = min.z;
549 }
550 else
551 {
552 vFarPoint.z = min.z;
553 vNearPoint.z = max.z;
554 }
555
556 // If near extreme point is outside, then the AABB is totally outside the
557 // plane
558 if(glm::dot(vNormal, vNearPoint - vCenter) + fPlaneDistance > 0.0f)
559 {
560 return false;
561 }
562
563 // If far extreme point is inside, then the AABB is not intersecting the plane
564 if(glm::dot(vNormal, vFarPoint - vCenter) + fPlaneDistance < 0.0f)
565 {
566 return false;
567 }
568
569 // AXISTEST macro required variables
570 vec3 vAbsEdge;
571 float fTemp0, fTemp1, fMin, fMax;
572#define AXISTEST(vEdge, vP0, vP1, nComponent0, nComponent1) \
573 fTemp0 = vEdge[nComponent1] * vP0[nComponent0] - vEdge[nComponent0] * vP0[nComponent1]; \
574 fTemp1 = vEdge[nComponent1] * vP1[nComponent0] - vEdge[nComponent0] * vP1[nComponent1]; \
575 if(fTemp0 < fTemp1) \
576 { \
577 fMin = fTemp0; \
578 fMax = fTemp1; \
579 } \
580 else \
581 { \
582 fMin = fTemp1; \
583 fMax = fTemp0; \
584 } \
585 fTemp0 = vAbsEdge[nComponent1] * vExtents[nComponent0] + vAbsEdge[nComponent0] * vExtents[nComponent1]; \
586 if(fMin > fTemp0 || fMax < -fTemp0) \
587 return false;
588
589#define AXISTEST2(vEdge, vP0, vP1, nComponent0, nComponent1) \
590 fTemp0 = -vEdge[nComponent1] * vP0[nComponent0] + vEdge[nComponent0] * vP0[nComponent1]; \
591 fTemp1 = -vEdge[nComponent1] * vP1[nComponent0] + vEdge[nComponent0] * vP1[nComponent1]; \
592 if(fTemp0 < fTemp1) \
593 { \
594 fMin = fTemp0; \
595 fMax = fTemp1; \
596 } \
597 else \
598 { \
599 fMin = fTemp1; \
600 fMax = fTemp0; \
601 } \
602 fTemp0 = vAbsEdge[nComponent1] * vExtents[nComponent0] + vAbsEdge[nComponent0] * vExtents[nComponent1]; \
603 if(fMin > fTemp0 || fMax < -fTemp0) \
604 return false;
605
606 // Test to see if the triangle edges cross the box.
607 vAbsEdge.x = glm::abs<float>(vEdge0.x);
608 vAbsEdge.y = glm::abs<float>(vEdge0.y);
609 vAbsEdge.z = glm::abs<float>(vEdge0.z);
610 AXISTEST(vEdge0, v0, v2, 1, 2); // X
611 AXISTEST2(vEdge0, v0, v2, 0, 2); // Y
612 AXISTEST(vEdge0, v2, v1, 0, 1); // Z
613
614 vAbsEdge.x = glm::abs<float>(vEdge1.x);
615 vAbsEdge.y = glm::abs<float>(vEdge1.y);
616 vAbsEdge.z = glm::abs<float>(vEdge1.z);
617 AXISTEST(vEdge1, v0, v2, 1, 2); // X
618 AXISTEST2(vEdge1, v0, v2, 0, 2); // Y
619 AXISTEST(vEdge1, v0, v1, 0, 1); // Z
620
621 const vec3 vEdge2 = v0 - v2;
622 vAbsEdge.x = glm::abs<float>(vEdge2.x);
623 vAbsEdge.y = glm::abs<float>(vEdge2.y);
624 vAbsEdge.z = glm::abs<float>(vEdge2.z);
625 AXISTEST(vEdge2, v0, v1, 1, 2); // X
626 AXISTEST2(vEdge2, v0, v1, 0, 2); // Y
627 AXISTEST(vEdge2, v2, v1, 0, 1); // Z
628
629 // Overlapping
630 return true;
631}
632
633bool bbox::intersect(const vec3& v_tri0, const vec3& v_tri1, const vec3& v_tri2) const
634{
635 bbox tri_bounds;
636 tri_bounds.add_point(v_tri0);
637 tri_bounds.add_point(v_tri1);
638 tri_bounds.add_point(v_tri2);
639
640 // Perform rough "broadphase" rejection by testing for intersection
641 // between the supplied triangle bounding box and the source box.
642 if(tri_bounds.min.x > max.x || tri_bounds.max.x < min.x || tri_bounds.min.y > max.y || tri_bounds.max.y < min.y ||
643 tri_bounds.min.z > max.z || tri_bounds.max.z < min.z)
644 {
645 return false;
646 }
647
648 // Move everything such that the box center is located at <0,0,0>
649 // and the entire test becomes relative to it.
650 const vec3 vCenter = get_center();
651 const vec3 vExtents = get_extents();
652 const vec3 v0 = v_tri0 - vCenter;
653 const vec3 v1 = v_tri1 - vCenter;
654 const vec3 v2 = v_tri2 - vCenter;
655
656 // Next we need to test to see if the triangle's plane intersects the
657 // source box. Begin by generating the plane itself. Note: We need
658 // the edge vectors for later tests, so keep them around.
659
660 vec3 vEdge0 = v1 - v0;
661 vec3 vEdge1 = v2 - v1;
662 vec3 vNormal = glm::cross(vEdge0, vEdge1);
663 float fPlaneDistance = -glm::dot(vNormal, v0);
664
665 // Calculate near / far extreme points
666 vec3 vNearPoint, vFarPoint;
667 if(vNormal.x > 0.0f)
668 {
669 vFarPoint.x = max.x;
670 vNearPoint.x = min.x;
671 }
672 else
673 {
674 vFarPoint.x = min.x;
675 vNearPoint.x = max.x;
676 }
677 if(vNormal.y > 0.0f)
678 {
679 vFarPoint.y = max.y;
680 vNearPoint.y = min.y;
681 }
682 else
683 {
684 vFarPoint.y = min.y;
685 vNearPoint.y = max.y;
686 }
687 if(vNormal.z > 0.0f)
688 {
689 vFarPoint.z = max.z;
690 vNearPoint.z = min.z;
691 }
692 else
693 {
694 vFarPoint.z = min.z;
695 vNearPoint.z = max.z;
696 }
697
698 // If near extreme point is outside, then the AABB is totally outside the
699 // plane
700 if(glm::dot(vNormal, vNearPoint - vCenter) + fPlaneDistance > 0.0f)
701 {
702 return false;
703 }
704
705 // If far extreme point is inside, then the AABB is not intersecting the plane
706 if(glm::dot(vNormal, vFarPoint - vCenter) + fPlaneDistance < 0.0f)
707 {
708 return false;
709 }
710
711 // AXISTEST macro required variables
712 vec3 vAbsEdge;
713 float fTemp0, fTemp1, fMin, fMax;
714#define AXISTEST(vEdge, vP0, vP1, nComponent0, nComponent1) \
715 fTemp0 = vEdge[nComponent1] * vP0[nComponent0] - vEdge[nComponent0] * vP0[nComponent1]; \
716 fTemp1 = vEdge[nComponent1] * vP1[nComponent0] - vEdge[nComponent0] * vP1[nComponent1]; \
717 if(fTemp0 < fTemp1) \
718 { \
719 fMin = fTemp0; \
720 fMax = fTemp1; \
721 } \
722 else \
723 { \
724 fMin = fTemp1; \
725 fMax = fTemp0; \
726 } \
727 fTemp0 = vAbsEdge[nComponent1] * vExtents[nComponent0] + vAbsEdge[nComponent0] * vExtents[nComponent1]; \
728 if(fMin > fTemp0 || fMax < -fTemp0) \
729 return false;
730
731#define AXISTEST2(vEdge, vP0, vP1, nComponent0, nComponent1) \
732 fTemp0 = -vEdge[nComponent1] * vP0[nComponent0] + vEdge[nComponent0] * vP0[nComponent1]; \
733 fTemp1 = -vEdge[nComponent1] * vP1[nComponent0] + vEdge[nComponent0] * vP1[nComponent1]; \
734 if(fTemp0 < fTemp1) \
735 { \
736 fMin = fTemp0; \
737 fMax = fTemp1; \
738 } \
739 else \
740 { \
741 fMin = fTemp1; \
742 fMax = fTemp0; \
743 } \
744 fTemp0 = vAbsEdge[nComponent1] * vExtents[nComponent0] + vAbsEdge[nComponent0] * vExtents[nComponent1]; \
745 if(fMin > fTemp0 || fMax < -fTemp0) \
746 return false;
747
748 // Test to see if the triangle edges cross the box.
749 vAbsEdge.x = glm::abs<float>(vEdge0.x);
750 vAbsEdge.y = glm::abs<float>(vEdge0.y);
751 vAbsEdge.z = glm::abs<float>(vEdge0.z);
752 AXISTEST(vEdge0, v0, v2, 1, 2); // X
753 AXISTEST2(vEdge0, v0, v2, 0, 2); // Y
754 AXISTEST(vEdge0, v2, v1, 0, 1); // Z
755
756 vAbsEdge.x = glm::abs<float>(vEdge1.x);
757 vAbsEdge.y = glm::abs<float>(vEdge1.y);
758 vAbsEdge.z = glm::abs<float>(vEdge1.z);
759 AXISTEST(vEdge1, v0, v2, 1, 2); // X
760 AXISTEST2(vEdge1, v0, v2, 0, 2); // Y
761 AXISTEST(vEdge1, v0, v1, 0, 1); // Z
762
763 const vec3 vEdge2 = v0 - v2;
764 vAbsEdge.x = glm::abs<float>(vEdge2.x);
765 vAbsEdge.y = glm::abs<float>(vEdge2.y);
766 vAbsEdge.z = glm::abs<float>(vEdge2.z);
767 AXISTEST(vEdge2, v0, v1, 1, 2); // X
768 AXISTEST2(vEdge2, v0, v1, 0, 2); // Y
769 AXISTEST(vEdge2, v2, v1, 0, 1); // Z
770
771 // Overlapping
772 return true;
773}
774
775bool bbox::contains_point(const vec3& point, float tolerance) const
776{
777 if(point.x < min.x - tolerance || point.x > max.x + tolerance)
778 {
779 return false;
780 }
781 if(point.y < min.y - tolerance || point.y > max.y + tolerance)
782 {
783 return false;
784 }
785 if(point.z < min.z - tolerance || point.z > max.z + tolerance)
786 {
787 return false;
788 }
789 return true;
790}
791
792bool bbox::contains_point(const vec3& point) const
793{
794 if(point.x < min.x || point.x > max.x)
795 {
796 return false;
797 }
798 if(point.y < min.y || point.y > max.y)
799 {
800 return false;
801 }
802 if(point.z < min.z || point.z > max.z)
803 {
804 return false;
805 }
806 return true;
807}
808
809bool bbox::contains_point(const vec3& point, const vec3& tolerance) const
810{
811 if(point.x < min.x - tolerance.x || point.x > max.x + tolerance.x)
812 {
813 return false;
814 }
815 if(point.y < min.y - tolerance.y || point.y > max.y + tolerance.y)
816 {
817 return false;
818 }
819 if(point.z < min.z - tolerance.z || point.z > max.z + tolerance.z)
820 {
821 return false;
822 }
823 return true;
824}
825
826vec3 bbox::closest_point(const vec3& test_point) const
827{
828 vec3 Closest;
829
830 // Test X extent
831 if(test_point.x < min.x)
832 {
833 Closest.x = min.x;
834 }
835 else if(test_point.x > max.x)
836 {
837 Closest.x = max.x;
838 }
839 else
840 {
841 Closest.x = test_point.x;
842 }
843
844 // Test Y extent
845 if(test_point.y < min.y)
846 {
847 Closest.y = min.y;
848 }
849 else if(test_point.y > max.y)
850 {
851 Closest.y = max.y;
852 }
853 else
854 {
855 Closest.y = test_point.y;
856 }
857
858 // Test Z extent
859 if(test_point.z < min.z)
860 {
861 Closest.z = min.z;
862 }
863 else if(test_point.z > max.z)
864 {
865 Closest.z = max.z;
866 }
867 else
868 {
869 Closest.z = test_point.z;
870 }
871
872 // Return the closest test_point
873 return Closest;
874}
875
877{
878 *this = mul(*this, t);
879
880 // Return reference to self
881 return *this;
882}
883
884bbox bbox::mul(const bbox& bounds, const transform& t)
885{
886 const auto x_axis = t.x_axis();
887 const auto y_axis = t.y_axis();
888 const auto z_axis = t.z_axis();
889 auto xa = x_axis * bounds.min.x;
890 auto xb = x_axis * bounds.max.x;
891 auto ya = y_axis * bounds.min.y;
892 auto yb = y_axis * bounds.max.y;
893 auto za = z_axis * bounds.min.z;
894 auto zb = z_axis * bounds.max.z;
895
896 return bbox(math::min(xa, xb) + math::min(ya, yb) + math::min(za, zb) + t.get_position(),
897 math::max(xa, xb) + math::max(ya, yb) + math::max(za, zb) + t.get_position());
898}
899
901{
902 *this = mul_no_scale(*this, t);
903
904 // Return reference to self
905 return *this;
906}
907
908bbox bbox::mul_no_scale(const bbox& bounds, const transform& t)
909{
910 const auto x_axis = t.x_unit_axis();
911 const auto y_axis = t.y_unit_axis();
912 const auto z_axis = t.z_unit_axis();
913 auto xa = x_axis * bounds.min.x;
914 auto xb = x_axis * bounds.max.x;
915 auto ya = y_axis * bounds.min.y;
916 auto yb = y_axis * bounds.max.y;
917 auto za = z_axis * bounds.min.z;
918 auto zb = z_axis * bounds.max.z;
919
920 return bbox(math::min(xa, xb) + math::min(ya, yb) + math::min(za, zb) + t.get_position(),
921 math::max(xa, xb) + math::max(ya, yb) + math::max(za, zb) + t.get_position());
922}
923
925{
926 if(point.x < min.x)
927 min.x = point.x;
928 if(point.y < min.y)
929 min.y = point.y;
930 if(point.z < min.z)
931 min.z = point.z;
932 if(point.x > max.x)
933 max.x = point.x;
934 if(point.y > max.y)
935 max.y = point.y;
936 if(point.z > max.z)
937 max.z = point.z;
938 return *this;
939}
940
942{
943 return max - min;
944}
945
947{
948 return vec3((max.x + min.x) * 0.5f, (max.y + min.y) * 0.5f, (max.z + min.z) * 0.5f);
949}
950
952{
953 return vec3((max.x - min.x) * 0.5f, (max.y - min.y) * 0.5f, (max.z - min.z) * 0.5f);
954}
955
956void bbox::inflate(float grow_size)
957{
958 min.x -= grow_size;
959 min.y -= grow_size;
960 min.z -= grow_size;
961 max.x += grow_size;
962 max.y += grow_size;
963 max.z += grow_size;
964}
965
966void bbox::inflate(const vec3& grow_size)
967{
968 min.x -= grow_size.x;
969 min.y -= grow_size.y;
970 min.z -= grow_size.z;
971 max.x += grow_size.x;
972 max.y += grow_size.y;
973 max.z += grow_size.z;
974}
975
976std::array<vec3, 8> bbox::get_corners() const
977{
978 return {{
979 { min.x, min.y, min.z },
980 { max.x, min.y, min.z },
981 { min.x, max.y, min.z },
982 { max.x, max.y, min.z },
983 { min.x, min.y, max.z },
984 { max.x, min.y, max.z },
985 { min.x, max.y, max.z },
986 { max.x, max.y, max.z }
987 }};
988}
989
990bbox& bbox::operator+=(const vec3& shift)
991{
992 min += shift;
993 max += shift;
994 return *this;
995}
996
997bbox& bbox::operator-=(const vec3& shift)
998{
999 min -= shift;
1000 max -= shift;
1001 return *this;
1002}
1003
1005{
1006 return bbox(min * scale, max * scale);
1007}
1008
1010{
1011 min *= scale;
1012 max *= scale;
1013 return *this;
1014}
1015
1017{
1018 mul(t);
1019 return *this;
1020}
1021
1022bool bbox::operator==(const bbox& bounds) const
1023{
1024 return (min == bounds.min) && (max == bounds.max);
1025}
1026
1027bool bbox::operator!=(const bbox& bounds) const
1028{
1029 return (min != bounds.min) || (max != bounds.max);
1030}
1031} // namespace math
#define AXISTEST2(vEdge, vP0, vP1, nComponent0, nComponent1)
#define AXISTEST(vEdge, vP0, vP1, nComponent0, nComponent1)
General purpose transformation class designed to maintain each component of the transformation separa...
Definition transform.hpp:27
float scale
Definition hub.cpp:25
Definition bbox.cpp:5
Storage for box vector values and wraps up common functionality.
Definition bbox.h:21
bbox & add_point(const vec3 &point)
Grows the bounding box based on the point passed.
Definition bbox.cpp:924
vec3 max
The maximum vector value of the bounding box.
Definition bbox.h:311
bbox operator*(float scale) const
Scales the bounding box values by the scalar passed.
Definition bbox.cpp:1004
void reset()
Resets the bounding box values.
Definition bbox.cpp:28
bool intersect(const bbox &bounds) const
Tests to see if this AABB is intersected by another AABB.
Definition bbox.cpp:244
bbox & operator+=(const vec3 &shift)
Moves the bounding box by the vector passed.
Definition bbox.cpp:990
bbox & from_points(const char *point_buffer, unsigned int point_count, unsigned int point_stride, bool reset=true)
Calculates the bounding box based on the points specified.
Definition bbox.cpp:190
bbox & operator-=(const vec3 &shift)
Moves the bounding box by the vector passed.
Definition bbox.cpp:997
bbox & mul(const transform &t)
Transforms an axis aligned bounding box by the specified matrix.
Definition bbox.cpp:876
void get_plane_points(volume_plane::e side, vec3 points_out[]) const
Retrieves the four points that form the boundary of the specified side of the bounding box.
Definition bbox.cpp:97
void inflate(float amount)
Grows the bounding box by the specified number of world space units on all three axes.
Definition bbox.cpp:956
bool operator==(const bbox &bounds) const
Checks for equality between this bounding box and another.
Definition bbox.cpp:1022
bbox & from_sphere(const vec3 &center, float radius)
Calculates the bounding box based on the sphere specified.
Definition bbox.cpp:213
bbox & operator*=(const transform &t)
Transforms the bounding box by the matrix passed.
Definition bbox.cpp:1016
vec3 min
The minimum vector value of the bounding box.
Definition bbox.h:306
std::array< vec3, 8 > get_corners() const
Definition bbox.cpp:976
bool is_degenerate() const
Checks if the bounding box is degenerate (empty)
Definition bbox.cpp:52
bbox & mul_no_scale(const transform &t)
Definition bbox.cpp:900
bool contains_point(const vec3 &point) const
Tests to see if a point falls within this bounding box or not.
Definition bbox.cpp:792
static bbox empty
An empty bounding box.
Definition bbox.h:316
plane get_plane(volume_plane::e side) const
Retrieves the plane for the specified side of the bounding box.
Definition bbox.cpp:59
void validate()
Ensures that the values placed in the min/max values never make the bounding box itself inverted.
Definition bbox.cpp:221
bool is_populated() const
Checks if the bounding box is populated.
Definition bbox.cpp:36
bool operator!=(const bbox &bounds) const
Checks for inequality between this bounding box and another.
Definition bbox.cpp:1027
vec3 get_dimensions() const
Returns a vector containing the dimensions of the bounding box.
Definition bbox.cpp:941
vec3 get_extents() const
Returns a vector containing the extents of the bounding box (the half-dimensions)
Definition bbox.cpp:951
vec3 closest_point(const vec3 &source_point) const
Computes the closest point on the surface of the AABB to the input point.
Definition bbox.cpp:826
vec3 get_center() const
Returns a vector containing the exact center point of the box.
Definition bbox.cpp:946
bbox()
Default Constructor.
Definition bbox.cpp:8
Storage for infinite plane.
Definition plane.h:21
vec4 data
The components of the plane.
Definition plane.h:240