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}