Skip to main content

rapier2d/geometry/narrow_phase/
queries.rs

1//! Read-only accessors and iterators over the narrow-phase's contact and
2//! intersection pairs and their interaction graphs.
3
4use super::NarrowPhase;
5use crate::geometry::{
6    ColliderHandle, ColliderSet, ContactData, ContactManifoldData, ContactPair, InteractionGraph,
7    IntersectionPair, TemporaryInteractionIndex,
8};
9use parry::query::PersistentQueryDispatcher;
10
11impl NarrowPhase {
12    /// Per-body masks (indexed by rigid-body arena index) of the solver colors used
13    /// by each body's active contact pairs. Read by the staged island solver to
14    /// color joints in the same color space as the contacts.
15    pub(crate) fn body_solver_color_masks(&self) -> &[u128] {
16        &self.body_solver_color_masks
17    }
18
19    /// The query dispatcher used by this narrow-phase to select the right collision-detection
20    /// algorithms depending on the shape types.
21    pub fn query_dispatcher(
22        &self,
23    ) -> &dyn PersistentQueryDispatcher<ContactManifoldData, ContactData> {
24        &*self.query_dispatcher
25    }
26
27    /// The contact graph containing all contact pairs and their contact information.
28    pub fn contact_graph(&self) -> &InteractionGraph<ColliderHandle, ContactPair> {
29        &self.contact_graph
30    }
31
32    /// The intersection graph containing all intersection pairs and their intersection information.
33    pub fn intersection_graph(&self) -> &InteractionGraph<ColliderHandle, IntersectionPair> {
34        &self.intersection_graph
35    }
36
37    /// All the contacts involving the given collider.
38    ///
39    /// It is strongly recommended to use the [`NarrowPhase::contact_pairs_with`] method instead. This
40    /// method can be used if the generation number of the collider handle isn't known.
41    pub fn contact_pairs_with_unknown_gen(
42        &self,
43        collider: u32,
44    ) -> impl Iterator<Item = &ContactPair> {
45        self.graph_indices
46            .get_unknown_gen(collider)
47            .map(|id| id.contact_graph_index)
48            .into_iter()
49            .flat_map(move |id| self.contact_graph.interactions_with(id))
50            .map(|pair| pair.2)
51    }
52
53    /// All the contact pairs involving the given collider.
54    ///
55    /// The returned contact pairs identify pairs of colliders with intersecting bounding-volumes.
56    /// To check if any geometric contact happened between the collider shapes, check
57    /// [`ContactPair::has_any_active_contact`].
58    pub fn contact_pairs_with(
59        &self,
60        collider: ColliderHandle,
61    ) -> impl Iterator<Item = &ContactPair> {
62        self.graph_indices
63            .get(collider.0)
64            .map(|id| id.contact_graph_index)
65            .into_iter()
66            .flat_map(move |id| self.contact_graph.interactions_with(id))
67            .map(|pair| pair.2)
68    }
69
70    /// All the intersection pairs involving the given collider.
71    ///
72    /// It is strongly recommended to use the [`NarrowPhase::intersection_pairs_with`]  method instead.
73    /// This method can be used if the generation number of the collider handle isn't known.
74    pub fn intersection_pairs_with_unknown_gen(
75        &self,
76        collider: u32,
77    ) -> impl Iterator<Item = (ColliderHandle, ColliderHandle, bool)> + '_ {
78        self.graph_indices
79            .get_unknown_gen(collider)
80            .map(|id| id.intersection_graph_index)
81            .into_iter()
82            .flat_map(move |id| {
83                self.intersection_graph
84                    .interactions_with(id)
85                    .map(|e| (e.0, e.1, e.2.intersecting))
86            })
87    }
88
89    /// All the intersection pairs involving the given collider, where at least one collider
90    /// involved in the intersection is a sensor.
91    ///
92    /// The returned contact pairs identify pairs of colliders (where at least one is a sensor) with
93    /// intersecting bounding-volumes. To check if any geometric overlap happened between the collider shapes, check
94    /// the returned boolean.
95    pub fn intersection_pairs_with(
96        &self,
97        collider: ColliderHandle,
98    ) -> impl Iterator<Item = (ColliderHandle, ColliderHandle, bool)> + '_ {
99        self.graph_indices
100            .get(collider.0)
101            .map(|id| id.intersection_graph_index)
102            .into_iter()
103            .flat_map(move |id| {
104                self.intersection_graph
105                    .interactions_with(id)
106                    .map(|e| (e.0, e.1, e.2.intersecting))
107            })
108    }
109
110    /// Returns the contact pair at the given temporary index.
111    pub fn contact_pair_at_index(&self, id: TemporaryInteractionIndex) -> &ContactPair {
112        &self.contact_graph.graph.edges[id.index()].weight
113    }
114
115    /// The contact pair involving two specific colliders.
116    ///
117    /// It is strongly recommended to use the [`NarrowPhase::contact_pair`] method instead. This
118    /// method can be used if the generation number of the collider handle isn't known.
119    ///
120    /// If this returns `None`, there is no contact between the two colliders.
121    /// If this returns `Some`, then there may be a contact between the two colliders. Check the
122    /// result [`ContactPair::has_any_active_contact`] method to see if there is an actual contact.
123    pub fn contact_pair_unknown_gen(&self, collider1: u32, collider2: u32) -> Option<&ContactPair> {
124        let id1 = self.graph_indices.get_unknown_gen(collider1)?;
125        let id2 = self.graph_indices.get_unknown_gen(collider2)?;
126        self.contact_graph
127            .interaction_pair(id1.contact_graph_index, id2.contact_graph_index)
128            .map(|c| c.2)
129    }
130
131    /// The contact pair involving two specific colliders.
132    ///
133    /// If this returns `None`, there is no contact between the two colliders.
134    /// If this returns `Some`, then there may be a contact between the two colliders. Check the
135    /// result [`ContactPair::has_any_active_contact`] method to see if there is an actual contact.
136    pub fn contact_pair(
137        &self,
138        collider1: ColliderHandle,
139        collider2: ColliderHandle,
140    ) -> Option<&ContactPair> {
141        let id1 = self.graph_indices.get(collider1.0)?;
142        let id2 = self.graph_indices.get(collider2.0)?;
143        self.contact_graph
144            .interaction_pair(id1.contact_graph_index, id2.contact_graph_index)
145            .map(|c| c.2)
146    }
147
148    /// The intersection pair involving two specific colliders.
149    ///
150    /// It is strongly recommended to use the [`NarrowPhase::intersection_pair`] method instead. This
151    /// method can be used if the generation number of the collider handle isn't known.
152    ///
153    /// If this returns `None` or `Some(false)`, then there is no intersection between the two colliders.
154    /// If this returns `Some(true)`, then there may be an intersection between the two colliders.
155    pub fn intersection_pair_unknown_gen(&self, collider1: u32, collider2: u32) -> Option<bool> {
156        let id1 = self.graph_indices.get_unknown_gen(collider1)?;
157        let id2 = self.graph_indices.get_unknown_gen(collider2)?;
158        self.intersection_graph
159            .interaction_pair(id1.intersection_graph_index, id2.intersection_graph_index)
160            .map(|c| c.2.intersecting)
161    }
162
163    /// The intersection pair involving two specific colliders.
164    ///
165    /// If this returns `None` or `Some(false)`, then there is no intersection between the two colliders.
166    /// If this returns `Some(true)`, then there may be an intersection between the two colliders.
167    pub fn intersection_pair(
168        &self,
169        collider1: ColliderHandle,
170        collider2: ColliderHandle,
171    ) -> Option<bool> {
172        let id1 = self.graph_indices.get(collider1.0)?;
173        let id2 = self.graph_indices.get(collider2.0)?;
174        self.intersection_graph
175            .interaction_pair(id1.intersection_graph_index, id2.intersection_graph_index)
176            .map(|c| c.2.intersecting)
177    }
178
179    /// All the contact pairs maintained by this narrow-phase.
180    pub fn contact_pairs(&self) -> impl Iterator<Item = &ContactPair> {
181        self.contact_graph.interactions()
182    }
183
184    /// `(edge_id, parent1, parent2)` for every *touching* contact pair. Used to (re)build
185    /// the persistent islands from scratch (bootstrap after construction or
186    /// deserialization) and by their debug validation.
187    pub(crate) fn touching_pairs_with_ids<'a>(
188        &'a self,
189        colliders: &'a ColliderSet,
190    ) -> impl Iterator<
191        Item = (
192            u32,
193            Option<crate::dynamics::RigidBodyHandle>,
194            Option<crate::dynamics::RigidBodyHandle>,
195        ),
196    > + 'a {
197        self.contact_graph
198            .graph
199            .edges
200            .iter()
201            .enumerate()
202            .filter_map(move |(edge_id, edge)| {
203                let pair = &edge.weight;
204                if !pair.has_any_active_contact() {
205                    return None;
206                }
207                let parent = |co: crate::geometry::ColliderHandle| {
208                    colliders.get(co).and_then(|c| c.parent.map(|p| p.handle))
209                };
210                Some((
211                    edge_id as u32,
212                    parent(pair.collider1),
213                    parent(pair.collider2),
214                ))
215            })
216    }
217
218    /// `(edge_id, other collider)` for every *touching* contact pair of `collider` — the
219    /// adjacency the persistent islands' local split search walks. Edge id and touching
220    /// predicate match the island contact links exactly.
221    pub(crate) fn touching_edges_with(
222        &self,
223        collider: ColliderHandle,
224    ) -> impl Iterator<Item = (u32, ColliderHandle)> + '_ {
225        self.graph_indices
226            .get(collider.0)
227            .map(|id| id.contact_graph_index)
228            .into_iter()
229            .flat_map(move |id| self.contact_graph.graph.edges(id))
230            .filter(|edge| edge.weight().has_any_active_contact())
231            .map(move |edge| {
232                let pair = edge.weight();
233                let other = if pair.collider1 == collider {
234                    pair.collider2
235                } else {
236                    pair.collider1
237                };
238                (edge.id().index() as u32, other)
239            })
240    }
241
242    /// All the intersection pairs maintained by this narrow-phase.
243    pub fn intersection_pairs(
244        &self,
245    ) -> impl Iterator<Item = (ColliderHandle, ColliderHandle, bool)> + '_ {
246        self.intersection_graph
247            .interactions_with_endpoints()
248            .map(|e| (e.0, e.1, e.2.intersecting))
249    }
250}