From fa5ea9881d352424e954e8386620565aea04db3d Mon Sep 17 00:00:00 2001 From: Jondolf Date: Fri, 7 Jul 2023 12:43:40 +0300 Subject: [PATCH] Add `LinearDamping` and `AngularDamping` --- src/components/mod.rs | 20 ++++++++++++++++ src/lib.rs | 1 + src/plugins/integrator.rs | 49 ++++++++++++++++++++++++++++++++------- src/plugins/setup.rs | 2 ++ 4 files changed, 64 insertions(+), 8 deletions(-) diff --git a/src/components/mod.rs b/src/components/mod.rs index 840e44d9..c77c28c6 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -500,6 +500,26 @@ impl From for Friction { } } +/// Automatically slows down a dynamic [rigid body](RigidBody), decreasing it's [linear velocity](LinearVelocity) +/// each frame. This can be used to simulate air resistance. +/// +/// The default linear damping coefficient is `0.0`, which corresponds to no damping. +#[derive( + Component, Reflect, Debug, Clone, Copy, PartialEq, PartialOrd, Default, Deref, DerefMut, +)] +#[reflect(Component)] +pub struct LinearDamping(pub Scalar); + +/// Automatically slows down a dynamic [rigid body](RigidBody), decreasing it's [angular velocity](AngularVelocity) +/// each frame. This can be used to simulate air resistance. +/// +/// The default angular damping coefficient is `0.0`, which corresponds to no damping. +#[derive( + Component, Reflect, Debug, Clone, Copy, PartialEq, PartialOrd, Default, Deref, DerefMut, +)] +#[reflect(Component)] +pub struct AngularDamping(pub Scalar); + #[cfg(test)] mod tests { use crate::prelude::*; diff --git a/src/lib.rs b/src/lib.rs index 9ebb24ed..13fea0d9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,6 +26,7 @@ //! - [Sensor colliders](Sensor) //! - [Collision layers](CollisionLayers) //! - Material properties like [restitution](Restitution) and [friction](Friction) +//! - [Linear damping](LinearDamping) and [angular damping](AngularDamping) for simulating drag //! - External [forces](ExternalForce) and [torque](ExternalTorque) //! - [Gravity](Gravity) //! - [Joints](joints) diff --git a/src/plugins/integrator.rs b/src/plugins/integrator.rs index 9abc7783..ab0a00ff 100644 --- a/src/plugins/integrator.rs +++ b/src/plugins/integrator.rs @@ -28,6 +28,7 @@ type PosIntegrationComponents = ( &'static mut Position, &'static mut PreviousPosition, &'static mut LinearVelocity, + Option<&'static LinearDamping>, &'static ExternalForce, &'static Mass, ); @@ -38,15 +39,20 @@ fn integrate_pos( gravity: Res, sub_dt: Res, ) { - for (rb, mut pos, mut prev_pos, mut lin_vel, external_force, mass) in &mut bodies { + for (rb, mut pos, mut prev_pos, mut lin_vel, lin_damping, external_force, mass) in &mut bodies { prev_pos.0 = pos.0; if rb.is_static() { continue; } - // Apply gravity and other external forces + // Apply damping, gravity and other external forces if rb.is_dynamic() { + // Apply damping + if let Some(damping) = lin_damping { + lin_vel.0 *= 1.0 / (1.0 + sub_dt.0 * damping.0); + } + let gravitation_force = mass.0 * gravity.0; let external_forces = gravitation_force + external_force.0; lin_vel.0 += sub_dt.0 * external_forces / mass.0; @@ -61,6 +67,7 @@ type RotIntegrationComponents = ( &'static mut Rotation, &'static mut PreviousRotation, &'static mut AngularVelocity, + Option<&'static AngularDamping>, &'static ExternalTorque, &'static Inertia, &'static InverseInertia, @@ -72,8 +79,16 @@ fn integrate_rot( mut bodies: Query>, sub_dt: Res, ) { - for (rb, mut rot, mut prev_rot, mut ang_vel, external_torque, _inertia, inverse_inertia) in - &mut bodies + for ( + rb, + mut rot, + mut prev_rot, + mut ang_vel, + ang_damping, + external_torque, + _inertia, + inverse_inertia, + ) in &mut bodies { prev_rot.0 = *rot; @@ -81,8 +96,13 @@ fn integrate_rot( continue; } - // Apply external torque + // Apply damping and external torque if rb.is_dynamic() { + // Apply damping + if let Some(damping) = ang_damping { + ang_vel.0 *= 1.0 / (1.0 + sub_dt.0 * damping.0); + } + ang_vel.0 += sub_dt.0 * inverse_inertia.0 * external_torque.0; } @@ -96,8 +116,16 @@ fn integrate_rot( mut bodies: Query>, sub_dt: Res, ) { - for (rb, mut rot, mut prev_rot, mut ang_vel, external_torque, inertia, inverse_inertia) in - &mut bodies + for ( + rb, + mut rot, + mut prev_rot, + mut ang_vel, + ang_damping, + external_torque, + inertia, + inverse_inertia, + ) in &mut bodies { prev_rot.0 = *rot; @@ -105,8 +133,13 @@ fn integrate_rot( continue; } - // Apply external torque + // Apply damping and external torque if rb.is_dynamic() { + // Apply damping + if let Some(damping) = ang_damping { + ang_vel.0 *= 1.0 / (1.0 + sub_dt.0 * damping.0); + } + let delta_ang_vel = sub_dt.0 * inverse_inertia.rotated(&rot).0 * (external_torque.0 - ang_vel.0.cross(inertia.rotated(&rot).0 * ang_vel.0)); diff --git a/src/plugins/setup.rs b/src/plugins/setup.rs index 77de991f..2b091f8d 100644 --- a/src/plugins/setup.rs +++ b/src/plugins/setup.rs @@ -64,6 +64,8 @@ impl Plugin for PhysicsSetupPlugin { .register_type::() .register_type::() .register_type::() + .register_type::() + .register_type::() .register_type::() .register_type::() .register_type::()