1pub use crate::{ColliderHandle, RigidBodyHandle};
2#[derive(Clone, Debug)]
4pub struct RigidBody {
5 core: body::Core,
6}
7impl body::Access for RigidBody {
8 fn core(&self) -> &body::Core {
9 &self.core
10 }
11 fn core_mut(&mut self) -> &mut body::Core {
12 &mut self.core
13 }
14}
15impl RigidBody {
16 pub fn translation(&self) -> Vector {
17 from3(self.core.position)
18 }
19 pub fn rotation(&self) -> &Rotation {
20 rotation(&self.core)
21 }
22 pub fn linvel(&self) -> Vector {
23 from3(self.core.velocity)
24 }
25 pub fn angvel(&self) -> Angular {
26 angular_from3(self.core.angular_velocity)
27 }
28 pub fn mass(&self) -> f32 {
29 self.core.mass
30 }
31 pub fn colliders(&self) -> &[ColliderHandle] {
32 &self.core.colliders
33 }
34 pub fn is_ccd_enabled(&self) -> bool {
35 self.core.ccd
36 }
37 pub fn enable_ccd(&mut self, enabled: bool) {
38 self.core.ccd = enabled;
39 }
40 pub fn is_sleeping(&self) -> bool {
41 self.core.sleeping
42 }
43 pub fn wake_up(&mut self, _strong: bool) {
44 self.core.wake();
45 }
46 pub fn set_translation(&mut self, p: Vector, wake: bool) {
47 assert!(p.is_finite());
48 if self.core.position!=to3(p) {self.core.invalidate_contacts();}
49 self.core.position = to3(p);
50 if wake {
51 self.core.wake();
52 }
53 }
54 pub fn set_rotation(&mut self, q: Rotation, wake: bool) {
55 self.core.invalidate_contacts();
56 self.core.set_rotation(rotation_to3(q));
57 if wake {
58 self.core.wake();
59 }
60 }
61 pub fn set_linvel(&mut self, v: Vector, wake: bool) {
62 assert!(v.is_finite());
63 self.core.velocity = to3(v);
64 if wake {
65 self.core.wake();
66 }
67 }
68 pub fn set_angvel(&mut self, v: Angular, wake: bool) {
69 let v = angular_to3(v);
70 assert!(v.is_finite());
71 self.core.angular_velocity = v;
72 if wake {
73 self.core.wake();
74 }
75 }
76 pub fn set_gravity_scale(&mut self, scale: f32, wake: bool) {
77 assert!(scale.is_finite());
78 if self.core.gravity_scale!=scale {self.core.invalidate_contacts();}
79 self.core.gravity_scale = scale;
80 if wake {
81 self.core.wake();
82 }
83 }
84 pub fn apply_impulse(&mut self, impulse: Vector, wake: bool) {
85 let v = to3(impulse);
86 assert!(v.is_finite());
87 self.core.velocity += v * self.core.inv_mass;
88 if wake {
89 self.core.wake();
90 }
91 }
92 pub fn apply_impulse_at_point(&mut self, impulse: Vector, point: Vector, wake: bool) {
93 let j = to3(impulse);
94 let p = to3(point);
95 assert!(j.is_finite() && p.is_finite());
96 let torque = (p - self.core.position).cross(j);
97 self.core.velocity += j * self.core.inv_mass;
98 self.core.angular_velocity += self.core.inverse_inertia(torque);
99 if wake {
100 self.core.wake();
101 }
102 }
103 pub fn apply_torque_impulse(&mut self, impulse: Angular, wake: bool) {
104 let v = angular_to3(impulse);
105 assert!(v.is_finite());
106 self.core.angular_velocity += self.core.inverse_inertia(v);
107 if wake {
108 self.core.wake();
109 }
110 }
111 pub fn add_force(&mut self, force: Vector, wake: bool) {
112 let f = to3(force);
113 assert!(f.is_finite());
114 self.core.force += f;
115 if wake {
116 self.core.wake();
117 }
118 }
119 pub fn add_torque(&mut self, torque: Angular, wake: bool) {
120 let t = angular_to3(torque);
121 assert!(t.is_finite());
122 self.core.torque += t;
123 if wake {
124 self.core.wake();
125 }
126 }
127 pub fn set_next_kinematic_translation(&mut self, p: Vector) {
128 assert!(p.is_finite());
129 self.core.next_position = Some(to3(p));
130 }
131 pub fn set_next_kinematic_rotation(&mut self, q: Rotation) {
132 self.core.next_rotation = Some(rotation_to3(q));
133 }
134}
135#[derive(Clone, Debug)]
136pub struct RigidBodyBuilder {
137 core: body::Core,
138}
139impl RigidBodyBuilder {
140 pub fn dynamic() -> Self {
141 Self {
142 core: body::Core::new(body::Kind::Dynamic, PLANAR),
143 }
144 }
145 pub fn fixed() -> Self {
146 Self {
147 core: body::Core::new(body::Kind::Fixed, PLANAR),
148 }
149 }
150 pub fn kinematic_position_based() -> Self {
151 Self {
152 core: body::Core::new(body::Kind::Kinematic, PLANAR),
153 }
154 }
155 pub fn translation(mut self, p: Vector) -> Self {
156 assert!(p.is_finite());
157 self.core.position = to3(p);
158 self
159 }
160 pub fn rotation(mut self, r: Angular) -> Self {
161 self.core
162 .set_rotation(Quat::from_scaled_axis(angular_to3(r)));
163 self
164 }
165 pub fn linvel(mut self, v: Vector) -> Self {
166 assert!(v.is_finite());
167 self.core.velocity = to3(v);
168 self
169 }
170 pub fn angvel(mut self, v: Angular) -> Self {
171 let v = angular_to3(v);
172 assert!(v.is_finite());
173 self.core.angular_velocity = v;
174 self
175 }
176 pub fn linear_damping(mut self, v: f32) -> Self {
177 assert!(v.is_finite() && v >= 0.);
178 self.core.linear_damping = v;
179 self
180 }
181 pub fn angular_damping(mut self, v: f32) -> Self {
182 assert!(v.is_finite() && v >= 0.);
183 self.core.angular_damping = v;
184 self
185 }
186 pub fn gravity_scale(mut self, v: f32) -> Self {
187 assert!(v.is_finite());
188 self.core.gravity_scale = v;
189 self
190 }
191 pub fn ccd_enabled(mut self, v: bool) -> Self {
192 self.core.ccd = v;
193 self
194 }
195 pub fn build(self) -> RigidBody {
196 self.into()
197 }
198}
199impl From<RigidBodyBuilder> for RigidBody {
200 fn from(b: RigidBodyBuilder) -> Self {
201 Self { core: b.core }
202 }
203}
204#[derive(Clone, Debug)]
205pub struct ColliderBuilder {
206 collider: Collider,
207}
208impl ColliderBuilder {
209 fn shape(shape: body::Shape) -> Self {
210 shape.validate();
211 Self {
212 collider: Collider::new(shape),
213 }
214 }
215 pub fn ball(radius: f32) -> Self {
216 Self::shape(body::Shape::Ball(radius))
217 }
218 pub fn density(mut self, v: f32) -> Self {
219 assert!(v.is_finite() && v > 0.);
220 self.collider.density = v;
221 self
222 }
223 pub fn friction(mut self, v: f32) -> Self {
224 assert!(v.is_finite() && v >= 0.);
225 self.collider.friction = v;
226 self
227 }
228 pub fn restitution(mut self, v: f32) -> Self {
229 self.collider.set_restitution(v);
230 self
231 }
232 pub fn sensor(mut self, v: bool) -> Self {
233 self.collider.sensor = v;
234 self
235 }
236 pub fn collision_layers(mut self, membership: u32, filter: u32) -> Self {
238 self.collider.membership = membership;
239 self.collider.filter = filter;
240 self
241 }
242 pub fn build(self) -> Collider {
243 self.into()
244 }
245}
246impl From<ColliderBuilder> for Collider {
247 fn from(b: ColliderBuilder) -> Self {
248 b.collider
249 }
250}
251pub type RawPhysicsWorld = world::World<RigidBody>;
252pub struct PhysicsWorld {
253 pub raw: RawPhysicsWorld,
254}
255impl Default for PhysicsWorld {
256 fn default() -> Self {
257 Self::new([0.; DIM])
258 }
259}
260impl std::ops::Deref for PhysicsWorld {
261 type Target = RawPhysicsWorld;
262 fn deref(&self) -> &Self::Target {
263 &self.raw
264 }
265}
266impl std::ops::DerefMut for PhysicsWorld {
267 fn deref_mut(&mut self) -> &mut Self::Target {
268 &mut self.raw
269 }
270}
271const DIM: usize = if PLANAR { 2 } else { 3 };
272impl PhysicsWorld {
273 pub fn new(gravity: [f32; DIM]) -> Self {
274 Self {
275 raw: world::World::new(to3(Vector::from_array(gravity)), PLANAR),
276 }
277 }
278 pub fn add_ball(&mut self, p: [f32; DIM], radius: f32, dynamic: bool) -> RigidBodyHandle {
279 let b = if dynamic {
280 RigidBodyBuilder::dynamic()
281 } else {
282 RigidBodyBuilder::fixed()
283 };
284 self.raw
285 .insert(
286 b.translation(Vector::from_array(p)),
287 ColliderBuilder::ball(radius),
288 )
289 .0
290 }
291 pub fn add_box(&mut self, p: [f32; DIM], half: [f32; DIM], dynamic: bool) -> RigidBodyHandle {
292 let b = if dynamic {
293 RigidBodyBuilder::dynamic()
294 } else {
295 RigidBodyBuilder::fixed()
296 };
297 let h = if PLANAR {
298 Vec3::new(half[0], half[1], 0.5)
299 } else {
300 Vec3::new(half[0], half[1], half.get(2).copied().unwrap_or(0.5))
301 };
302 self.raw
303 .insert(
304 b.translation(Vector::from_array(p)),
305 ColliderBuilder::shape(body::Shape::Box(h)),
306 )
307 .0
308 }
309 pub fn refresh_queries(&mut self) {}
311 pub fn raycast(
312 &self,
313 origin: [f32; DIM],
314 direction: [f32; DIM],
315 max_distance: f32,
316 ) -> Option<RayHit> {
317 self.raw
318 .cast_ray(
319 to3(Vector::from_array(origin)),
320 to3(Vector::from_array(direction)),
321 max_distance,
322 )
323 .map(|h| RayHit {
324 body: Some(h.0),
325 collider: h.1,
326 distance: h.2,
327 point: from3(h.3).to_array(),
328 normal: from3(h.4).to_array(),
329 })
330 }
331}
332#[derive(Clone, Copy, Debug)]
333pub struct RayHit {
334 pub body: Option<RigidBodyHandle>,
335 pub collider: ColliderHandle,
336 pub distance: f32,
337 pub point: [f32; DIM],
338 pub normal: [f32; DIM],
339}
340
341impl crate::character::Terrain for PhysicsWorld {
342 fn visit(&self,bounds:crate::character::QueryBounds,visitor:&mut dyn FnMut(crate::character::Obstacle)) {
343 crate::character::Terrain::visit(&self.raw,bounds,visitor);
344 }
345 fn obstacle(&self,id:u64)->Option<crate::character::Obstacle> {crate::character::Terrain::obstacle(&self.raw,id)}
346}