Skip to main content

engvis_core/
aabb.rs

1use glam::{Vec3, Affine3A, Mat4};
2
3#[derive(Debug, Clone, Copy)]
4pub struct Aabb {
5    pub min: Vec3,
6    pub max: Vec3,
7}
8
9impl Aabb {
10    pub fn empty() -> Self {
11        Self {
12            min: Vec3::splat(f32::MAX),
13            max: Vec3::splat(f32::MIN),
14        }
15    }
16
17    pub fn expand(&mut self, point: Vec3) {
18        self.min = self.min.min(point);
19        self.max = self.max.max(point);
20    }
21
22    /// Expand to include another AABB.
23    pub fn union(&self, other: &Aabb) -> Aabb {
24        if !other.is_valid() {
25            return *self;
26        }
27        if !self.is_valid() {
28            return *other;
29        }
30        Aabb {
31            min: self.min.min(other.min),
32            max: self.max.max(other.max),
33        }
34    }
35
36    /// Compute the AABB of a transformed AABB (uses the 8 corner approach).
37    pub fn from_transformed_aabb(local: &Aabb, transform: &Affine3A) -> Aabb {
38        let mat = Mat4::from(*transform);
39        let corners = [
40            Vec3::new(local.min.x, local.min.y, local.min.z),
41            Vec3::new(local.max.x, local.min.y, local.min.z),
42            Vec3::new(local.min.x, local.max.y, local.min.z),
43            Vec3::new(local.min.x, local.min.y, local.max.z),
44            Vec3::new(local.max.x, local.max.y, local.min.z),
45            Vec3::new(local.min.x, local.max.y, local.max.z),
46            Vec3::new(local.max.x, local.min.y, local.max.z),
47            Vec3::new(local.max.x, local.max.y, local.max.z),
48        ];
49        let mut out = Aabb::empty();
50        for c in &corners {
51            let t = mat.transform_point3(*c);
52            out.expand(t);
53        }
54        out
55    }
56
57    pub fn center(&self) -> Vec3 {
58        (self.min + self.max) * 0.5
59    }
60
61    pub fn extents(&self) -> Vec3 {
62        self.max - self.min
63    }
64
65    pub fn diagonal(&self) -> f32 {
66        self.extents().length()
67    }
68
69    pub fn is_valid(&self) -> bool {
70        self.min.x <= self.max.x && self.min.y <= self.max.y && self.min.z <= self.max.z
71    }
72}
73
74impl Default for Aabb {
75    fn default() -> Self {
76        Self::empty()
77    }
78}