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}