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    /// Mutable access to the contact pair involving two specific colliders (the soft-body
149    /// solver writes its contact impulses back through it).
150    pub(crate) fn contact_pair_mut(
151        &mut self,
152        collider1: ColliderHandle,
153        collider2: ColliderHandle,
154    ) -> Option<&mut ContactPair> {
155        let id1 = self.graph_indices.get(collider1.0)?;
156        let id2 = self.graph_indices.get(collider2.0)?;
157        self.contact_graph
158            .interaction_pair_mut(id1.contact_graph_index, id2.contact_graph_index)
159            .map(|c| c.2)
160    }
161
162    /// The intersection pair involving two specific colliders.
163    ///
164    /// It is strongly recommended to use the [`NarrowPhase::intersection_pair`] method instead. This
165    /// method can be used if the generation number of the collider handle isn't known.
166    ///
167    /// If this returns `None` or `Some(false)`, then there is no intersection between the two colliders.
168    /// If this returns `Some(true)`, then there may be an intersection between the two colliders.
169    pub fn intersection_pair_unknown_gen(&self, collider1: u32, collider2: u32) -> Option<bool> {
170        let id1 = self.graph_indices.get_unknown_gen(collider1)?;
171        let id2 = self.graph_indices.get_unknown_gen(collider2)?;
172        self.intersection_graph
173            .interaction_pair(id1.intersection_graph_index, id2.intersection_graph_index)
174            .map(|c| c.2.intersecting)
175    }
176
177    /// The intersection pair involving two specific colliders.
178    ///
179    /// If this returns `None` or `Some(false)`, then there is no intersection between the two colliders.
180    /// If this returns `Some(true)`, then there may be an intersection between the two colliders.
181    pub fn intersection_pair(
182        &self,
183        collider1: ColliderHandle,
184        collider2: ColliderHandle,
185    ) -> Option<bool> {
186        let id1 = self.graph_indices.get(collider1.0)?;
187        let id2 = self.graph_indices.get(collider2.0)?;
188        self.intersection_graph
189            .interaction_pair(id1.intersection_graph_index, id2.intersection_graph_index)
190            .map(|c| c.2.intersecting)
191    }
192
193    /// All the contact pairs maintained by this narrow-phase.
194    pub fn contact_pairs(&self) -> impl Iterator<Item = &ContactPair> {
195        self.contact_graph.interactions()
196    }
197
198    /// `(edge_id, parent1, parent2)` for every *touching* contact pair. Used to (re)build
199    /// the persistent islands from scratch (bootstrap after construction or
200    /// deserialization) and by their debug validation.
201    pub(crate) fn touching_pairs_with_ids<'a>(
202        &'a self,
203        colliders: &'a ColliderSet,
204    ) -> impl Iterator<
205        Item = (
206            u32,
207            Option<crate::dynamics::RigidBodyHandle>,
208            Option<crate::dynamics::RigidBodyHandle>,
209        ),
210    > + 'a {
211        self.contact_graph
212            .graph
213            .edges
214            .iter()
215            .enumerate()
216            .filter_map(move |(edge_id, edge)| {
217                let pair = &edge.weight;
218                if !pair.has_any_active_contact() {
219                    return None;
220                }
221                let parent = |co: crate::geometry::ColliderHandle| {
222                    colliders.get(co).and_then(|c| c.parent.map(|p| p.handle))
223                };
224                Some((
225                    edge_id as u32,
226                    parent(pair.collider1),
227                    parent(pair.collider2),
228                ))
229            })
230    }
231
232    /// `(edge_id, other collider)` for every *touching* contact pair of `collider` — the
233    /// adjacency the persistent islands' local split search walks. Edge id and touching
234    /// predicate match the island contact links exactly.
235    pub(crate) fn touching_edges_with(
236        &self,
237        collider: ColliderHandle,
238    ) -> impl Iterator<Item = (u32, ColliderHandle)> + '_ {
239        self.graph_indices
240            .get(collider.0)
241            .map(|id| id.contact_graph_index)
242            .into_iter()
243            .flat_map(move |id| self.contact_graph.graph.edges(id))
244            .filter(|edge| edge.weight().has_any_active_contact())
245            .map(move |edge| {
246                let pair = edge.weight();
247                let other = if pair.collider1 == collider {
248                    pair.collider2
249                } else {
250                    pair.collider1
251                };
252                (edge.id().index() as u32, other)
253            })
254    }
255
256    /// All the intersection pairs maintained by this narrow-phase.
257    pub fn intersection_pairs(
258        &self,
259    ) -> impl Iterator<Item = (ColliderHandle, ColliderHandle, bool)> + '_ {
260        self.intersection_graph
261            .interactions_with_endpoints()
262            .map(|e| (e.0, e.1, e.2.intersecting))
263    }
264}