Skip to main content

dynamis_model/
body.rs

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