diff options
| author | Sébastien Crozet <developer@crozet.re> | 2022-03-13 15:29:22 +0100 |
|---|---|---|
| committer | Sébastien Crozet <sebastien@crozet.re> | 2022-03-20 21:49:16 +0100 |
| commit | 8e07d8799fe40fd5c759eb9468b9f642432985f0 (patch) | |
| tree | a707e782a00de0fb6a0df84df824958edbcf57b1 /src | |
| parent | 1535db87c7e21065dfbc736ffe5927810d37fe75 (diff) | |
| download | rapier-8e07d8799fe40fd5c759eb9468b9f642432985f0.tar.gz rapier-8e07d8799fe40fd5c759eb9468b9f642432985f0.tar.bz2 rapier-8e07d8799fe40fd5c759eb9468b9f642432985f0.zip | |
Rigid-body: don’t clear forces at end of timestep + don’t wake-up a rigid-body if the modified property is equal to the old value.
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynamics/rigid_body.rs | 437 | ||||
| -rw-r--r-- | src/dynamics/rigid_body_components.rs | 65 | ||||
| -rw-r--r-- | src/pipeline/physics_pipeline.rs | 22 |
3 files changed, 300 insertions, 224 deletions
diff --git a/src/dynamics/rigid_body.rs b/src/dynamics/rigid_body.rs index 1b08b50..d37994c 100644 --- a/src/dynamics/rigid_body.rs +++ b/src/dynamics/rigid_body.rs @@ -1,7 +1,7 @@ use crate::dynamics::{ - MassProperties, RigidBodyActivation, RigidBodyCcd, RigidBodyChanges, RigidBodyColliders, - RigidBodyDamping, RigidBodyDominance, RigidBodyForces, RigidBodyIds, RigidBodyMassProps, - RigidBodyMassPropsFlags, RigidBodyPosition, RigidBodyType, RigidBodyVelocity, + LockedAxes, MassProperties, RigidBodyActivation, RigidBodyCcd, RigidBodyChanges, + RigidBodyColliders, RigidBodyDamping, RigidBodyDominance, RigidBodyForces, RigidBodyIds, + RigidBodyMassProps, RigidBodyPosition, RigidBodyType, RigidBodyVelocity, }; use crate::geometry::{ Collider, ColliderHandle, ColliderMassProps, ColliderParent, ColliderPosition, ColliderShape, @@ -111,6 +111,10 @@ impl RigidBody { if status != self.rb_type { self.changes.insert(RigidBodyChanges::TYPE); self.rb_type = status; + + if status == RigidBodyType::Static { + self.rb_vels = RigidBodyVelocity::zero(); + } } } @@ -130,22 +134,34 @@ impl RigidBody { } #[inline] + pub fn set_locked_axes(&mut self, locked_axes: LockedAxes, wake_up: bool) { + if locked_axes != self.rb_mprops.flags { + if self.is_dynamic() && wake_up { + self.wake_up(true); + } + + self.rb_mprops.flags = locked_axes; + self.update_world_mass_properties(); + } + } + + #[inline] /// Locks or unlocks all the rotations of this rigid-body. pub fn lock_rotations(&mut self, locked: bool, wake_up: bool) { - if self.is_dynamic() { - if wake_up { + if !self.rb_mprops.flags.contains(LockedAxes::ROTATION_LOCKED) { + if self.is_dynamic() && wake_up { self.wake_up(true); } self.rb_mprops .flags - .set(RigidBodyMassPropsFlags::ROTATION_LOCKED_X, locked); + .set(LockedAxes::ROTATION_LOCKED_X, locked); self.rb_mprops .flags - .set(RigidBodyMassPropsFlags::ROTATION_LOCKED_Y, locked); + .set(LockedAxes::ROTATION_LOCKED_Y, locked); self.rb_mprops .flags - .set(RigidBodyMassPropsFlags::ROTATION_LOCKED_Z, locked); + .set(LockedAxes::ROTATION_LOCKED_Z, locked); self.update_world_mass_properties(); } } @@ -159,23 +175,23 @@ impl RigidBody { allow_rotations_z: bool, wake_up: bool, ) { - if self.is_dynamic() { - if wake_up { + if self.rb_mprops.flags.contains(LockedAxes::ROTATION_LOCKED_X) != !allow_rotations_x + || self.rb_mprops.flags.contains(LockedAxes::ROTATION_LOCKED_Y) != !allow_rotations_y + || self.rb_mprops.flags.contains(LockedAxes::ROTATION_LOCKED_Z) != !allow_rotations_z + { + if self.is_dynamic() && wake_up { self.wake_up(true); } - self.rb_mprops.flags.set( - RigidBodyMassPropsFlags::ROTATION_LOCKED_X, - !allow_rotations_x, - ); - self.rb_mprops.flags.set( - RigidBodyMassPropsFlags::ROTATION_LOCKED_Y, - !allow_rotations_y, - ); - self.rb_mprops.flags.set( - RigidBodyMassPropsFlags::ROTATION_LOCKED_Z, - !allow_rotations_z, - ); + self.rb_mprops + .flags + .set(LockedAxes::ROTATION_LOCKED_X, !allow_rotations_x); + self.rb_mprops + .flags + .set(LockedAxes::ROTATION_LOCKED_Y, !allow_rotations_y); + self.rb_mprops + .flags + .set(LockedAxes::ROTATION_LOCKED_Z, !allow_rotations_z); self.update_world_mass_properties(); } } @@ -183,14 +199,18 @@ impl RigidBody { #[inline] /// Locks or unlocks all the rotations of this rigid-body. pub fn lock_translations(&mut self, locked: bool, wake_up: bool) { - if self.is_dynamic() { - if wake_up { + if !self + .rb_mprops + .flags + .contains(LockedAxes::TRANSLATION_LOCKED) + { + if self.is_dynamic() && wake_up { self.wake_up(true); } self.rb_mprops .flags - .set(RigidBodyMassPropsFlags::TRANSLATION_LOCKED, locked); + .set(LockedAxes::TRANSLATION_LOCKED, locked); self.update_world_mass_properties(); } } @@ -204,35 +224,65 @@ impl RigidBody { #[cfg(feature = "dim3")] allow_translation_z: bool, wake_up: bool, ) { - if self.is_dynamic() { - if wake_up { - self.wake_up(true); - } + #[cfg(feature = "dim2")] + if self + .rb_mprops + .flags + .contains(LockedAxes::TRANSLATION_LOCKED_X) + == !allow_translation_x + && self + .rb_mprops + .flags + .contains(LockedAxes::TRANSLATION_LOCKED_Y) + == !allow_translation_y + { + // Nothing to change. + return; + } + #[cfg(feature = "dim3")] + if self + .rb_mprops + .flags + .contains(LockedAxes::TRANSLATION_LOCKED_X) + == !allow_translation_x + && self + .rb_mprops + .flags + .contains(LockedAxes::TRANSLATION_LOCKED_Y) + == !allow_translation_y + && self + .rb_mprops + .flags + .contains(LockedAxes::TRANSLATION_LOCKED_Z) + == !allow_translation_z + { + // Nothing to change. + return; + } - self.rb_mprops.flags.set( - RigidBodyMassPropsFlags::TRANSLATION_LOCKED_X, - !allow_translation_x, - ); - self.rb_mprops.flags.set( - RigidBodyMassPropsFlags::TRANSLATION_LOCKED_Y, - !allow_translation_y, - ); - #[cfg(feature = "dim3")] - self.rb_mprops.flags.set( - RigidBodyMassPropsFlags::TRANSLATION_LOCKED_Z, - !allow_translation_z, - ); - self.update_world_mass_properties(); + if self.is_dynamic() && wake_up { + self.wake_up(true); } + + self.rb_mprops + .flags + .set(LockedAxes::TRANSLATION_LOCKED_X, !allow_translation_x); + self.rb_mprops + .flags + .set(LockedAxes::TRANSLATION_LOCKED_Y, !allow_translation_y); + #[cfg(feature = "dim3")] + self.rb_mprops + .flags + .set(LockedAxes::TRANSLATION_LOCKED_Z, !allow_translation_z); + self.update_world_mass_properties(); } /// Are the translations of this rigid-body locked? #[cfg(feature = "dim2")] pub fn is_translation_locked(&self) -> bool { - self.rb_mprops.flags.contains( - RigidBodyMassPropsFlags::TRANSLATION_LOCKED_X - | RigidBodyMassPropsFlags::TRANSLATION_LOCKED_Y, - ) + self.rb_mprops + .flags + .contains(LockedAxes::TRANSLATION_LOCKED_X | LockedAxes::TRANSLATION_LOCKED_Y) } /// Are the translations of this rigid-body locked? @@ -240,30 +290,22 @@ impl RigidBody { pub fn is_translation_locked(&self) -> bool { self.rb_mprops .flags - .contains(RigidBodyMassPropsFlags::TRANSLATION_LOCKED) + .contains(LockedAxes::TRANSLATION_LOCKED) } /// Are the rotations of this rigid-body locked? #[cfg(feature = "dim2")] pub fn is_rotation_locked(&self) -> bool { - self.rb_mprops - .flags - .contains(RigidBodyMassPropsFlags::ROTATION_LOCKED_Z) + self.rb_mprops.flags.contains(LockedAxes::ROTATION_LOCKED_Z) } /// Returns `true` for each rotational degrees of freedom locked on this rigid-body. #[cfg(feature = "dim3")] pub fn is_rotation_locked(&self) -> [bool; 3] { [ - self.rb_mprops - .flags - .contains(RigidBodyMassPropsFlags::ROTATION_LOCKED_X), - self.rb_mprops - .flags - .contains(RigidBodyMassPropsFlags::ROTATION_LOCKED_Y), - self.rb_mprops - .flags - .contains(RigidBodyMassPropsFlags::ROTATION_LOCKED_Z), + self.rb_mprops.flags.contains(LockedAxes::ROTATION_LOCKED_X), + self.rb_mprops.flags.contains(LockedAxes::ROTATION_LOCKED_Y), + self.rb_mprops.flags.contains(LockedAxes::ROTATION_LOCKED_Z), ] } @@ -300,12 +342,14 @@ impl RigidBody { /// put to sleep because it did not move for a while. #[inline] pub fn set_mass_properties(&mut self, props: MassProperties, wake_up: bool) { - if self.is_dynamic() && wake_up { - self.wake_up(true); - } + if self.rb_mprops.local_mprops != props { + if self.is_dynamic() && wake_up { + self.wake_up(true); + } - self.rb_mprops.local_mprops = props; - self.update_world_mass_properties(); + self.rb_mprops.local_mprops = props; + self.update_world_mass_properties(); + } } /// The handles of colliders attached to this rigid body. @@ -357,12 +401,14 @@ impl RigidBody { /// Sets the gravity scale facter for this rigid-body. pub fn set_gravity_scale(&mut self, scale: Real, wake_up: bool) { - if wake_up && self.rb_activation.sleeping { - self.changes.insert(RigidBodyChanges::SLEEP); - self.rb_activation.sleeping = false; - } + if self.rb_forces.gravity_scale != scale { + if wake_up && self.rb_activation.sleeping { + self.changes.insert(RigidBodyChanges::SLEEP); + self.rb_activation.sleeping = false; + } - self.rb_forces.gravity_scale = scale; + self.rb_forces.gravity_scale = scale; + } } /// The dominance group of this rigid-body. @@ -473,10 +519,19 @@ impl RigidBody { /// If `wake_up` is `true` then the rigid-body will be woken up if it was /// put to sleep because it did not move for a while. pub fn set_linvel(&mut self, linvel: Vector<Real>, wake_up: bool) { - self.rb_vels.linvel = linvel; - - if self.is_dynamic() && wake_up { - self.wake_up(true) + if self.rb_vels.linvel != linvel { + match self.rb_type { + RigidBodyType::Dynamic => { + self.rb_vels.linvel = linvel; + if wake_up { + self.wake_up(true) + } + } + RigidBodyType::KinematicVelocityBased => { + self.rb_vels.linvel = linvel; + } + RigidBodyType::Static | RigidBodyType::KinematicPositionBased => {} + } } } @@ -486,10 +541,19 @@ impl RigidBody { /// put to sleep because it did not move for a while. #[cfg(feature = "dim2")] pub fn set_angvel(&mut self, angvel: Real, wake_up: bool) { - self.rb_vels.angvel = angvel; - - if self.is_dynamic() && wake_up { - self.wake_up(true) + if self.rb_vels.angvel != angvel { + match self.rb_type { + RigidBodyType::Dynamic => { + self.rb_vels.angvel = angvel; + if wake_up { + self.wake_up(true) + } + } + RigidBodyType::KinematicVelocityBased => { + self.rb_vels.angvel = angvel; + } + RigidBodyType::Static | RigidBodyType::KinematicPositionBased => {} + } } } @@ -499,10 +563,19 @@ impl RigidBody { /// put to sleep because it did not move for a while. #[cfg(feature = "dim3")] pub fn set_angvel(&mut self, angvel: Vector<Real>, wake_up: bool) { - self.rb_vels.angvel = angvel; - - if self.is_dynamic() && wake_up { - self.wake_up(true) + if self.rb_vels.angvel != angvel { + match self.rb_type { + RigidBodyType::Dynamic => { + self.rb_vels.angvel = angvel; + if wake_up { + self.wake_up(true) + } + } + RigidBodyType::KinematicVelocityBased => { + self.rb_vels.angvel = angvel; + } + RigidBodyType::Static | RigidBodyType::KinematicPositionBased => {} + } } } @@ -521,13 +594,17 @@ impl RigidBody { /// Sets the translational part of this rigid-body's position. #[inline] pub fn set_translation(&mut self, translation: Vector<Real>, wake_up: bool) { - self.changes.insert(RigidBodyChanges::POSITION); - self.rb_pos.position.translation.vector = translation; - self.rb_pos.next_position.translation.vector = translation; - - // TODO: Do we really need to check that the body isn't dynamic? - if wake_up && self.is_dynamic() { - self.wake_up(true) + if self.rb_pos.position.translation.vector != translation + || self.rb_pos.next_position.translation.vector != translation + { + self.changes.insert(RigidBodyChanges::POSITION); + self.rb_pos.position.translation.vector = translation; + self.rb_pos.next_position.translation.vector = translation; + + // TODO: Do we really need to check that the body isn't dynamic? + if wake_up && self.is_dynamic() { + self.wake_up(true) + } } } @@ -540,14 +617,19 @@ impl RigidBody { /// Sets the rotational part of this rigid-body's position. #[inline] pub fn set_rotation(&mut self, rotation: AngVector<Real>, wake_up: bool) { - self.changes.insert(RigidBodyChanges::POSITION); let rotation = Rotation::new(rotation); - self.rb_pos.position.rotation = rotation; - self.rb_pos.next_position.rotation = rotation; - // TODO: Do we really need to check that the body isn't dynamic? - if wake_up && self.is_dynamic() { - self.wake_up(true) + if self.rb_pos.position.rotation != rotation + || self.rb_pos.next_position.rotation != rotation + { + self.changes.insert(RigidBodyChanges::POSITION); + self.rb_pos.position.rotation = rotation; + self.rb_pos.next_position.rotation = rotation; + + // TODO: Do we really need to check that the body isn't dynamic? + if wake_up && self.is_dynamic() { + self.wake_up(true) + } } } @@ -561,13 +643,15 @@ impl RigidBody { /// If `wake_up` is `true` then the rigid-body will be woken up if it was /// put to sleep because it did not move for a while. pub fn set_position(&mut self, pos: Isometry<Real>, wake_up: bool) { - self.changes.insert(RigidBodyChanges::POSITION); - self.rb_pos.position = pos; - self.rb_pos.next_position = pos; + if self.rb_pos.position != pos || self.rb_pos.next_position != pos { + self.changes.insert(RigidBodyChanges::POSITION); + self.rb_pos.position = pos; + self.rb_pos.next_position = pos; - // TODO: Do we really need to check that the body isn't dynamic? - if wake_up && self.is_dynamic() { - self.wake_up(true) + // TODO: Do we really need to check that the body isn't dynamic? + if wake_up && self.is_dynamic() { + self.wake_up(true) + } } } @@ -611,12 +695,10 @@ impl RigidBody { /// ## Applying forces and torques impl RigidBody { - /// Applies a force at the center-of-mass of this rigid-body. - /// The force will be applied in the next simulation step. - /// This does nothing on non-dynamic bodies. - pub fn apply_force(&mut self, force: Vector<Real>, wake_up: bool) { - if self.rb_type == RigidBodyType::Dynamic { - self.rb_forces.force += force; + /// Resets to zero all the constant (linear) forces applied to this rigid-body. + pub fn reset_force(&mut self, wake_up: bool) { + if !self.rb_forces.user_force.is_zero() { + self.rb_forces.user_force = na::zero(); if wake_up { self.wake_up(true); @@ -624,13 +706,10 @@ impl RigidBody { } } - /// Applies a torque at the center-of-mass of this rigid-body. - /// The torque will be applied in the next simulation step. - /// This does nothing on non-dynamic bodies. - #[cfg(feature = "dim2")] - pub fn apply_torque(&mut self, torque: Real, wake_up: bool) { - if self.rb_type == RigidBodyType::Dynamic { - self.rb_forces.torque += torque; + /// Resets to zero all the constant torques applied to this rigid-body. + pub fn reset_torque(&mut self, wake_up: bool) { + if !self.rb_forces.user_torque.is_zero() { + self.rb_forces.user_torque = na::zero(); if wake_up { self.wake_up(true); @@ -638,30 +717,65 @@ impl RigidBody { } } - /// Applies a torque at the center-of-mass of this rigid-body. - /// The torque will be applied in the next simulation step. + /// Adds to this rigid-body a constant force applied at its center-of-mass.ç + /// /// This does nothing on non-dynamic bodies. - #[cfg(feature = "dim3")] - pub fn apply_torque(&mut self, torque: Vector<Real>, wake_up: bool) { - if self.rb_type == RigidBodyType::Dynamic { - self.rb_forces.torque += torque; + pub fn add_force(&mut self, force: Vector<Real>, wake_up: bool) { + if !force.is_zero() { + if self.rb_type == RigidBodyType::Dynamic { + self.rb_forces.user_force += force; + + if wake_up { + self.wake_up(true); + } + } + } + } - if wake_up { - self.wake_up(true); + /// Adds to this rigid-body a constant torque at its center-of-mass. + /// + /// This does nothing on non-dynamic bodies. + #[cfg(feature = "dim2")] + pub fn add_torque(&mut self, torque: Real, wake_up: bool) { + if !torque.is_zero() { + if self.rb_type == RigidBodyType::Dynamic { + self.rb_forces.user_torque += torque; + + if wake_up { + self.wake_up(true); + } } } } - /// Applies a force at the given world-space point of this rigid-body. - /// The force will be applied in the next simulation step. + /// Adds to this rigid-body a constant torque at its center-of-mass. + /// /// This does nothing on non-dynamic bodies. - pub fn apply_force_at_point(&mut self, force: Vector<Real>, point: Point<Real>, wake_up: bool) { - if self.rb_type == RigidBodyType::Dynamic { - self.rb_forces.force += force; - self.rb_forces.torque += (point - self.rb_mprops.world_com).gcross(force); + #[cfg(feature = "dim3")] + pub fn add_torque(&mut self, torque: Vector<Real>, wake_up: bool) { + if !torque.is_zero() { + if self.rb_type == RigidBodyType::Dynamic { + self.rb_forces.user_torque += torque; + + if wake_up { + self.wake_up(true); + } + } + } + } - if wake_up { - self.wake_up(true); + /// Adds to this rigid-body a constant force at the given world-space point of this rigid-body. + /// + /// This does nothing on non-dynamic bodies. + pub fn add_force_at_point(&mut self, force: Vector<Real>, point: Point<Real>, wake_up: bool) { + if !force.is_zero() { + if self.rb_type == RigidBodyType::Dynamic { + self.rb_forces.user_force += force; + self.rb_forces.user_torque += (point - self.rb_mprops.world_com).gcross(force); + + if wake_up { + self.wake_up(true); + } } } } @@ -673,7 +787,7 @@ impl RigidBody { /// The impulse is applied right away, changing the linear velocity. /// This does nothing on non-dynamic bodies. pub fn apply_impulse(&mut self, impulse: Vector<Real>, wake_up: bool) { - if self.rb_type == RigidBodyType::Dynamic { + if !impulse.is_zero() && self.rb_type == RigidBodyType::Dynamic { self.rb_vels.linvel += impulse.component_mul(&self.rb_mprops.effective_inv_mass); if wake_up { @@ -687,7 +801,7 @@ impl RigidBody { /// This does nothing on non-dynamic bodies. #[cfg(feature = "dim2")] pub fn apply_torque_impulse(&mut self, torque_impulse: Real, wake_up: bool) { - if self.rb_type == RigidBodyType::Dynamic { + if !torque_impulse.is_zero() && self.rb_type == RigidBodyType::Dynamic { self.rb_vels.angvel += self.rb_mprops.effective_world_inv_inertia_sqrt * (self.rb_mprops.effective_world_inv_inertia_sqrt * torque_impulse); @@ -702,7 +816,7 @@ impl RigidBody { /// This does nothing on non-dynamic bodies. #[cfg(feature = "dim3")] pub fn apply_torque_impulse(&mut self, torque_impulse: Vector<Real>, wake_up: bool) { - if self.rb_type == RigidBodyType::Dynamic { + if !torque_impulse.is_zero() && self.rb_type == RigidBodyType::Dynamic { self.rb_vels.angvel += self.rb_mprops.effective_world_inv_inertia_sqrt * (self.rb_mprops.effective_world_inv_inertia_sqrt * torque_impulse); @@ -772,7 +886,7 @@ pub struct RigidBodyBuilder { /// Damping factor for gradually slowing down the angular motion of the rigid-body, `0.0` by default. pub angular_damping: Real, rb_type: RigidBodyType, - mprops_flags: RigidBodyMassPropsFlags, + mprops_flags: LockedAxes, /// The additional mass properties of the rigid-body being built. See [`RigidBodyBuilder::additional_mass_properties`] for more information. pub mass_properties: MassProperties, /// Whether or not the rigid-body to be created can sleep if it reaches a dynamic equilibrium. @@ -800,7 +914,7 @@ impl RigidBodyBuilder { linear_damping: 0.0, angular_damping: 0.0, rb_type, - mprops_flags: RigidBodyMassPropsFlags::empty(), + mprops_flags: LockedAxes::empty(), mass_properties: MassProperties::zero(), can_sleep: true, sleeping: false, @@ -881,10 +995,14 @@ impl RigidBodyBuilder { self } + pub fn locked_axes(mut self, locked_axes: LockedAxes) -> Self { + self.mprops_flags = locked_axes; + self + } + /// Prevents this rigid-body from translating because of forces. pub fn lock_translations(mut self) -> Self { - self.mprops_flags - .set(RigidBodyMassPropsFlags::TRANSLATION_LOCKED, true); + self.mprops_flags.set(LockedAxes::TRANSLATION_LOCKED, true); self } @@ -895,30 +1013,21 @@ impl RigidBodyBuilder { allow_translations_y: bool, #[cfg(feature = "dim3")] allow_translations_z: bool, ) -> Self { - self.mprops_flags.set( - RigidBodyMassPropsFlags::TRANSLATION_LOCKED_X, - !allow_translations_x, - ); - self.mprops_flags.set( - RigidBodyMassPropsFlags::TRANSLATION_LOCKED_Y, - !allow_translations_y, - ); + self.mprops_flags + .set(LockedAxes::TRANSLATION_LOCKED_X, !allow_translations_x); + self.mprops_flags + .set(LockedAxes::TRANSLATION_LOCKED_Y, !allow_translations_y); #[cfg(feature = "dim3")] - self.mprops_flags.set( - RigidBodyMassPropsFlags::TRANSLATION_LOCKED_Z, - !allow_translations_z, - ); + self.mprops_flags + .set(LockedAxes::TRANSLATION_LOCKED_Z, !allow_translations_z); self } /// Prevents this rigid-body from rotating because of forces. pub fn lock_rotations(mut self) -> Self { - self.mprops_flags - .set(RigidBodyMassPropsFlags::ROTATION_LOCKED_X, true); - self.mprops_flags - .set(RigidBodyMassPropsFlags::ROTATION_LOCKED_Y, true); - self.mprops_flags - .set(RigidBodyMassPropsFlags::ROTATION_LOCKED_Z, true); + self.mprops_flags.set(LockedAxes::ROTATION_LOCKED_X, true); + self.mprops_flags.set(LockedAxes::ROTATION_LOCKED_Y, true); + self.mprops_flags.set(LockedAxes::ROTATION_LOCKED_Z, true); self } @@ -930,18 +1039,12 @@ impl RigidBodyBuilder { allow_rotations_y: bool, allow_rotations_z: bool, ) -> Self { - self.mprops_flags.set( - RigidBodyMassPropsFlags::ROTATION_LOCKED_X, - !allow_rotations_x, - ); - self.mprops_flags.set( - RigidBodyMassPropsFlags::ROTATION_LOCKED_Y, - !allow_rotations_y, - ); - self.mprops_flags.set( - RigidBodyMassPropsFlags::ROTATION_LOCKED_Z, - !allow_rotations_z, - ); + self.mprops_flags + .set(LockedAxes::ROTATION_LOCKED_X, !allow_rotations_x); + self.mprops_flags + .set(LockedAxes::ROTATION_LOCKED_Y, !allow_rotations_y); + self.mprops_flags + .set(LockedAxes::ROTATION_LOCKED_Z, !allow_rotations_z); self } diff --git a/src/dynamics/rigid_body_components.rs b/src/dynamics/rigid_body_components.rs index c7542d1..4bfaa28 100644 --- a/src/dynamics/rigid_body_components.rs +++ b/src/dynamics/rigid_body_components.rs @@ -202,7 +202,8 @@ where bitflags::bitflags! { #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] /// Flags affecting the behavior of the constraints solver for a given contact manifold. - pub struct RigidBodyMassPropsFlags: u8 { + // FIXME: rename this to LockedAxes + pub struct LockedAxes: u8 { /// Flag indicating that the rigid-body cannot translate along the `X` axis. const TRANSLATION_LOCKED_X = 1 << 0; /// Flag indicating that the rigid-body cannot translate along the `Y` axis. @@ -228,7 +229,7 @@ bitflags::bitflags! { /// The mass properties of this rigid-bodies. pub struct RigidBodyMassProps { /// Flags for locking rotation and translation. - pub flags: RigidBodyMassPropsFlags, + pub flags: LockedAxes, /// The local mass properties of the rigid-body. pub local_mprops: MassProperties, /// The world-space center of mass of the rigid-body. @@ -243,7 +244,7 @@ pub struct RigidBodyMassProps { impl Default for RigidBodyMassProps { fn default() -> Self { Self { - flags: RigidBodyMassPropsFlags::empty(), + flags: LockedAxes::empty(), local_mprops: MassProperties::zero(), world_com: Point::origin(), effective_inv_mass: Vector::zero(), @@ -252,8 +253,8 @@ impl Default for RigidBodyMassProps { } } -impl From<RigidBodyMassPropsFlags> for RigidBodyMassProps { - fn from(flags: RigidBodyMassPropsFlags) -> Self { +impl From<LockedAxes> for RigidBodyMassProps { + fn from(flags: LockedAxes) -> Self { Self { flags, ..Self::default() @@ -299,60 +300,39 @@ impl RigidBodyMassProps { self.local_mprops.world_inv_inertia_sqrt(&position.rotation); // Take into account translation/rotation locking. - if self - .flags - .contains(RigidBodyMassPropsFlags::TRANSLATION_LOCKED_X) - { + if self.flags.contains(LockedAxes::TRANSLATION_LOCKED_X) { self.effective_inv_mass.x = 0.0; } - if self - .flags - .contains(RigidBodyMassPropsFlags::TRANSLATION_LOCKED_Y) - { + if self.flags.contains(LockedAxes::TRANSLATION_LOCKED_Y) { self.effective_inv_mass.y = 0.0; } #[cfg(feature = "dim3")] - if self - .flags - .contains(RigidBodyMassPropsFlags::TRANSLATION_LOCKED_Z) - { + if self.flags.contains(LockedAxes::TRANSLATION_LOCKED_Z) { self.effective_inv_mass.z = 0.0; } #[cfg(feature = "dim2")] { - if self - .flags - .contains(RigidBodyMassPropsFlags::ROTATION_LOCKED_Z) - { + if self.flags.contains(LockedAxes::ROTATION_LOCKED_Z) { self.effective_world_inv_inertia_sqrt = 0.0; } } #[cfg(feature = "dim3")] { - if self - .flags - .contains(RigidBodyMassPropsFlags::ROTATION_LOCKED_X) - { + if self.flags.contains(LockedAxes::ROTATION_LOCKED_X) { self.effective_world_inv_inertia_sqrt.m11 = 0.0; self.effective_world_inv_inertia_sqrt.m12 = 0.0; self.effective_world_inv_inertia_sqrt.m13 = 0.0; } - if self - .flags - .contains(RigidBodyMassPropsFlags::ROTATION_LOCKED_Y) - { + if self.flags.contains(LockedAxes::ROTATION_LOCKED_Y) { self.effective_world_inv_inertia_sqrt.m22 = 0.0; self.effective_world_inv_inertia_sqrt.m12 = 0.0; self.effective_world_inv_inertia_sqrt.m23 = 0.0; } - if self - .flags - .contains(RigidBodyMassPropsFlags::ROTATION_LOCKED_Z) - { + if self.flags.contains(LockedAxes::ROTATION_LOCKED_Z) { self.effective_world_inv_inertia_sqrt.m33 = 0.0; self.effective_world_inv_inertia_sqrt.m13 = 0.0; self.effective_world_inv_inertia_sqrt.m23 = 0.0; @@ -659,6 +639,10 @@ pub struct RigidBodyForces { /// Gravity is multiplied by this scaling factor before it's /// applied to this rigid-body. pub gravity_scale: Real, + // Forces applied by the user. + pub user_force: Vector<Real>, + // Torque applied by the user. + pub user_torque: AngVector<Real>, } impl Default for RigidBodyForces { @@ -667,6 +651,8 @@ impl Default for RigidBodyForces { force: na::zero(), torque: na::zero(), gravity_scale: 1.0, + user_force: na::zero(), + user_torque: na::zero(), } } } @@ -692,8 +678,13 @@ impl RigidBodyForces { /// Adds to `self` the gravitational force that would result in a gravitational acceleration /// equal to `gravity`. - pub fn add_gravity_acceleration(&mut self, gravity: &Vector<Real>, mass: &Vector<Real>) { - self.force += gravity.component_mul(&mass) * self.gravity_scale; + pub fn compute_effective_force_and_torque( + &mut self, + gravity: &Vector<Real>, + mass: &Vector<Real>, + ) { + self.force = self.user_force + gravity.component_mul(&mass) * self.gravity_scale; + self.torque = self.user_torque; } /// Applies a force at the given world-space point of the rigid-body with the given mass properties. @@ -703,8 +694,8 @@ impl RigidBodyForces { force: Vector<Real>, point: Point<Real>, ) { - self.force += force; - self.torque += (point - rb_mprops.world_com).gcross(force); + self.user_force += force; + self.user_torque += (point - rb_mprops.world_com).gcross(force); } } diff --git a/src/pipeline/physics_pipeline.rs b/src/pipeline/physics_pipeline.rs index 9992ea0..894cbaf 100644 --- a/src/pipeline/physics_pipeline.rs +++ b/src/pipeline/physics_pipeline.rs @@ -224,7 +224,7 @@ impl PhysicsPipeline { }) .unwrap(); bodies.map_mut_internal(handle.0, |forces: &mut RigidBodyForces| { - forces.add_gravity_acceleration(&gravity, &effective_inv_mass) + forces.compute_effective_force_and_torque(&gravity, &effective_inv_mass) }); } @@ -355,7 +355,6 @@ impl PhysicsPipeline { bodies: &mut Bodies, colliders: &mut Colliders, modified_colliders: &mut Vec<ColliderHandle>, - clear_forces: bool, ) where Bodies: ComponentSetMut<RigidBodyVelocity> + ComponentSetMut<RigidBodyForces> @@ -369,16 +368,6 @@ impl PhysicsPipeline { // Set the rigid-bodies and kinematic bodies to their final position. for handle in islands.iter_active_bodies() { let status: &RigidBodyType = bodies.index(handle.0); - if status.is_kinematic() { - bodies.set_internal(handle.0, RigidBodyVelocity::zero()); - } - - if clear_forces { - bodies.map_mut_internal(handle.0, |f: &mut RigidBodyForces| { - f.torque = na::zero(); - f.force = na::zero(); - }); - } bodies.map_mut_internal(handle.0, |poss: &mut RigidBodyPosition| { poss.position = poss.next_position @@ -666,14 +655,7 @@ impl PhysicsPipeline { } } - let clear_forces = remaining_substeps == 0; - self.advance_to_final_positions( - islands, - bodies, - colliders, - modified_colliders, - clear_forces, - ); + self.advance_to_final_positions(islands, bodies, colliders, modified_colliders); self.detect_collisions( &integration_parameters, |
