From e231bacec608fa5efd24f7a876572927dbd6c9c4 Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Thu, 17 Dec 2020 10:24:36 +0100 Subject: Move all the contact manifold computations out of Rapier. --- src/geometry/contact_pair.rs | 292 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 292 insertions(+) create mode 100644 src/geometry/contact_pair.rs (limited to 'src/geometry/contact_pair.rs') diff --git a/src/geometry/contact_pair.rs b/src/geometry/contact_pair.rs new file mode 100644 index 0000000..ba5da2a --- /dev/null +++ b/src/geometry/contact_pair.rs @@ -0,0 +1,292 @@ +use crate::dynamics::{BodyPair, RigidBodyHandle, RigidBodySet}; +use crate::geometry::{Collider, ColliderPair, ColliderSet, Contact, ContactManifold}; +use crate::math::{Isometry, Point, Vector}; +use eagl::query::ContactManifoldsWorkspace; +use eagl::utils::MaybeSerializableData; +#[cfg(feature = "simd-is-enabled")] +use { + crate::math::{SimdReal, SIMD_WIDTH}, + simba::simd::SimdValue, +}; + +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 SolverFlags: u32 { + /// The constraint solver will take this contact manifold into + /// account for force computation. + const COMPUTE_IMPULSES = 0b01; + } +} + +#[cfg(feature = "simd-is-enabled")] +pub(crate) struct WContact { + pub local_p1: Point, + pub local_p2: Point, + pub local_n1: Vector, + pub local_n2: Vector, + pub dist: SimdReal, + pub fid1: [u8; SIMD_WIDTH], + pub fid2: [u8; SIMD_WIDTH], +} + +#[cfg(feature = "simd-is-enabled")] +impl WContact { + pub fn extract(&self, i: usize) -> (Contact, Vector, Vector) { + let c = Contact { + local_p1: self.local_p1.extract(i), + local_p2: self.local_p2.extract(i), + dist: self.dist.extract(i), + fid1: self.fid1[i], + fid2: self.fid2[i], + data: ContactData::default(), + }; + + (c, self.local_n1.extract(i), self.local_n2.extract(i)) + } +} + +#[derive(Copy, Clone, Debug)] +#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] +/// A single contact between two collider. +pub struct ContactData { + /// The impulse, along the contact normal, applied by this contact to the first collider's rigid-body. + /// + /// The impulse applied to the second collider's rigid-body is given by `-impulse`. + pub impulse: f32, + /// The friction impulse along the vector orthonormal to the contact normal, applied to the first + /// collider's rigid-body. + #[cfg(feature = "dim2")] + pub tangent_impulse: f32, + /// The friction impulses along the basis orthonormal to the contact normal, applied to the first + /// collider's rigid-body. + #[cfg(feature = "dim3")] + pub tangent_impulse: [f32; 2], +} + +impl ContactData { + #[cfg(feature = "dim2")] + pub(crate) fn zero_tangent_impulse() -> f32 { + 0.0 + } + + #[cfg(feature = "dim3")] + pub(crate) fn zero_tangent_impulse() -> [f32; 2] { + [0.0, 0.0] + } +} + +impl Default for ContactData { + fn default() -> Self { + Self { + impulse: 0.0, + tangent_impulse: Self::zero_tangent_impulse(), + } + } +} + +#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] +#[derive(Clone)] +/// The description of all the contacts between a pair of colliders. +pub struct ContactPair { + /// The pair of colliders involved. + pub pair: ColliderPair, + /// The set of contact manifolds between the two colliders. + /// + /// All contact manifold contain themselves contact points between the colliders. + pub manifolds: Vec, + pub(crate) workspace: Option, +} + +impl ContactPair { + pub(crate) fn new(pair: ColliderPair) -> Self { + Self { + pair, + manifolds: Vec::new(), + workspace: None, + } + } + + /// Does this contact pair have any active contact? + /// + /// An active contact is a contact that may result in a non-zero contact force. + pub fn has_any_active_contact(&self) -> bool { + for manifold in &self.manifolds { + if manifold.num_active_contacts != 0 { + return true; + } + } + + false + } + + pub(crate) fn single_manifold<'a, 'b>( + &'a mut self, + colliders: &'b ColliderSet, + flags: SolverFlags, + ) -> ( + &'b Collider, + &'b Collider, + &'a mut ContactManifold, + Option<&'a mut (dyn MaybeSerializableData)>, + ) { + let coll1 = &colliders[self.pair.collider1]; + let coll2 = &colliders[self.pair.collider2]; + + if self.manifolds.len() == 0 { + let manifold_data = ContactManifoldData::from_colliders(self.pair, coll1, coll2, flags); + self.manifolds + .push(ContactManifold::with_data((0, 0), manifold_data)); + } + + // We have to make sure the order of the returned collider + // match the order of the pair stored inside of the manifold. + // (This order can be modified by the contact determination algorithm). + let manifold = &mut self.manifolds[0]; + if manifold.data.pair.collider1 == self.pair.collider1 { + ( + coll1, + coll2, + manifold, + self.workspace.as_mut().map(|w| &mut *w.0), + ) + } else { + ( + coll2, + coll1, + manifold, + self.workspace.as_mut().map(|w| &mut *w.0), + ) + } + } +} + +#[derive(Clone, Debug)] +#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] +/// A contact manifold between two colliders. +/// +/// A contact manifold describes a set of contacts between two colliders. All the contact +/// part of the same contact manifold share the same contact normal and contact kinematics. +pub struct ContactManifoldData { + // The following are set by the narrow-phase. + /// The pair of colliders involved in this contact manifold. + pub pair: ColliderPair, + /// The pair of body involved in this contact manifold. + pub body_pair: BodyPair, + pub(crate) warmstart_multiplier: f32, + // The two following are set by the constraints solver. + pub(crate) constraint_index: usize, + pub(crate) position_constraint_index: usize, + // We put the following fields here to avoids reading the colliders inside of the + // contact preparation method. + /// The friction coefficient for of all the contacts on this contact manifold. + pub friction: f32, + /// The restitution coefficient for all the contacts on this contact manifold. + pub restitution: f32, + /// The relative position between the first collider and its parent at the time the + /// contact points were generated. + pub delta1: Isometry, + /// The relative position between the second collider and its parent at the time the + /// contact points were generated. + pub delta2: Isometry, + /// Flags used to control some aspects of the constraints solver for this contact manifold. + pub solver_flags: SolverFlags, +} + +impl Default for ContactManifoldData { + fn default() -> Self { + Self::new( + ColliderPair::new(ColliderSet::invalid_handle(), ColliderSet::invalid_handle()), + BodyPair::new( + RigidBodySet::invalid_handle(), + RigidBodySet::invalid_handle(), + ), + Isometry::identity(), + Isometry::identity(), + 0.0, + 0.0, + SolverFlags::empty(), + ) + } +} + +impl ContactManifoldData { + pub(crate) fn new( + pair: ColliderPair, + body_pair: BodyPair, + delta1: Isometry, + delta2: Isometry, + friction: f32, + restitution: f32, + solver_flags: SolverFlags, + ) -> ContactManifoldData { + Self { + pair, + body_pair, + warmstart_multiplier: Self::min_warmstart_multiplier(), + friction, + restitution, + delta1, + delta2, + constraint_index: 0, + position_constraint_index: 0, + solver_flags, + } + } + + pub(crate) fn from_colliders( + pair: ColliderPair, + coll1: &Collider, + coll2: &Collider, + flags: SolverFlags, + ) -> Self { + Self::with_subshape_indices(pair, coll1, coll2, flags) + } + + pub(crate) fn with_subshape_indices( + pair: ColliderPair, + coll1: &Collider, + coll2: &Collider, + solver_flags: SolverFlags, + ) -> Self { + Self::new( + pair, + BodyPair::new(coll1.parent, coll2.parent), + *coll1.position_wrt_parent(), + *coll2.position_wrt_parent(), + (coll1.friction + coll2.friction) * 0.5, + (coll1.restitution + coll2.restitution) * 0.5, + solver_flags, + ) + } + + pub(crate) fn min_warmstart_multiplier() -> f32 { + // Multiplier used to reduce the amount of warm-starting. + // This coefficient increases exponentially over time, until it reaches 1.0. + // This will reduce significant overshoot at the timesteps that + // follow a timestep involving high-velocity impacts. + 1.0 // 0.01 + } + + pub(crate) fn update_warmstart_multiplier(manifold: &mut ContactManifold) { + // In 2D, tall stacks will actually suffer from this + // because oscillation due to inaccuracies in 2D often + // cause contacts to break, which would result in + // a reset of the warmstart multiplier. + if cfg!(feature = "dim2") { + manifold.data.warmstart_multiplier = 1.0; + return; + } + + for pt in &manifold.points { + if pt.data.impulse != 0.0 { + manifold.data.warmstart_multiplier = + (manifold.data.warmstart_multiplier * 2.0).min(1.0); + return; + } + } + + // Reset the multiplier. + manifold.data.warmstart_multiplier = Self::min_warmstart_multiplier() + } +} -- cgit From 8fe2df126a279a435cc544b150aadf8f7b757868 Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Thu, 17 Dec 2020 18:37:16 +0100 Subject: Remove some irrelevant code. --- src/geometry/contact_pair.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/geometry/contact_pair.rs') diff --git a/src/geometry/contact_pair.rs b/src/geometry/contact_pair.rs index ba5da2a..990e61c 100644 --- a/src/geometry/contact_pair.rs +++ b/src/geometry/contact_pair.rs @@ -1,8 +1,8 @@ use crate::dynamics::{BodyPair, RigidBodyHandle, RigidBodySet}; use crate::geometry::{Collider, ColliderPair, ColliderSet, Contact, ContactManifold}; use crate::math::{Isometry, Point, Vector}; -use eagl::query::ContactManifoldsWorkspace; -use eagl::utils::MaybeSerializableData; +use cdl::query::ContactManifoldsWorkspace; +use cdl::utils::MaybeSerializableData; #[cfg(feature = "simd-is-enabled")] use { crate::math::{SimdReal, SIMD_WIDTH}, -- cgit From 5876a262daa3b6544f132e6654923c2bfabe35d9 Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Wed, 30 Dec 2020 11:44:08 +0100 Subject: Remove the useless manifold.data.pair field. --- src/geometry/contact_pair.rs | 43 +++++++++---------------------------------- 1 file changed, 9 insertions(+), 34 deletions(-) (limited to 'src/geometry/contact_pair.rs') diff --git a/src/geometry/contact_pair.rs b/src/geometry/contact_pair.rs index 990e61c..7b945ae 100644 --- a/src/geometry/contact_pair.rs +++ b/src/geometry/contact_pair.rs @@ -134,30 +134,17 @@ impl ContactPair { let coll2 = &colliders[self.pair.collider2]; if self.manifolds.len() == 0 { - let manifold_data = ContactManifoldData::from_colliders(self.pair, coll1, coll2, flags); + let manifold_data = ContactManifoldData::from_colliders(coll1, coll2, flags); self.manifolds .push(ContactManifold::with_data((0, 0), manifold_data)); } - // We have to make sure the order of the returned collider - // match the order of the pair stored inside of the manifold. - // (This order can be modified by the contact determination algorithm). - let manifold = &mut self.manifolds[0]; - if manifold.data.pair.collider1 == self.pair.collider1 { - ( - coll1, - coll2, - manifold, - self.workspace.as_mut().map(|w| &mut *w.0), - ) - } else { - ( - coll2, - coll1, - manifold, - self.workspace.as_mut().map(|w| &mut *w.0), - ) - } + ( + coll1, + coll2, + &mut self.manifolds[0], + self.workspace.as_mut().map(|w| &mut *w.0), + ) } } @@ -169,8 +156,6 @@ impl ContactPair { /// part of the same contact manifold share the same contact normal and contact kinematics. pub struct ContactManifoldData { // The following are set by the narrow-phase. - /// The pair of colliders involved in this contact manifold. - pub pair: ColliderPair, /// The pair of body involved in this contact manifold. pub body_pair: BodyPair, pub(crate) warmstart_multiplier: f32, @@ -196,7 +181,6 @@ pub struct ContactManifoldData { impl Default for ContactManifoldData { fn default() -> Self { Self::new( - ColliderPair::new(ColliderSet::invalid_handle(), ColliderSet::invalid_handle()), BodyPair::new( RigidBodySet::invalid_handle(), RigidBodySet::invalid_handle(), @@ -212,7 +196,6 @@ impl Default for ContactManifoldData { impl ContactManifoldData { pub(crate) fn new( - pair: ColliderPair, body_pair: BodyPair, delta1: Isometry, delta2: Isometry, @@ -221,7 +204,6 @@ impl ContactManifoldData { solver_flags: SolverFlags, ) -> ContactManifoldData { Self { - pair, body_pair, warmstart_multiplier: Self::min_warmstart_multiplier(), friction, @@ -234,23 +216,16 @@ impl ContactManifoldData { } } - pub(crate) fn from_colliders( - pair: ColliderPair, - coll1: &Collider, - coll2: &Collider, - flags: SolverFlags, - ) -> Self { - Self::with_subshape_indices(pair, coll1, coll2, flags) + pub(crate) fn from_colliders(coll1: &Collider, coll2: &Collider, flags: SolverFlags) -> Self { + Self::with_subshape_indices(coll1, coll2, flags) } pub(crate) fn with_subshape_indices( - pair: ColliderPair, coll1: &Collider, coll2: &Collider, solver_flags: SolverFlags, ) -> Self { Self::new( - pair, BodyPair::new(coll1.parent, coll2.parent), *coll1.position_wrt_parent(), *coll2.position_wrt_parent(), -- cgit From 43628c8846c8805d2f835dda4182b7240292900c Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Wed, 30 Dec 2020 17:30:07 +0100 Subject: Try using solver contacts again, but in a more cache-coherent way. --- src/geometry/contact_pair.rs | 65 ++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 38 deletions(-) (limited to 'src/geometry/contact_pair.rs') diff --git a/src/geometry/contact_pair.rs b/src/geometry/contact_pair.rs index 7b945ae..6b0815b 100644 --- a/src/geometry/contact_pair.rs +++ b/src/geometry/contact_pair.rs @@ -1,6 +1,6 @@ use crate::dynamics::{BodyPair, RigidBodyHandle, RigidBodySet}; use crate::geometry::{Collider, ColliderPair, ColliderSet, Contact, ContactManifold}; -use crate::math::{Isometry, Point, Vector}; +use crate::math::{Isometry, Point, Real, Vector}; use cdl::query::ContactManifoldsWorkspace; use cdl::utils::MaybeSerializableData; #[cfg(feature = "simd-is-enabled")] @@ -134,7 +134,7 @@ impl ContactPair { let coll2 = &colliders[self.pair.collider2]; if self.manifolds.len() == 0 { - let manifold_data = ContactManifoldData::from_colliders(coll1, coll2, flags); + let manifold_data = ContactManifoldData::with_subshape_indices(coll1, coll2, flags); self.manifolds .push(ContactManifold::with_data((0, 0), manifold_data)); } @@ -164,18 +164,21 @@ pub struct ContactManifoldData { pub(crate) position_constraint_index: usize, // We put the following fields here to avoids reading the colliders inside of the // contact preparation method. - /// The friction coefficient for of all the contacts on this contact manifold. - pub friction: f32, - /// The restitution coefficient for all the contacts on this contact manifold. - pub restitution: f32, - /// The relative position between the first collider and its parent at the time the - /// contact points were generated. - pub delta1: Isometry, - /// The relative position between the second collider and its parent at the time the - /// contact points were generated. - pub delta2: Isometry, /// Flags used to control some aspects of the constraints solver for this contact manifold. pub solver_flags: SolverFlags, + pub normal: Vector, + pub solver_contacts: Vec, +} + +#[derive(Copy, Clone, Debug)] +#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] +pub struct SolverContact { + pub point: Point, + pub dist: Real, + pub friction: Real, + pub restitution: Real, + pub surface_velocity: Vector, + pub data: ContactData, } impl Default for ContactManifoldData { @@ -185,39 +188,32 @@ impl Default for ContactManifoldData { RigidBodySet::invalid_handle(), RigidBodySet::invalid_handle(), ), - Isometry::identity(), - Isometry::identity(), - 0.0, - 0.0, SolverFlags::empty(), ) } } impl ContactManifoldData { - pub(crate) fn new( - body_pair: BodyPair, - delta1: Isometry, - delta2: Isometry, - friction: f32, - restitution: f32, - solver_flags: SolverFlags, - ) -> ContactManifoldData { + pub(crate) fn new(body_pair: BodyPair, solver_flags: SolverFlags) -> ContactManifoldData { Self { body_pair, warmstart_multiplier: Self::min_warmstart_multiplier(), - friction, - restitution, - delta1, - delta2, constraint_index: 0, position_constraint_index: 0, solver_flags, + normal: Vector::zeros(), + solver_contacts: Vec::new(), } } - pub(crate) fn from_colliders(coll1: &Collider, coll2: &Collider, flags: SolverFlags) -> Self { - Self::with_subshape_indices(coll1, coll2, flags) + pub(crate) fn set_from_colliders( + &mut self, + coll1: &Collider, + coll2: &Collider, + flags: SolverFlags, + ) { + self.body_pair = BodyPair::new(coll1.parent, coll2.parent); + self.solver_flags = flags; } pub(crate) fn with_subshape_indices( @@ -225,14 +221,7 @@ impl ContactManifoldData { coll2: &Collider, solver_flags: SolverFlags, ) -> Self { - Self::new( - BodyPair::new(coll1.parent, coll2.parent), - *coll1.position_wrt_parent(), - *coll2.position_wrt_parent(), - (coll1.friction + coll2.friction) * 0.5, - (coll1.restitution + coll2.restitution) * 0.5, - solver_flags, - ) + Self::new(BodyPair::new(coll1.parent, coll2.parent), solver_flags) } pub(crate) fn min_warmstart_multiplier() -> f32 { -- cgit From 967145a9492175be59e8db33299b1687d69d84e2 Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Thu, 31 Dec 2020 11:16:03 +0100 Subject: Perform contact sorting in the narrow-phase directly. --- src/geometry/contact_pair.rs | 129 ++++++++++--------------------------------- 1 file changed, 28 insertions(+), 101 deletions(-) (limited to 'src/geometry/contact_pair.rs') diff --git a/src/geometry/contact_pair.rs b/src/geometry/contact_pair.rs index 6b0815b..3ad4f70 100644 --- a/src/geometry/contact_pair.rs +++ b/src/geometry/contact_pair.rs @@ -1,13 +1,7 @@ -use crate::dynamics::{BodyPair, RigidBodyHandle, RigidBodySet}; -use crate::geometry::{Collider, ColliderPair, ColliderSet, Contact, ContactManifold}; -use crate::math::{Isometry, Point, Real, Vector}; +use crate::dynamics::{BodyPair, RigidBodySet}; +use crate::geometry::{Collider, ColliderPair, ContactManifold}; +use crate::math::{Point, Real, Vector}; use cdl::query::ContactManifoldsWorkspace; -use cdl::utils::MaybeSerializableData; -#[cfg(feature = "simd-is-enabled")] -use { - crate::math::{SimdReal, SIMD_WIDTH}, - simba::simd::SimdValue, -}; bitflags::bitflags! { #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] @@ -19,33 +13,6 @@ bitflags::bitflags! { } } -#[cfg(feature = "simd-is-enabled")] -pub(crate) struct WContact { - pub local_p1: Point, - pub local_p2: Point, - pub local_n1: Vector, - pub local_n2: Vector, - pub dist: SimdReal, - pub fid1: [u8; SIMD_WIDTH], - pub fid2: [u8; SIMD_WIDTH], -} - -#[cfg(feature = "simd-is-enabled")] -impl WContact { - pub fn extract(&self, i: usize) -> (Contact, Vector, Vector) { - let c = Contact { - local_p1: self.local_p1.extract(i), - local_p2: self.local_p2.extract(i), - dist: self.dist.extract(i), - fid1: self.fid1[i], - fid2: self.fid2[i], - data: ContactData::default(), - }; - - (c, self.local_n1.extract(i), self.local_n2.extract(i)) - } -} - #[derive(Copy, Clone, Debug)] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] /// A single contact between two collider. @@ -112,40 +79,13 @@ impl ContactPair { /// An active contact is a contact that may result in a non-zero contact force. pub fn has_any_active_contact(&self) -> bool { for manifold in &self.manifolds { - if manifold.num_active_contacts != 0 { + if manifold.data.num_active_contacts() != 0 { return true; } } false } - - pub(crate) fn single_manifold<'a, 'b>( - &'a mut self, - colliders: &'b ColliderSet, - flags: SolverFlags, - ) -> ( - &'b Collider, - &'b Collider, - &'a mut ContactManifold, - Option<&'a mut (dyn MaybeSerializableData)>, - ) { - let coll1 = &colliders[self.pair.collider1]; - let coll2 = &colliders[self.pair.collider2]; - - if self.manifolds.len() == 0 { - let manifold_data = ContactManifoldData::with_subshape_indices(coll1, coll2, flags); - self.manifolds - .push(ContactManifold::with_data((0, 0), manifold_data)); - } - - ( - coll1, - coll2, - &mut self.manifolds[0], - self.workspace.as_mut().map(|w| &mut *w.0), - ) - } } #[derive(Clone, Debug)] @@ -206,22 +146,9 @@ impl ContactManifoldData { } } - pub(crate) fn set_from_colliders( - &mut self, - coll1: &Collider, - coll2: &Collider, - flags: SolverFlags, - ) { - self.body_pair = BodyPair::new(coll1.parent, coll2.parent); - self.solver_flags = flags; - } - - pub(crate) fn with_subshape_indices( - coll1: &Collider, - coll2: &Collider, - solver_flags: SolverFlags, - ) -> Self { - Self::new(BodyPair::new(coll1.parent, coll2.parent), solver_flags) + #[inline] + pub fn num_active_contacts(&self) -> usize { + self.solver_contacts.len() } pub(crate) fn min_warmstart_multiplier() -> f32 { @@ -232,25 +159,25 @@ impl ContactManifoldData { 1.0 // 0.01 } - pub(crate) fn update_warmstart_multiplier(manifold: &mut ContactManifold) { - // In 2D, tall stacks will actually suffer from this - // because oscillation due to inaccuracies in 2D often - // cause contacts to break, which would result in - // a reset of the warmstart multiplier. - if cfg!(feature = "dim2") { - manifold.data.warmstart_multiplier = 1.0; - return; - } - - for pt in &manifold.points { - if pt.data.impulse != 0.0 { - manifold.data.warmstart_multiplier = - (manifold.data.warmstart_multiplier * 2.0).min(1.0); - return; - } - } - - // Reset the multiplier. - manifold.data.warmstart_multiplier = Self::min_warmstart_multiplier() - } + // pub(crate) fn update_warmstart_multiplier(manifold: &mut ContactManifold) { + // // In 2D, tall stacks will actually suffer from this + // // because oscillation due to inaccuracies in 2D often + // // cause contacts to break, which would result in + // // a reset of the warmstart multiplier. + // if cfg!(feature = "dim2") { + // manifold.data.warmstart_multiplier = 1.0; + // return; + // } + // + // for pt in &manifold.points { + // if pt.data.impulse != 0.0 { + // manifold.data.warmstart_multiplier = + // (manifold.data.warmstart_multiplier * 2.0).min(1.0); + // return; + // } + // } + // + // // Reset the multiplier. + // manifold.data.warmstart_multiplier = Self::min_warmstart_multiplier() + // } } -- cgit From 1feac2e02d8779a1a03c9c16d5fbe4fd79c9324a Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Thu, 31 Dec 2020 11:37:42 +0100 Subject: Restore contact events. --- src/geometry/contact_pair.rs | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) (limited to 'src/geometry/contact_pair.rs') diff --git a/src/geometry/contact_pair.rs b/src/geometry/contact_pair.rs index 3ad4f70..b2ae812 100644 --- a/src/geometry/contact_pair.rs +++ b/src/geometry/contact_pair.rs @@ -62,6 +62,7 @@ pub struct ContactPair { /// /// All contact manifold contain themselves contact points between the colliders. pub manifolds: Vec, + pub has_any_active_contact: bool, pub(crate) workspace: Option, } @@ -69,23 +70,11 @@ impl ContactPair { pub(crate) fn new(pair: ColliderPair) -> Self { Self { pair, + has_any_active_contact: false, manifolds: Vec::new(), workspace: None, } } - - /// Does this contact pair have any active contact? - /// - /// An active contact is a contact that may result in a non-zero contact force. - pub fn has_any_active_contact(&self) -> bool { - for manifold in &self.manifolds { - if manifold.data.num_active_contacts() != 0 { - return true; - } - } - - false - } } #[derive(Clone, Debug)] -- cgit From aa61fe65e3ff0289ecab57b4053a3410cf6d4a87 Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Mon, 4 Jan 2021 15:14:25 +0100 Subject: Add support of 64-bits reals. --- src/geometry/contact_pair.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src/geometry/contact_pair.rs') diff --git a/src/geometry/contact_pair.rs b/src/geometry/contact_pair.rs index b2ae812..129d444 100644 --- a/src/geometry/contact_pair.rs +++ b/src/geometry/contact_pair.rs @@ -20,25 +20,25 @@ pub struct ContactData { /// The impulse, along the contact normal, applied by this contact to the first collider's rigid-body. /// /// The impulse applied to the second collider's rigid-body is given by `-impulse`. - pub impulse: f32, + pub impulse: Real, /// The friction impulse along the vector orthonormal to the contact normal, applied to the first /// collider's rigid-body. #[cfg(feature = "dim2")] - pub tangent_impulse: f32, + pub tangent_impulse: Real, /// The friction impulses along the basis orthonormal to the contact normal, applied to the first /// collider's rigid-body. #[cfg(feature = "dim3")] - pub tangent_impulse: [f32; 2], + pub tangent_impulse: [Real; 2], } impl ContactData { #[cfg(feature = "dim2")] - pub(crate) fn zero_tangent_impulse() -> f32 { + pub(crate) fn zero_tangent_impulse() -> Real { 0.0 } #[cfg(feature = "dim3")] - pub(crate) fn zero_tangent_impulse() -> [f32; 2] { + pub(crate) fn zero_tangent_impulse() -> [Real; 2] { [0.0, 0.0] } } @@ -87,7 +87,7 @@ pub struct ContactManifoldData { // The following are set by the narrow-phase. /// The pair of body involved in this contact manifold. pub body_pair: BodyPair, - pub(crate) warmstart_multiplier: f32, + pub(crate) warmstart_multiplier: Real, // The two following are set by the constraints solver. pub(crate) constraint_index: usize, pub(crate) position_constraint_index: usize, @@ -140,7 +140,7 @@ impl ContactManifoldData { self.solver_contacts.len() } - pub(crate) fn min_warmstart_multiplier() -> f32 { + pub(crate) fn min_warmstart_multiplier() -> Real { // Multiplier used to reduce the amount of warm-starting. // This coefficient increases exponentially over time, until it reaches 1.0. // This will reduce significant overshoot at the timesteps that -- cgit From 261ed1ebed04fb594f612b66811350f63b73f104 Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Wed, 6 Jan 2021 12:53:26 +0100 Subject: Fix 2D compilation. --- src/geometry/contact_pair.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/geometry/contact_pair.rs') diff --git a/src/geometry/contact_pair.rs b/src/geometry/contact_pair.rs index 129d444..546b127 100644 --- a/src/geometry/contact_pair.rs +++ b/src/geometry/contact_pair.rs @@ -1,5 +1,5 @@ use crate::dynamics::{BodyPair, RigidBodySet}; -use crate::geometry::{Collider, ColliderPair, ContactManifold}; +use crate::geometry::{ColliderPair, ContactManifold}; use crate::math::{Point, Real, Vector}; use cdl::query::ContactManifoldsWorkspace; -- cgit From 0ade350b5f4b6e7c0c4116e1f4f2b30ab86b7e52 Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Wed, 20 Jan 2021 16:33:42 +0100 Subject: Use newtypes for collider, rigid-body and joint handles. --- src/geometry/contact_pair.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'src/geometry/contact_pair.rs') diff --git a/src/geometry/contact_pair.rs b/src/geometry/contact_pair.rs index 546b127..bd18a5d 100644 --- a/src/geometry/contact_pair.rs +++ b/src/geometry/contact_pair.rs @@ -1,4 +1,4 @@ -use crate::dynamics::{BodyPair, RigidBodySet}; +use crate::dynamics::{BodyPair, RigidBodyHandle}; use crate::geometry::{ColliderPair, ContactManifold}; use crate::math::{Point, Real, Vector}; use cdl::query::ContactManifoldsWorkspace; @@ -113,10 +113,7 @@ pub struct SolverContact { impl Default for ContactManifoldData { fn default() -> Self { Self::new( - BodyPair::new( - RigidBodySet::invalid_handle(), - RigidBodySet::invalid_handle(), - ), + BodyPair::new(RigidBodyHandle::invalid(), RigidBodyHandle::invalid()), SolverFlags::empty(), ) } -- cgit From 8f7220f03d3c23574b9ece09d81d32e862f1b5c6 Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Sun, 24 Jan 2021 11:13:44 +0100 Subject: Rename cdl to parry. --- src/geometry/contact_pair.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/geometry/contact_pair.rs') diff --git a/src/geometry/contact_pair.rs b/src/geometry/contact_pair.rs index bd18a5d..cbb012a 100644 --- a/src/geometry/contact_pair.rs +++ b/src/geometry/contact_pair.rs @@ -1,7 +1,7 @@ use crate::dynamics::{BodyPair, RigidBodyHandle}; use crate::geometry::{ColliderPair, ContactManifold}; use crate::math::{Point, Real, Vector}; -use cdl::query::ContactManifoldsWorkspace; +use parry::query::ContactManifoldsWorkspace; bitflags::bitflags! { #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] -- cgit From 8ff2bcc3ec666805aceedaa477bde89f2a577d1c Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Wed, 27 Jan 2021 14:20:14 +0100 Subject: Add all the missing docs. --- src/geometry/contact_pair.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'src/geometry/contact_pair.rs') diff --git a/src/geometry/contact_pair.rs b/src/geometry/contact_pair.rs index cbb012a..f6c4989 100644 --- a/src/geometry/contact_pair.rs +++ b/src/geometry/contact_pair.rs @@ -62,6 +62,7 @@ pub struct ContactPair { /// /// All contact manifold contain themselves contact points between the colliders. pub manifolds: Vec, + /// Is there any active contact in this contact pair? pub has_any_active_contact: bool, pub(crate) workspace: Option, } @@ -95,18 +96,31 @@ pub struct ContactManifoldData { // contact preparation method. /// Flags used to control some aspects of the constraints solver for this contact manifold. pub solver_flags: SolverFlags, + /// The world-space contact normal shared by all the contact in this contact manifold. pub normal: Vector, + /// The contacts that will be seen by the constraints solver for computing forces. pub solver_contacts: Vec, } +/// A contact seen by the constraints solver for computing forces. #[derive(Copy, Clone, Debug)] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] pub struct SolverContact { + /// The world-space contact point. pub point: Point, + /// The distance between the two original contacts points along the contact normal. + /// If negative, this is measures the penetration depth. pub dist: Real, + /// The effective friction coefficient at this contact point. pub friction: Real, + /// The effective restitution coefficient at this contact point. pub restitution: Real, + /// The artificially add relative velocity at the contact point. + /// This is set to zero by default. Set to a non-zero value to + /// simulate, e.g., conveyor belts. pub surface_velocity: Vector, + /// Associated contact data used to warm-start the constraints + /// solver. pub data: ContactData, } @@ -132,6 +146,8 @@ impl ContactManifoldData { } } + /// Number of actives contacts, i.e., contacts that will be seen by + /// the constraints solver. #[inline] pub fn num_active_contacts(&self) -> usize { self.solver_contacts.len() -- cgit