Add solver flags for controlling whether or not some contacts should be taken into account by the constraints solver.
This commit is contained in:
@@ -49,6 +49,7 @@ erased-serde = { version = "0.3", optional = true }
|
|||||||
indexmap = { version = "1", features = [ "serde-1" ], optional = true }
|
indexmap = { version = "1", features = [ "serde-1" ], optional = true }
|
||||||
downcast-rs = "1.2"
|
downcast-rs = "1.2"
|
||||||
num-derive = "0.3"
|
num-derive = "0.3"
|
||||||
|
bitflags = "1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
bincode = "1"
|
bincode = "1"
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ erased-serde = { version = "0.3", optional = true }
|
|||||||
indexmap = { version = "1", features = [ "serde-1" ], optional = true }
|
indexmap = { version = "1", features = [ "serde-1" ], optional = true }
|
||||||
downcast-rs = "1.2"
|
downcast-rs = "1.2"
|
||||||
num-derive = "0.3"
|
num-derive = "0.3"
|
||||||
|
bitflags = "1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
bincode = "1"
|
bincode = "1"
|
||||||
|
|||||||
@@ -204,6 +204,7 @@ pub struct Collider {
|
|||||||
/// The restitution coefficient of this collider.
|
/// The restitution coefficient of this collider.
|
||||||
pub restitution: f32,
|
pub restitution: f32,
|
||||||
pub(crate) collision_groups: InteractionGroups,
|
pub(crate) collision_groups: InteractionGroups,
|
||||||
|
pub(crate) solver_groups: InteractionGroups,
|
||||||
pub(crate) contact_graph_index: ColliderGraphIndex,
|
pub(crate) contact_graph_index: ColliderGraphIndex,
|
||||||
pub(crate) proximity_graph_index: ColliderGraphIndex,
|
pub(crate) proximity_graph_index: ColliderGraphIndex,
|
||||||
pub(crate) proxy_index: usize,
|
pub(crate) proxy_index: usize,
|
||||||
@@ -261,6 +262,11 @@ impl Collider {
|
|||||||
self.collision_groups
|
self.collision_groups
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The solver groups used by this collider.
|
||||||
|
pub fn solver_groups(&self) -> InteractionGroups {
|
||||||
|
self.solver_groups
|
||||||
|
}
|
||||||
|
|
||||||
/// The density of this collider.
|
/// The density of this collider.
|
||||||
pub fn density(&self) -> f32 {
|
pub fn density(&self) -> f32 {
|
||||||
self.density
|
self.density
|
||||||
@@ -304,10 +310,12 @@ pub struct ColliderBuilder {
|
|||||||
pub delta: Isometry<f32>,
|
pub delta: Isometry<f32>,
|
||||||
/// Is this collider a sensor?
|
/// Is this collider a sensor?
|
||||||
pub is_sensor: bool,
|
pub is_sensor: bool,
|
||||||
/// The user-data of the collider beind built.
|
/// The user-data of the collider being built.
|
||||||
pub user_data: u128,
|
pub user_data: u128,
|
||||||
/// The collision groups for the collider being built.
|
/// The collision groups for the collider being built.
|
||||||
pub collision_groups: InteractionGroups,
|
pub collision_groups: InteractionGroups,
|
||||||
|
/// The solver groups for the collider being built.
|
||||||
|
pub solver_groups: InteractionGroups,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ColliderBuilder {
|
impl ColliderBuilder {
|
||||||
@@ -322,6 +330,7 @@ impl ColliderBuilder {
|
|||||||
is_sensor: false,
|
is_sensor: false,
|
||||||
user_data: 0,
|
user_data: 0,
|
||||||
collision_groups: InteractionGroups::all(),
|
collision_groups: InteractionGroups::all(),
|
||||||
|
solver_groups: InteractionGroups::all(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -442,6 +451,15 @@ impl ColliderBuilder {
|
|||||||
self
|
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.
|
/// Sets whether or not the collider built by this builder is a sensor.
|
||||||
pub fn sensor(mut self, is_sensor: bool) -> Self {
|
pub fn sensor(mut self, is_sensor: bool) -> Self {
|
||||||
self.is_sensor = is_sensor;
|
self.is_sensor = is_sensor;
|
||||||
@@ -523,6 +541,8 @@ impl ColliderBuilder {
|
|||||||
contact_graph_index: InteractionGraph::<Contact>::invalid_graph_index(),
|
contact_graph_index: InteractionGraph::<Contact>::invalid_graph_index(),
|
||||||
proximity_graph_index: InteractionGraph::<Proximity>::invalid_graph_index(),
|
proximity_graph_index: InteractionGraph::<Proximity>::invalid_graph_index(),
|
||||||
proxy_index: crate::INVALID_USIZE,
|
proxy_index: crate::INVALID_USIZE,
|
||||||
|
collision_groups: self.collision_groups,
|
||||||
|
solver_groups: self.solver_groups,
|
||||||
user_data: self.user_data,
|
user_data: self.user_data,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,16 @@ use {
|
|||||||
simba::simd::SimdValue,
|
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)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||||
/// The type local linear approximation of the neighborhood of a pair contact points on two shapes
|
/// 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>(
|
pub(crate) fn single_manifold<'a, 'b>(
|
||||||
&'a mut self,
|
&'a mut self,
|
||||||
colliders: &'b ColliderSet,
|
colliders: &'b ColliderSet,
|
||||||
|
flags: SolverFlags,
|
||||||
) -> (
|
) -> (
|
||||||
&'b Collider,
|
&'b Collider,
|
||||||
&'b Collider,
|
&'b Collider,
|
||||||
@@ -216,7 +227,7 @@ impl ContactPair {
|
|||||||
let coll2 = &colliders[self.pair.collider2];
|
let coll2 = &colliders[self.pair.collider2];
|
||||||
|
|
||||||
if self.manifolds.len() == 0 {
|
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);
|
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
|
/// The relative position between the second collider and its parent at the time the
|
||||||
/// contact points were generated.
|
/// contact points were generated.
|
||||||
pub delta2: Isometry<f32>,
|
pub delta2: Isometry<f32>,
|
||||||
|
/// Flags used to control some aspects of the constraints solver for this contact manifold.
|
||||||
|
pub solver_flags: SolverFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ContactManifold {
|
impl ContactManifold {
|
||||||
@@ -299,6 +312,7 @@ impl ContactManifold {
|
|||||||
delta2: Isometry<f32>,
|
delta2: Isometry<f32>,
|
||||||
friction: f32,
|
friction: f32,
|
||||||
restitution: f32,
|
restitution: f32,
|
||||||
|
solver_flags: SolverFlags,
|
||||||
) -> ContactManifold {
|
) -> ContactManifold {
|
||||||
Self {
|
Self {
|
||||||
#[cfg(feature = "dim2")]
|
#[cfg(feature = "dim2")]
|
||||||
@@ -319,6 +333,7 @@ impl ContactManifold {
|
|||||||
delta2,
|
delta2,
|
||||||
constraint_index: 0,
|
constraint_index: 0,
|
||||||
position_constraint_index: 0,
|
position_constraint_index: 0,
|
||||||
|
solver_flags,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,11 +357,17 @@ impl ContactManifold {
|
|||||||
delta2: self.delta2,
|
delta2: self.delta2,
|
||||||
constraint_index: self.constraint_index,
|
constraint_index: self.constraint_index,
|
||||||
position_constraint_index: self.position_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 {
|
pub(crate) fn from_colliders(
|
||||||
Self::with_subshape_indices(pair, coll1, coll2, 0, 0)
|
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(
|
pub(crate) fn with_subshape_indices(
|
||||||
@@ -355,6 +376,7 @@ impl ContactManifold {
|
|||||||
coll2: &Collider,
|
coll2: &Collider,
|
||||||
subshape1: usize,
|
subshape1: usize,
|
||||||
subshape2: usize,
|
subshape2: usize,
|
||||||
|
solver_flags: SolverFlags,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self::new(
|
Self::new(
|
||||||
pair,
|
pair,
|
||||||
@@ -364,6 +386,7 @@ impl ContactManifold {
|
|||||||
*coll2.position_wrt_parent(),
|
*coll2.position_wrt_parent(),
|
||||||
(coll1.friction + coll2.friction) * 0.5,
|
(coll1.friction + coll2.friction) * 0.5,
|
||||||
(coll1.restitution + coll2.restitution) * 0.5,
|
(coll1.restitution + coll2.restitution) * 0.5,
|
||||||
|
solver_flags,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use crate::geometry::{
|
use crate::geometry::{
|
||||||
Collider, ColliderSet, ContactDispatcher, ContactEvent, ContactManifold, ContactPair, Shape,
|
Collider, ColliderSet, ContactDispatcher, ContactEvent, ContactManifold, ContactPair, Shape,
|
||||||
|
SolverFlags,
|
||||||
};
|
};
|
||||||
use crate::math::Isometry;
|
use crate::math::Isometry;
|
||||||
#[cfg(feature = "simd-is-enabled")]
|
#[cfg(feature = "simd-is-enabled")]
|
||||||
@@ -26,8 +27,9 @@ impl ContactPhase {
|
|||||||
Self::NearPhase(gen) => (gen.generate_contacts)(&mut context),
|
Self::NearPhase(gen) => (gen.generate_contacts)(&mut context),
|
||||||
Self::ExactPhase(gen) => {
|
Self::ExactPhase(gen) => {
|
||||||
// Build the primitive context from the non-primitive context and dispatch.
|
// Build the primitive context from the non-primitive context and dispatch.
|
||||||
let (collider1, collider2, manifold, workspace) =
|
let (collider1, collider2, manifold, workspace) = context
|
||||||
context.pair.single_manifold(context.colliders);
|
.pair
|
||||||
|
.single_manifold(context.colliders, context.solver_flags);
|
||||||
let mut context2 = PrimitiveContactGenerationContext {
|
let mut context2 = PrimitiveContactGenerationContext {
|
||||||
prediction_distance: context.prediction_distance,
|
prediction_distance: context.prediction_distance,
|
||||||
collider1,
|
collider1,
|
||||||
@@ -85,9 +87,11 @@ impl ContactPhase {
|
|||||||
[Option<&mut (dyn Any + Send + Sync)>; SIMD_WIDTH],
|
[Option<&mut (dyn Any + Send + Sync)>; SIMD_WIDTH],
|
||||||
> = ArrayVec::new();
|
> = 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) =
|
let (collider1, collider2, manifold, workspace) =
|
||||||
pair.single_manifold(context.colliders);
|
pair.single_manifold(context.colliders, *solver_flags);
|
||||||
colliders_arr.push((collider1, collider2));
|
colliders_arr.push((collider1, collider2));
|
||||||
manifold_arr.push(manifold);
|
manifold_arr.push(manifold);
|
||||||
workspace_arr.push(workspace);
|
workspace_arr.push(workspace);
|
||||||
@@ -188,6 +192,7 @@ pub struct ContactGenerationContext<'a> {
|
|||||||
pub prediction_distance: f32,
|
pub prediction_distance: f32,
|
||||||
pub colliders: &'a ColliderSet,
|
pub colliders: &'a ColliderSet,
|
||||||
pub pair: &'a mut ContactPair,
|
pub pair: &'a mut ContactPair,
|
||||||
|
pub solver_flags: SolverFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "simd-is-enabled")]
|
#[cfg(feature = "simd-is-enabled")]
|
||||||
@@ -196,6 +201,7 @@ pub struct ContactGenerationContextSimd<'a, 'b> {
|
|||||||
pub prediction_distance: f32,
|
pub prediction_distance: f32,
|
||||||
pub colliders: &'a ColliderSet,
|
pub colliders: &'a ColliderSet,
|
||||||
pub pairs: &'a mut [&'b mut ContactPair],
|
pub pairs: &'a mut [&'b mut ContactPair],
|
||||||
|
pub solver_flags: &'a [SolverFlags],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ fn do_generate_contacts(
|
|||||||
let manifolds = &mut ctxt.pair.manifolds;
|
let manifolds = &mut ctxt.pair.manifolds;
|
||||||
let prediction_distance = ctxt.prediction_distance;
|
let prediction_distance = ctxt.prediction_distance;
|
||||||
let dispatcher = ctxt.dispatcher;
|
let dispatcher = ctxt.dispatcher;
|
||||||
|
let solver_flags = ctxt.solver_flags;
|
||||||
let shape_type2 = collider2.shape().shape_type();
|
let shape_type2 = collider2.shape().shape_type();
|
||||||
|
|
||||||
heightfield1.map_elements_in_local_aabb(&ls_aabb2, &mut |i, part1, _| {
|
heightfield1.map_elements_in_local_aabb(&ls_aabb2, &mut |i, part1, _| {
|
||||||
@@ -131,8 +132,14 @@ fn do_generate_contacts(
|
|||||||
timestamp: new_timestamp,
|
timestamp: new_timestamp,
|
||||||
workspace: workspace2,
|
workspace: workspace2,
|
||||||
};
|
};
|
||||||
let manifold =
|
let manifold = ContactManifold::with_subshape_indices(
|
||||||
ContactManifold::with_subshape_indices(coll_pair, collider1, collider2, i, 0);
|
coll_pair,
|
||||||
|
collider1,
|
||||||
|
collider2,
|
||||||
|
i,
|
||||||
|
0,
|
||||||
|
solver_flags,
|
||||||
|
);
|
||||||
manifolds.push(manifold);
|
manifolds.push(manifold);
|
||||||
|
|
||||||
entry.insert(sub_detector)
|
entry.insert(sub_detector)
|
||||||
|
|||||||
@@ -149,6 +149,7 @@ fn do_generate_contacts(
|
|||||||
collider2,
|
collider2,
|
||||||
*triangle_id,
|
*triangle_id,
|
||||||
0,
|
0,
|
||||||
|
ctxt.solver_flags,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// We already have a manifold for this triangle.
|
// We already have a manifold for this triangle.
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ pub use self::capsule::Capsule;
|
|||||||
pub use self::collider::{Collider, ColliderBuilder, ColliderShape};
|
pub use self::collider::{Collider, ColliderBuilder, ColliderShape};
|
||||||
pub use self::collider_set::{ColliderHandle, ColliderSet};
|
pub use self::collider_set::{ColliderHandle, ColliderSet};
|
||||||
pub use self::contact::{
|
pub use self::contact::{
|
||||||
Contact, ContactKinematics, ContactManifold, ContactPair, KinematicsCategory,
|
Contact, ContactKinematics, ContactManifold, ContactPair, KinematicsCategory, SolverFlags,
|
||||||
};
|
};
|
||||||
pub use self::contact_generator::{ContactDispatcher, DefaultContactDispatcher};
|
pub use self::contact_generator::{ContactDispatcher, DefaultContactDispatcher};
|
||||||
#[cfg(feature = "dim2")]
|
#[cfg(feature = "dim2")]
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ use crate::geometry::proximity_detector::{
|
|||||||
//};
|
//};
|
||||||
use crate::geometry::{
|
use crate::geometry::{
|
||||||
BroadPhasePairEvent, ColliderGraphIndex, ColliderHandle, ContactEvent, ProximityEvent,
|
BroadPhasePairEvent, ColliderGraphIndex, ColliderHandle, ContactEvent, ProximityEvent,
|
||||||
ProximityPair, RemovedCollider,
|
ProximityPair, RemovedCollider, SolverFlags,
|
||||||
};
|
};
|
||||||
use crate::geometry::{ColliderSet, ContactManifold, ContactPair, InteractionGraph};
|
use crate::geometry::{ColliderSet, ContactManifold, ContactPair, InteractionGraph};
|
||||||
//#[cfg(feature = "simd-is-enabled")]
|
//#[cfg(feature = "simd-is-enabled")]
|
||||||
@@ -374,11 +374,18 @@ impl NarrowPhase {
|
|||||||
pair.generator_workspace = workspace;
|
pair.generator_workspace = workspace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let solver_flags = if co1.solver_groups.test(co2.solver_groups) {
|
||||||
|
SolverFlags::COMPUTE_FORCES
|
||||||
|
} else {
|
||||||
|
SolverFlags::empty()
|
||||||
|
};
|
||||||
|
|
||||||
let context = ContactGenerationContext {
|
let context = ContactGenerationContext {
|
||||||
dispatcher: &dispatcher,
|
dispatcher: &dispatcher,
|
||||||
prediction_distance,
|
prediction_distance,
|
||||||
colliders,
|
colliders,
|
||||||
pair,
|
pair,
|
||||||
|
solver_flags,
|
||||||
};
|
};
|
||||||
|
|
||||||
context
|
context
|
||||||
|
|||||||
Reference in New Issue
Block a user