diff options
| author | Crozet Sébastien <developer@crozet.re> | 2020-10-27 13:36:53 +0100 |
|---|---|---|
| committer | Crozet Sébastien <developer@crozet.re> | 2020-10-27 14:35:01 +0100 |
| commit | cb6a7ff9468347735ef63db9a9e38faeb476981b (patch) | |
| tree | 49f3a20afbd5a3be4c3d9de25f630f6b353e6406 /src | |
| parent | 3def91d62eba6ca2486fdaa386f78d82923c705a (diff) | |
| download | rapier-cb6a7ff9468347735ef63db9a9e38faeb476981b.tar.gz rapier-cb6a7ff9468347735ef63db9a9e38faeb476981b.tar.bz2 rapier-cb6a7ff9468347735ef63db9a9e38faeb476981b.zip | |
Add solver flags for controlling whether or not some contacts should be taken into account by the constraints solver.
Diffstat (limited to 'src')
| -rw-r--r-- | src/geometry/collider.rs | 22 | ||||
| -rw-r--r-- | src/geometry/contact.rs | 29 | ||||
| -rw-r--r-- | src/geometry/contact_generator/contact_generator.rs | 14 | ||||
| -rw-r--r-- | src/geometry/contact_generator/heightfield_shape_contact_generator.rs | 11 | ||||
| -rw-r--r-- | src/geometry/contact_generator/trimesh_shape_contact_generator.rs | 1 | ||||
| -rw-r--r-- | src/geometry/mod.rs | 2 | ||||
| -rw-r--r-- | src/geometry/narrow_phase.rs | 9 |
7 files changed, 76 insertions, 12 deletions
diff --git a/src/geometry/collider.rs b/src/geometry/collider.rs index 7147e95..f53d75a 100644 --- a/src/geometry/collider.rs +++ b/src/geometry/collider.rs @@ -204,6 +204,7 @@ pub struct Collider { /// The restitution coefficient of this collider. pub restitution: f32, pub(crate) collision_groups: InteractionGroups, + pub(crate) solver_groups: InteractionGroups, pub(crate) contact_graph_index: ColliderGraphIndex, pub(crate) proximity_graph_index: ColliderGraphIndex, pub(crate) proxy_index: usize, @@ -261,6 +262,11 @@ impl Collider { self.collision_groups } + /// The solver groups used by this collider. + pub fn solver_groups(&self) -> InteractionGroups { + self.solver_groups + } + /// The density of this collider. pub fn density(&self) -> f32 { self.density @@ -304,10 +310,12 @@ pub struct ColliderBuilder { pub delta: Isometry<f32>, /// Is this collider a sensor? pub is_sensor: bool, - /// The user-data of the collider beind built. + /// The user-data of the collider being built. pub user_data: u128, /// The collision groups for the collider being built. pub collision_groups: InteractionGroups, + /// The solver groups for the collider being built. + pub solver_groups: InteractionGroups, } impl ColliderBuilder { @@ -322,6 +330,7 @@ impl ColliderBuilder { is_sensor: false, user_data: 0, collision_groups: InteractionGroups::all(), + solver_groups: InteractionGroups::all(), } } @@ -442,6 +451,15 @@ impl ColliderBuilder { self } + /// Sets the solver groups used by this collider. + /// + /// Forces between two colliders in contact will be computed iff their solver groups are + /// compatible. See [InteractionGroups::test] for details. + pub fn solver_groups(mut self, groups: InteractionGroups) -> Self { + self.solver_groups = groups; + self + } + /// Sets whether or not the collider built by this builder is a sensor. pub fn sensor(mut self, is_sensor: bool) -> Self { self.is_sensor = is_sensor; @@ -523,6 +541,8 @@ impl ColliderBuilder { contact_graph_index: InteractionGraph::<Contact>::invalid_graph_index(), proximity_graph_index: InteractionGraph::<Proximity>::invalid_graph_index(), proxy_index: crate::INVALID_USIZE, + collision_groups: self.collision_groups, + solver_groups: self.solver_groups, user_data: self.user_data, } } diff --git a/src/geometry/contact.rs b/src/geometry/contact.rs index d211cf1..1f50e43 100644 --- a/src/geometry/contact.rs +++ b/src/geometry/contact.rs @@ -9,6 +9,16 @@ use { 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_FORCES = 0b01; + } +} + #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] /// The type local linear approximation of the neighborhood of a pair contact points on two shapes @@ -206,6 +216,7 @@ impl ContactPair { pub(crate) fn single_manifold<'a, 'b>( &'a mut self, colliders: &'b ColliderSet, + flags: SolverFlags, ) -> ( &'b Collider, &'b Collider, @@ -216,7 +227,7 @@ impl ContactPair { let coll2 = &colliders[self.pair.collider2]; if self.manifolds.len() == 0 { - let manifold = ContactManifold::from_colliders(self.pair, coll1, coll2); + let manifold = ContactManifold::from_colliders(self.pair, coll1, coll2, flags); self.manifolds.push(manifold); } @@ -288,6 +299,8 @@ pub struct ContactManifold { /// The relative position between the second collider and its parent at the time the /// contact points were generated. pub delta2: Isometry<f32>, + /// Flags used to control some aspects of the constraints solver for this contact manifold. + pub solver_flags: SolverFlags, } impl ContactManifold { @@ -299,6 +312,7 @@ impl ContactManifold { delta2: Isometry<f32>, friction: f32, restitution: f32, + solver_flags: SolverFlags, ) -> ContactManifold { Self { #[cfg(feature = "dim2")] @@ -319,6 +333,7 @@ impl ContactManifold { delta2, constraint_index: 0, position_constraint_index: 0, + solver_flags, } } @@ -342,11 +357,17 @@ impl ContactManifold { delta2: self.delta2, constraint_index: self.constraint_index, position_constraint_index: self.position_constraint_index, + solver_flags: self.solver_flags, } } - pub(crate) fn from_colliders(pair: ColliderPair, coll1: &Collider, coll2: &Collider) -> Self { - Self::with_subshape_indices(pair, coll1, coll2, 0, 0) + pub(crate) fn from_colliders( + pair: ColliderPair, + coll1: &Collider, + coll2: &Collider, + flags: SolverFlags, + ) -> Self { + Self::with_subshape_indices(pair, coll1, coll2, 0, 0, flags) } pub(crate) fn with_subshape_indices( @@ -355,6 +376,7 @@ impl ContactManifold { coll2: &Collider, subshape1: usize, subshape2: usize, + solver_flags: SolverFlags, ) -> Self { Self::new( pair, @@ -364,6 +386,7 @@ impl ContactManifold { *coll2.position_wrt_parent(), (coll1.friction + coll2.friction) * 0.5, (coll1.restitution + coll2.restitution) * 0.5, + solver_flags, ) } diff --git a/src/geometry/contact_generator/contact_generator.rs b/src/geometry/contact_generator/contact_generator.rs index b034760..728794d 100644 --- a/src/geometry/contact_generator/contact_generator.rs +++ b/src/geometry/contact_generator/contact_generator.rs @@ -1,5 +1,6 @@ use crate::geometry::{ Collider, ColliderSet, ContactDispatcher, ContactEvent, ContactManifold, ContactPair, Shape, + SolverFlags, }; use crate::math::Isometry; #[cfg(feature = "simd-is-enabled")] @@ -26,8 +27,9 @@ impl ContactPhase { Self::NearPhase(gen) => (gen.generate_contacts)(&mut context), Self::ExactPhase(gen) => { // Build the primitive context from the non-primitive context and dispatch. - let (collider1, collider2, manifold, workspace) = - context.pair.single_manifold(context.colliders); + let (collider1, collider2, manifold, workspace) = context + .pair + .single_manifold(context.colliders, context.solver_flags); let mut context2 = PrimitiveContactGenerationContext { prediction_distance: context.prediction_distance, collider1, @@ -85,9 +87,11 @@ impl ContactPhase { [Option<&mut (dyn Any + Send + Sync)>; SIMD_WIDTH], > = ArrayVec::new(); - for pair in context.pairs.iter_mut() { + for (pair, solver_flags) in + context.pairs.iter_mut().zip(context.solver_flags.iter()) + { let (collider1, collider2, manifold, workspace) = - pair.single_manifold(context.colliders); + pair.single_manifold(context.colliders, *solver_flags); colliders_arr.push((collider1, collider2)); manifold_arr.push(manifold); workspace_arr.push(workspace); @@ -188,6 +192,7 @@ pub struct ContactGenerationContext<'a> { pub prediction_distance: f32, pub colliders: &'a ColliderSet, pub pair: &'a mut ContactPair, + pub solver_flags: SolverFlags, } #[cfg(feature = "simd-is-enabled")] @@ -196,6 +201,7 @@ pub struct ContactGenerationContextSimd<'a, 'b> { pub prediction_distance: f32, pub colliders: &'a ColliderSet, pub pairs: &'a mut [&'b mut ContactPair], + pub solver_flags: &'a [SolverFlags], } #[derive(Copy, Clone)] diff --git a/src/geometry/contact_generator/heightfield_shape_contact_generator.rs b/src/geometry/contact_generator/heightfield_shape_contact_generator.rs index 9224d4e..f291fa0 100644 --- a/src/geometry/contact_generator/heightfield_shape_contact_generator.rs +++ b/src/geometry/contact_generator/heightfield_shape_contact_generator.rs @@ -104,6 +104,7 @@ fn do_generate_contacts( let manifolds = &mut ctxt.pair.manifolds; let prediction_distance = ctxt.prediction_distance; let dispatcher = ctxt.dispatcher; + let solver_flags = ctxt.solver_flags; let shape_type2 = collider2.shape().shape_type(); heightfield1.map_elements_in_local_aabb(&ls_aabb2, &mut |i, part1, _| { @@ -131,8 +132,14 @@ fn do_generate_contacts( timestamp: new_timestamp, workspace: workspace2, }; - let manifold = - ContactManifold::with_subshape_indices(coll_pair, collider1, collider2, i, 0); + let manifold = ContactManifold::with_subshape_indices( + coll_pair, + collider1, + collider2, + i, + 0, + solver_flags, + ); manifolds.push(manifold); entry.insert(sub_detector) diff --git a/src/geometry/contact_generator/trimesh_shape_contact_generator.rs b/src/geometry/contact_generator/trimesh_shape_contact_generator.rs index 502658d..9474516 100644 --- a/src/geometry/contact_generator/trimesh_shape_contact_generator.rs +++ b/src/geometry/contact_generator/trimesh_shape_contact_generator.rs @@ -149,6 +149,7 @@ fn do_generate_contacts( collider2, *triangle_id, 0, + ctxt.solver_flags, ) } else { // We already have a manifold for this triangle. diff --git a/src/geometry/mod.rs b/src/geometry/mod.rs index 4055d43..9da35d9 100644 --- a/src/geometry/mod.rs +++ b/src/geometry/mod.rs @@ -5,7 +5,7 @@ pub use self::capsule::Capsule; pub use self::collider::{Collider, ColliderBuilder, ColliderShape}; pub use self::collider_set::{ColliderHandle, ColliderSet}; pub use self::contact::{ - Contact, ContactKinematics, ContactManifold, ContactPair, KinematicsCategory, + Contact, ContactKinematics, ContactManifold, ContactPair, KinematicsCategory, SolverFlags, }; pub use self::contact_generator::{ContactDispatcher, DefaultContactDispatcher}; #[cfg(feature = "dim2")] diff --git a/src/geometry/narrow_phase.rs b/src/geometry/narrow_phase.rs index 5bcdcdb..290d55f 100644 --- a/src/geometry/narrow_phase.rs +++ b/src/geometry/narrow_phase.rs @@ -15,7 +15,7 @@ use crate::geometry::proximity_detector::{ //}; use crate::geometry::{ BroadPhasePairEvent, ColliderGraphIndex, ColliderHandle, ContactEvent, ProximityEvent, - ProximityPair, RemovedCollider, + ProximityPair, RemovedCollider, SolverFlags, }; use crate::geometry::{ColliderSet, ContactManifold, ContactPair, InteractionGraph}; //#[cfg(feature = "simd-is-enabled")] @@ -374,11 +374,18 @@ impl NarrowPhase { pair.generator_workspace = workspace; } + let solver_flags = if co1.solver_groups.test(co2.solver_groups) { + SolverFlags::COMPUTE_FORCES + } else { + SolverFlags::empty() + }; + let context = ContactGenerationContext { dispatcher: &dispatcher, prediction_distance, colliders, pair, + solver_flags, }; context |
