anput_physics/density_fields/
aabb.rs

1use crate::{
2    Scalar,
3    components::BodyAccessInfo,
4    density_fields::{DensityField, DensityRange},
5};
6use std::cmp::Ordering;
7use vek::{Aabb, Vec3};
8
9pub struct AabbDensityField {
10    pub aabb: Aabb<Scalar>,
11    pub density: Scalar,
12}
13
14impl DensityField for AabbDensityField {
15    fn aabb(&self, _: &BodyAccessInfo) -> Aabb<Scalar> {
16        self.aabb
17    }
18
19    fn density_at_point(&self, point: Vec3<Scalar>, _: &BodyAccessInfo) -> Scalar {
20        if self.aabb.contains_point(point) {
21            self.density
22        } else {
23            0.0
24        }
25    }
26
27    fn density_at_region(&self, region: Aabb<Scalar>, _: &BodyAccessInfo) -> DensityRange {
28        if self.aabb.contains_aabb(region) {
29            DensityRange::converged(self.density)
30        } else if self.aabb.collides_with_aabb(region) {
31            DensityRange {
32                min: 0.0,
33                max: self.density,
34            }
35        } else {
36            Default::default()
37        }
38    }
39
40    fn normal_at_point(
41        &self,
42        point: Vec3<Scalar>,
43        _: Vec3<Scalar>,
44        _: &BodyAccessInfo,
45    ) -> Vec3<Scalar> {
46        let size = self.aabb.size().into_array();
47        [
48            (
49                size[0],
50                (point.x - self.aabb.min.x).abs(),
51                Vec3::new(-1.0, 0.0, 0.0),
52            ),
53            (
54                size[1],
55                (point.y - self.aabb.min.y).abs(),
56                Vec3::new(0.0, -1.0, 0.0),
57            ),
58            (
59                size[2],
60                (point.z - self.aabb.min.z).abs(),
61                Vec3::new(0.0, 0.0, -1.0),
62            ),
63            (
64                size[0],
65                (self.aabb.max.x - point.x).abs(),
66                Vec3::new(1.0, 0.0, 0.0),
67            ),
68            (
69                size[1],
70                (self.aabb.max.y - point.y).abs(),
71                Vec3::new(0.0, 1.0, 0.0),
72            ),
73            (
74                size[2],
75                (self.aabb.max.z - point.z).abs(),
76                Vec3::new(0.0, 0.0, 1.0),
77            ),
78        ]
79        .into_iter()
80        .filter(|(size, _, _)| *size > Scalar::EPSILON)
81        .min_by(|(_, a, _), (_, b, _)| a.partial_cmp(b).unwrap_or(Ordering::Equal))
82        .map(|(_, _, normal)| normal)
83        .unwrap_or_default()
84    }
85}