#[cfg(feature = "parallel")]
use rayon::prelude::*;
use crate::data::graph::EdgeIndex;
use crate::data::Coarena;
use crate::dynamics::{
CoefficientCombineRule, Dominance, ImpulseJointSet, IslandManager, RigidBodySet, RigidBodyType,
};
use crate::geometry::{
BroadPhasePairEvent, ColliderChanges, ColliderGraphIndex, ColliderHandle, ColliderPair,
ColliderSet, CollisionEvent, ContactData, ContactManifold, ContactManifoldData, ContactPair,
InteractionGraph, IntersectionPair, SolverContact, SolverFlags, TemporaryInteractionIndex,
};
use crate::math::*;
use crate::pipeline::{
ActiveEvents, ActiveHooks, ContactModificationContext, EventHandler, PairFilterContext,
PhysicsHooks,
};
use crate::prelude::{CollisionEventFlags, MultibodyJointSet};
use parry::math::center;
use parry::query::{DefaultQueryDispatcher, PersistentQueryDispatcher};
use std::collections::HashMap;
use std::sync::Arc;
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
struct ColliderGraphIndices {
contact_graph_index: ColliderGraphIndex,
intersection_graph_index: ColliderGraphIndex,
}
impl ColliderGraphIndices {
fn invalid() -> Self {
Self {
contact_graph_index: InteractionGraph::<(), ()>::invalid_graph_index(),
intersection_graph_index: InteractionGraph::<(), ()>::invalid_graph_index(),
}
}
}
#[derive(Copy, Clone, PartialEq, Eq)]
enum PairRemovalMode {
FromContactGraph,
FromIntersectionGraph,
Auto,
}
/// The narrow-phase responsible for computing precise contact information between colliders.
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
#[derive(Clone)]
pub struct NarrowPhase {
#[cfg_attr(
feature = "serde-serialize",
serde(skip, default = "crate::geometry::default_persistent_query_dispatcher")
)]
query_dispatcher: Arc<dyn PersistentQueryDispatcher<ContactManifoldData, ContactData>>,
contact_graph: InteractionGraph<ColliderHandle, ContactPair>,
intersection_graph: InteractionGraph<ColliderHandle, IntersectionPair>,
graph_indices: Coarena<ColliderGraphIndices>,
}
pub(crate) type ContactManifoldIndex = usize;
impl Default for NarrowPhase {
fn default() -> Self {
Self::new()
}
}
impl NarrowPhase {
/// Creates a new empty narrow-phase.
pub fn new() -> Self {
Self::with_query_dispatcher(DefaultQueryDispatcher)
}
/// Creates a new empty narrow-phase with a custom query dispatcher.
pub fn with_query_dispatcher<D>(d: D) -> Self
where
D: 'static + PersistentQueryDispatcher<ContactManifoldData, ContactData>,
{
Self {
query_dispatcher: Arc::new(d),
contact_graph: InteractionGraph::new(),
intersection_graph: InteractionGraph::new(),
graph_indices: Coarena::new(),
}
}
/// The query dispatcher used by this narrow-phase to select the right collision-detection
/// algorithms depending of the shape types.
pub fn query_dispatcher(
&self,
) -> &dyn PersistentQueryDispatcher<ContactManifoldData, ContactData> {
&*self.query_dispatcher
}
/// The contact graph containing all contact pairs and their contact information.
pub fn contact_graph(&self) -> &InteractionGraph<ColliderHandle, ContactPair> {
&self.contact_graph
}
/// The intersection graph containing all intersection pairs and their intersection information.
pub fn intersection_graph(&self) -> &InteractionGraph<ColliderHandle, IntersectionPair> {
&self.intersection_graph
}
/// All the contacts involving the given collider.
///
/// It is strongly recommended to use the [`NarrowPhase::contacts_with`] method instead. This
/// method can be used if the generation number of the collider handle isn't known.
pub fn contact_pairs_with_unknown_gen(
&self,
collider: u32,
) -> impl Iterator<Item = &ContactPair> {
self.graph_indices
.get_unknown_gen(collider)
.map(|