Skip to main content

dynamis_model/
shape.rs

1#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2pub enum ShapeKind {
3    Sphere,
4    Box,
5    Capsule,
6}
7
8#[derive(Clone, Copy, Debug)]
9pub struct ShapeDesc {
10    pub kind: ShapeKind,
11    pub radius: f32,
12    pub half_extents: [f32; 3],
13    pub half_height: f32,
14}
15
16impl ShapeDesc {
17    pub fn sphere(radius: f32) -> Self {
18        Self {
19            kind: ShapeKind::Sphere,
20            radius,
21            half_extents: [0.0; 3],
22            half_height: 0.0,
23        }
24    }
25
26    pub fn cuboid(half_extents: [f32; 3]) -> Self {
27        Self {
28            kind: ShapeKind::Box,
29            radius: 0.0,
30            half_extents,
31            half_height: 0.0,
32        }
33    }
34
35    pub fn capsule(radius: f32, half_height: f32) -> Self {
36        Self {
37            kind: ShapeKind::Capsule,
38            radius,
39            half_extents: [0.0; 3],
40            half_height,
41        }
42    }
43
44    pub fn bounding_radius(&self) -> f32 {
45        match self.kind {
46            ShapeKind::Sphere => self.radius,
47            ShapeKind::Box => {
48                let x = self.half_extents[0];
49                let y = self.half_extents[1];
50                let z = self.half_extents[2];
51                (x * x + y * y + z * z).sqrt()
52            }
53            ShapeKind::Capsule => self.half_height + self.radius,
54        }
55    }
56
57    pub fn inverse_inertia_diagonal(&self, inverse_mass: f32) -> [f32; 3] {
58        if inverse_mass == 0.0 {
59            return [0.0; 3];
60        }
61        let mass = 1.0 / inverse_mass;
62        match self.kind {
63            ShapeKind::Sphere => {
64                let i = 2.0 / 5.0 * mass * self.radius * self.radius;
65                [1.0 / i; 3]
66            }
67            ShapeKind::Box => {
68                let hx = self.half_extents[0];
69                let hy = self.half_extents[1];
70                let hz = self.half_extents[2];
71                let ex = 2.0 * hx;
72                let ey = 2.0 * hy;
73                let ez = 2.0 * hz;
74                let ix = mass / 12.0 * (ey * ey + ez * ez);
75                let iy = mass / 12.0 * (ex * ex + ez * ez);
76                let iz = mass / 12.0 * (ex * ex + ey * ey);
77                [1.0 / ix, 1.0 / iy, 1.0 / iz]
78            }
79            ShapeKind::Capsule => {
80                let r = self.radius;
81                let h = self.half_height;
82                let cylinder_volume = std::f32::consts::PI * r * r * 2.0 * h;
83                let sphere_volume = 4.0 / 3.0 * std::f32::consts::PI * r * r * r;
84                let total = cylinder_volume + sphere_volume;
85                let cylinder_mass = mass * cylinder_volume / total;
86                let sphere_mass = mass * sphere_volume / total;
87                let ix = cylinder_mass / 12.0 * (3.0 * r * r + (2.0 * h) * (2.0 * h))
88                    + sphere_mass
89                        * (2.0 / 5.0 * r * r + (h + 3.0 / 8.0 * r) * (h + 3.0 / 8.0 * r))
90                        * 2.0;
91                let iy = cylinder_mass / 2.0 * r * r + sphere_mass * 2.0 / 5.0 * r * r * 2.0;
92                [1.0 / ix, 1.0 / iy, 1.0 / ix]
93            }
94        }
95    }
96}