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}