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}