anput_physics/density_fields/
aabb.rs1use 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}