cem/
collider.rs

1use std::io::{self, Read, Write};
2
3use cgmath::{Point3, MetricSpace};
4use std::f32;
5use Encode;
6
7const INFINITE_AABB: Aabb = Aabb {
8	lower: Point3 { x:  f32::INFINITY, y:  f32::INFINITY, z:  f32::INFINITY},
9	upper: Point3 { x: -f32::INFINITY, y: -f32::INFINITY, z: -f32::INFINITY}
10};
11
12pub struct CenterBuilder(Aabb);
13impl CenterBuilder {
14	pub fn begin() -> Self {
15		CenterBuilder(INFINITE_AABB)
16	}
17
18	pub fn update(&mut self, point: Point3<f32>) {
19		self.0 = self.0.with(point);
20	}
21
22	pub fn build(&self) -> Point3<f32> {
23		Point3 {
24			x: (self.0.upper.x + self.0.lower.x) / 2.0,
25			y: (self.0.upper.y + self.0.lower.y) / 2.0,
26			z: (self.0.upper.z + self.0.lower.z) / 2.0
27		}
28	}
29}
30
31#[derive(Debug, Default, Copy, Clone, PartialEq)]
32pub struct Collider {
33	pub aabb: Aabb,
34	pub radius: f32
35}
36
37#[derive(Debug)]
38pub struct ColliderBuilder {
39	center: Point3<f32>,
40	aabb: Aabb,
41	radius_squared: f32
42}
43
44impl ColliderBuilder {
45	pub fn begin(center: Point3<f32>) -> Self {
46		ColliderBuilder {
47			center,
48			aabb: INFINITE_AABB,
49			radius_squared: 0.0
50		}
51	}
52
53	pub fn update(&mut self, point: Point3<f32>) {
54		self.radius_squared = self.radius_squared.max (
55			point.distance2(self.center)
56		);
57
58		self.aabb = self.aabb.with(point);
59	}
60
61	pub fn build(&self) -> Collider {
62		Collider {
63			aabb: if self.aabb == INFINITE_AABB { Aabb::default() } else { self.aabb },
64			radius: self.radius_squared.sqrt()
65		}
66	}
67}
68
69/// An axis-aligned bounding box containing a lower corner and upper corner.
70#[derive(Debug, Copy, Clone, PartialEq)]
71pub struct Aabb {
72	pub lower: Point3<f32>,
73	pub upper: Point3<f32>
74}
75
76impl Aabb {
77	pub fn with(self, point: Point3<f32>) -> Aabb {
78		Aabb {
79			lower: Point3 {
80				x: self.lower.x.min(point.x),
81				y: self.lower.y.min(point.y),
82				z: self.lower.z.min(point.z)
83			},
84			upper: Point3 {
85				x: self.upper.x.max(point.x),
86				y: self.upper.y.max(point.y),
87				z: self.upper.z.max(point.z)
88			}
89		}
90	}
91}
92
93impl Encode for Aabb {
94	fn read<R>(r: &mut R) -> io::Result<Self> where R: Read {
95		Ok(Aabb {
96			lower: Point3::read(r)?,
97			upper: Point3::read(r)?
98		})
99	}
100
101	fn write<W>(&self, w: &mut W) -> io::Result<()> where W: Write {
102		self.lower.write(w)?;
103		self.upper.write(w)
104	}
105}
106
107impl Default for Aabb {
108	fn default() -> Self {
109		Aabb {
110			lower: Point3::new(0.0, 0.0, 0.0),
111			upper: Point3::new(0.0, 0.0, 0.0)
112		}
113	}
114}