1use crate::{Point3, Scalar, Vec3};
4
5#[derive(Debug, Clone, Copy, PartialEq)]
7#[cfg_attr(
8 feature = "serde",
9 derive(serde::Serialize, serde::Deserialize),
10 serde(deny_unknown_fields)
11)]
12pub struct Aabb {
13 pub min: Point3,
15 pub max: Point3,
17}
18
19impl Aabb {
20 pub const fn empty() -> Self {
22 Self {
23 min: Vec3::splat(Scalar::INFINITY),
24 max: Vec3::splat(Scalar::NEG_INFINITY),
25 }
26 }
27
28 #[inline]
30 pub const fn from_point(point: Point3) -> Self {
31 Self {
32 min: point,
33 max: point,
34 }
35 }
36
37 #[inline]
39 pub fn extend(&mut self, point: Point3) {
40 self.min = self.min.min(point);
41 self.max = self.max.max(point);
42 }
43
44 #[inline]
46 pub fn union(&mut self, other: &Self) {
47 self.min = self.min.min(other.min);
48 self.max = self.max.max(other.max);
49 }
50
51 #[inline]
53 pub fn is_finite(&self) -> bool {
54 self.min.is_finite() && self.max.is_finite()
55 }
56
57 #[inline]
59 pub fn intersects(&self, other: &Self) -> bool {
60 self.min.x <= other.max.x
61 && self.max.x >= other.min.x
62 && self.min.y <= other.max.y
63 && self.max.y >= other.min.y
64 && self.min.z <= other.max.z
65 && self.max.z >= other.min.z
66 }
67
68 #[inline]
70 pub fn is_empty(&self) -> bool {
71 self.min.x > self.max.x
72 }
73
74 pub fn diagonal(&self) -> Vec3 {
76 if self.is_empty() {
77 Vec3::ZERO
78 } else {
79 self.max - self.min
80 }
81 }
82
83 #[inline]
85 pub fn center(&self) -> Point3 {
86 if self.is_empty() {
87 Vec3::ZERO
88 } else {
89 (self.min + self.max) * 0.5
90 }
91 }
92
93 #[inline]
96 pub fn gap(&self, other: &Self) -> Scalar {
97 let separation = (other.min - self.max)
98 .max(self.min - other.max)
99 .max(Vec3::ZERO);
100 separation.length()
101 }
102}
103
104impl Default for Aabb {
105 fn default() -> Self {
106 Self::empty()
107 }
108}
109
110#[cfg(test)]
111mod tests {
112 use super::*;
113
114 #[test]
115 fn empty_box_absorbs_first_point() {
116 let mut bounds = Aabb::default();
117 assert!(bounds.is_empty());
118 bounds.extend(Vec3::new(1.0, 2.0, 3.0));
119 assert_eq!(bounds.min, bounds.max);
120 }
121
122 #[test]
123 fn disjoint_boxes_do_not_intersect() {
124 let mut left = Aabb::default();
125 left.extend(Vec3::ZERO);
126 left.extend(Vec3::ONE);
127 let mut right = Aabb::default();
128 right.extend(Vec3::splat(2.0));
129 right.extend(Vec3::splat(3.0));
130 assert!(!left.intersects(&right));
131 }
132}