Skip to main content

dynamis_model/
body.rs

1use crate::collider::ColliderDesc;
2use crate::shape::Shape;
3
4#[derive(Clone, Copy, Debug, PartialEq)]
5pub struct BodyHandle {
6    pub id: u32,
7    pub generation: u32,
8}
9
10#[derive(Clone, Copy, Debug, PartialEq)]
11pub struct BodyState {
12    pub position: [f32; 3],
13    pub orientation: [f32; 4],
14    pub velocity: [f32; 3],
15    pub angular_velocity: [f32; 3],
16    pub inverse_mass: f32,
17    pub sleeping: bool,
18    pub step: u64,
19}
20
21pub const DEFAULT_COLLISION_GROUP: u32 = 0x0000_0001;
22pub const DEFAULT_COLLISION_MASK: u32 = 0xFFFF_FFFF;
23pub const BODY_DESC_COLLIDERS_MAX: usize = 4;
24
25#[derive(Clone, Debug)]
26pub struct BodyDesc {
27    pub colliders: Vec<ColliderDesc>,
28    pub position: [f32; 3],
29    pub orientation: [f32; 4],
30    pub velocity: [f32; 3],
31    pub angular_velocity: [f32; 3],
32    pub mass: f32,
33    pub collision_group: u32,
34    pub collision_mask: u32,
35    pub kinematic: bool,
36    pub ccd: bool,
37}
38
39impl BodyDesc {
40    pub fn new(collider: ColliderDesc) -> Self {
41        Self {
42            colliders: vec![collider],
43            position: [0.0; 3],
44            orientation: [0.0, 0.0, 0.0, 1.0],
45            velocity: [0.0; 3],
46            angular_velocity: [0.0; 3],
47            mass: 1.0,
48            collision_group: DEFAULT_COLLISION_GROUP,
49            collision_mask: DEFAULT_COLLISION_MASK,
50            kinematic: false,
51            ccd: false,
52        }
53    }
54
55    pub fn collider(mut self, collider: ColliderDesc) -> Self {
56        assert!(
57            self.colliders.len() < BODY_DESC_COLLIDERS_MAX,
58            "a body supports at most four colliders"
59        );
60        self.colliders.push(collider);
61        self
62    }
63
64    pub fn sphere(radius: f32) -> Self {
65        Self::new(ColliderDesc::new(Shape::sphere(radius)))
66    }
67
68    pub fn cuboid(half_extents: [f32; 3]) -> Self {
69        Self::new(ColliderDesc::new(Shape::cuboid(half_extents)))
70    }
71
72    pub fn capsule(radius: f32, half_height: f32) -> Self {
73        Self::new(ColliderDesc::new(Shape::capsule(radius, half_height)))
74    }
75
76    pub fn cylinder(radius: f32, half_height: f32) -> Self {
77        Self::new(ColliderDesc::new(Shape::cylinder(radius, half_height)))
78    }
79
80    pub fn static_sphere(radius: f32) -> Self {
81        Self {
82            mass: 0.0,
83            ..Self::sphere(radius)
84        }
85    }
86
87    pub fn position(mut self, position: [f32; 3]) -> Self {
88        self.position = position;
89        self
90    }
91
92    pub fn restitution(mut self, restitution: f32) -> Self {
93        self.colliders[0].restitution = restitution;
94        self
95    }
96
97    pub fn friction(mut self, friction: f32) -> Self {
98        assert!(friction >= 0.0, "friction must be non-negative");
99        self.colliders[0].friction = friction;
100        self
101    }
102
103    pub fn sensor(mut self, sensor: bool) -> Self {
104        assert!(
105            !self.colliders.is_empty(),
106            "a body needs at least one collider"
107        );
108        self.colliders[0].sensor = sensor;
109        self
110    }
111
112    pub fn orientation(mut self, orientation: [f32; 4]) -> Self {
113        assert!(
114            (orientation[0] * orientation[0]
115                + orientation[1] * orientation[1]
116                + orientation[2] * orientation[2]
117                + orientation[3] * orientation[3]
118                - 1.0)
119                .abs()
120                < 1e-4,
121            "orientation must be a unit quaternion"
122        );
123        self.orientation = orientation;
124        self
125    }
126
127    pub fn velocity(mut self, velocity: [f32; 3]) -> Self {
128        self.velocity = velocity;
129        self
130    }
131
132    pub fn angular_velocity(mut self, angular_velocity: [f32; 3]) -> Self {
133        self.angular_velocity = angular_velocity;
134        self
135    }
136
137    pub fn mass(mut self, mass: f32) -> Self {
138        assert!(mass >= 0.0, "mass must be non-negative");
139        self.mass = mass;
140        self
141    }
142
143    pub fn collision_group(mut self, group: u32) -> Self {
144        self.collision_group = group;
145        self
146    }
147
148    pub fn collision_mask(mut self, mask: u32) -> Self {
149        self.collision_mask = mask;
150        self
151    }
152
153    pub fn kinematic(mut self, kinematic: bool) -> Self {
154        self.kinematic = kinematic;
155        self
156    }
157
158    pub fn ccd(mut self, ccd: bool) -> Self {
159        self.ccd = ccd;
160        self
161    }
162}