Skip to main content

he3d_physics/
aabb.rs

1use he3d_math::Vec3;
2
3/// An axis-aligned bounding box in world space.
4/// 世界空间中的轴对齐包围盒。
5#[derive(Clone, Copy, Debug, PartialEq)]
6pub struct Aabb {
7   /// The corner with the smallest coordinate on every axis.
8   /// 每个轴上坐标最小的角点。
9   pub min: Vec3,
10   /// The corner with the largest coordinate on every axis.
11   /// 每个轴上坐标最大的角点。
12   pub max: Vec3,
13}
14
15impl Aabb {
16   /// Build a box from two opposite corners, ordering them if necessary.
17   /// 由两个对角点构造包围盒;如有必要会重新排序。
18   #[must_use]
19   pub fn new(a: Vec3, b: Vec3) -> Self {
20      Self {
21         min: a.min(b),
22         max: a.max(b),
23      }
24   }
25
26   /// Build a box from a center and half extents.
27   /// 由中心与半长构造包围盒。
28   #[must_use]
29   pub fn from_center_half_extents(center: Vec3, half_extents: Vec3) -> Self {
30      Self {
31         min: center - half_extents,
32         max: center + half_extents,
33      }
34   }
35
36   /// The center of the box.
37   /// 包围盒的中心。
38   #[must_use]
39   pub fn center(&self) -> Vec3 {
40      (self.min + self.max) * 0.5
41   }
42
43   /// The half extents of the box.
44   /// 包围盒的半长。
45   #[must_use]
46   pub fn half_extents(&self) -> Vec3 {
47      (self.max - self.min) * 0.5
48   }
49
50   /// Whether two boxes share any volume. Touching faces count as overlapping.
51   /// 两个包围盒是否有体积重叠。面接触算作重叠。
52   #[must_use]
53   pub fn overlaps(&self, other: &Self) -> bool {
54      self.min.cmple(other.max).all() && self.max.cmpge(other.min).all()
55   }
56
57   /// The smallest box containing both inputs.
58   /// 包含两者的最小包围盒。
59   #[must_use]
60   pub fn merged(&self, other: &Self) -> Self {
61      Self {
62         min: self.min.min(other.min),
63         max: self.max.max(other.max),
64      }
65   }
66
67   /// Whether a point lies inside the box, faces included.
68   /// 点是否位于包围盒内(含面)。
69   #[must_use]
70   pub fn contains_point(&self, point: Vec3) -> bool {
71      point.cmpge(self.min).all() && point.cmple(self.max).all()
72   }
73
74   /// Grow the box by `margin` on every axis.
75   /// 每个轴向外扩展 `margin`。
76   #[must_use]
77   pub fn expanded(&self, margin: f32) -> Self {
78      let margin = Vec3::splat(margin);
79      Self {
80         min: self.min - margin,
81         max: self.max + margin,
82      }
83   }
84}
85
86#[cfg(test)]
87mod tests {
88   use super::Aabb;
89   use he3d_math::Vec3;
90
91   #[test]
92   fn orders_corners() {
93      let aabb = Aabb::new(Vec3::new(1.0, 2.0, 3.0), Vec3::new(-1.0, -2.0, -3.0));
94      assert_eq!(aabb.min, Vec3::new(-1.0, -2.0, -3.0));
95      assert_eq!(aabb.max, Vec3::new(1.0, 2.0, 3.0));
96   }
97
98   #[test]
99   fn touching_faces_overlap() {
100      let a = Aabb::from_center_half_extents(Vec3::ZERO, Vec3::ONE);
101      let b = Aabb::from_center_half_extents(Vec3::new(2.0, 0.0, 0.0), Vec3::ONE);
102      assert!(a.overlaps(&b));
103   }
104
105   #[test]
106   fn separated_boxes_do_not_overlap() {
107      let a = Aabb::from_center_half_extents(Vec3::ZERO, Vec3::ONE);
108      let b = Aabb::from_center_half_extents(Vec3::new(2.5, 0.0, 0.0), Vec3::ONE);
109      assert!(!a.overlaps(&b));
110   }
111}