linear_sim/collision/contact/
mod.rs1use std;
2use stash::Stash;
3use vec_map::VecMap;
4#[cfg(feature = "derive_serdes")]
5use serde::{Deserialize, Serialize};
6
7use crate::{constraint, event, object};
8use super::{CONTACT_DISTANCE, InternalId, ObjectPair, Proximity};
9
10pub (crate) mod group;
11pub (crate) use self::group::Group;
12
13#[cfg_attr(feature = "derive_serdes", derive(Deserialize, Serialize))]
14#[derive(Clone, Debug, PartialEq)]
15pub struct Contact {
16 pub constraint : constraint::Planar
17}
18
19#[cfg_attr(feature = "derive_serdes", derive(Deserialize, Serialize))]
31#[derive(Clone, Debug, PartialEq)]
32pub struct Colliding {
33 pub contact : Contact,
34 pub restitution : f64
35}
36
37#[cfg_attr(feature = "derive_serdes", derive(Deserialize, Serialize))]
39#[derive(Clone, Debug)]
40pub (crate) struct Manager {
41 pub contact_groups : Option <Stash <Group>>,
44 object_contacts_static : VecMap <u32>,
49 object_group_contacts_dynamic : VecMap <(group::KeyType, u32)>
51}
52
53impl Manager {
54 pub fn get_group (&self, key : group::KeyType) -> Option <&Group> {
55 self.contact_groups.as_ref().unwrap().get (key as usize)
56 }
57 pub fn get_group_mut (&mut self, key : group::KeyType) -> Option <&mut Group> {
58 self.contact_groups.as_mut().unwrap().get_mut (key as usize)
59 }
60 pub fn remove_group (&mut self, key : group::KeyType) -> Option <Group> {
61 self.contact_groups.as_mut().unwrap().take (key as usize)
62 }
63 pub fn add_contact (&mut self, object_pair : ObjectPair, contact : Contact) {
64 let (object_id_a, object_id_b) = object_pair.into();
65 let group = match (
66 self.get_group_key (object_id_a), self.get_group_key (object_id_b)
67 ) {
68 (Some (group_a), None) => {
69 self.increment_contact (object_id_a);
71 self.assign_dynamic_group_key (object_id_b, group_a);
72 self.get_group_mut (group_a).unwrap()
73 }
74 (None, Some (group_b)) => {
75 if object_id_a.kind() == object::Kind::Dynamic {
77 self.assign_dynamic_group_key (object_id_a, group_b);
78 } else {
79 self.increment_contact (object_id_a);
80 }
81 self.increment_contact (object_id_b);
82 self.get_group_mut (group_b).unwrap()
83 }
84 (Some (group_a), Some (group_b)) => {
85 self.increment_contact (object_id_a);
86 self.increment_contact (object_id_b);
87 if group_a == group_b {
88 self.get_group_mut (group_a).unwrap()
89 } else {
90 let group_b = self.remove_group (group_b).unwrap();
92 for (pair, _) in group_b.contacts.iter() {
93 let (id_a, id_b) = (*pair).into();
94 if id_a.kind() == object::Kind::Dynamic {
95 self.change_dynamic_group_key (id_a, group_a);
96 }
97 self.change_dynamic_group_key (id_b, group_a);
98 }
99 let group_a = self.get_group_mut (group_a).unwrap();
100 group_a.contacts.extend (group_b.contacts);
101 group_a
102 }
103 }
104 (None, None) => {
105 let new_group_index = self.contact_groups.as_mut().unwrap()
107 .put (Group::default());
108 debug_assert!(new_group_index < group::KeyType::MAX as usize);
109 let new_group_key = new_group_index as group::KeyType;
110 if object_id_a.kind() == object::Kind::Dynamic {
111 self.assign_dynamic_group_key (object_id_a, new_group_key);
112 } else {
113 self.increment_contact (object_id_a);
114 }
115 self.assign_dynamic_group_key (object_id_b, new_group_key);
116 self.get_group_mut (new_group_key).unwrap()
117 }
118 };
119 group.contacts.push ((object_pair, contact));
120 }
121
122 #[must_use]
127 pub fn remove_object (&mut self, object_id : InternalId) -> bool {
128 if let Some (group_key) = self.get_group_key (object_id) {
129 debug_assert_eq!(object_id.kind(), object::Kind::Dynamic);
130 let group = self.get_group_mut (group_key).unwrap();
131 let removed = group.remove_object (object_id);
132 let empty = group.contacts.is_empty();
133 if empty {
134 let _ = self.remove_group (group_key).unwrap();
135 }
136 for id in removed {
137 self.decrement_contact (id);
138 }
139 self.object_group_contacts_dynamic.remove (object_id.key().index())
140 .unwrap();
141 true
142 } else if object_id.kind() == object::Kind::Static {
143 let index = object_id.key().index();
144 if let Some (mut contact_count) =
145 self.object_contacts_static.remove (index)
146 {
147 debug_assert!(contact_count > 0);
148 let mut empty = vec![];
149 let mut contact_groups = self.contact_groups.take().unwrap();
150 for (i, group) in contact_groups.iter_mut() {
151 let removed = group.remove_object (object_id);
152 if group.contacts.is_empty() {
153 empty.push (i);
154 }
155 contact_count -= removed.len() as u32;
156 for id in removed {
157 self.decrement_contact (id);
158 }
159 if contact_count == 0 {
160 break
161 }
162 }
163 for i in empty {
164 contact_groups.take (i);
165 }
166 self.contact_groups = Some (contact_groups);
167 true
168 } else {
169 false
170 }
171 } else {
172 false
173 }
174 }
175
176 pub fn output_contacts (&self, output : &mut Vec <event::Output>) {
177 for group in self.contact_groups.as_ref().unwrap().values() {
178 for (object_pair, contact) in group.contacts.iter().cloned() {
179 let (id_a, id_b) = object_pair.into();
180 output.push (event::Contact {
181 object_id_a: id_a.into(),
182 object_id_b: id_b.into(),
183 contact
184 }.into())
185 }
186 }
187 }
188
189 pub (crate) fn remove_contacts (&mut self,
195 group : &mut Group, remove_list : &[u32]
196 ) {
197 debug_assert!(!remove_list.is_empty());
198 group.contacts = group.contacts.drain (..).enumerate().filter_map (
199 |(i, contact@(object_pair, _))|
200 if remove_list.contains (&(i as u32)) {
201 let (object_id_a, object_id_b) = object_pair.into();
202 self.decrement_contact (object_id_a);
203 self.decrement_contact (object_id_b);
204 None
205 } else {
206 Some (contact)
207 }
208 ).collect();
209 }
210
211 pub (crate) fn get_contact_count (&self, object_id : InternalId)
213 -> Option <u32>
214 {
215 let index = object_id.key().index();
216 match object_id.kind() {
217 object::Kind::Static => self.object_contacts_static.get (index).cloned(),
218 object::Kind::Dynamic => self.object_group_contacts_dynamic.get (index)
219 .map (|g| g.1),
220 _ => unreachable!()
221 }
222 }
223
224 pub (crate) fn get_group_key (&self, object_id : InternalId)
227 -> Option <group::KeyType>
228 {
229 let index = object_id.key().index();
230 match object_id.kind() {
231 object::Kind::Static => None,
233 object::Kind::Dynamic => self.object_group_contacts_dynamic.get (index)
234 .map (|g| g.0),
235 _ => unreachable!()
236 }
237 }
238
239 pub (crate) fn change_dynamic_group_key (&mut self,
241 object_id : InternalId, group_key : group::KeyType
242 ) {
243 match object_id.kind() {
244 object::Kind::Static => unreachable!(),
245 object::Kind::Dynamic => {
246 let index = object_id.key().index();
247 self.object_group_contacts_dynamic[index].0 = group_key;
248 }
249 _ => unimplemented!()
250 }
251 }
252
253 fn assign_dynamic_group_key (&mut self,
255 object_id : InternalId, group_key : group::KeyType
256 ) {
257 let index = object_id.key().index();
258 match object_id.kind() {
259 object::Kind::Static => unreachable!("call increment_contact instead"),
260 object::Kind::Dynamic =>
261 assert!(self.object_group_contacts_dynamic.insert (index, (group_key, 1))
262 .is_none()),
263 _ => unimplemented!()
264 }
265 }
266
267 fn increment_contact (&mut self, object_id : InternalId) {
271 let index = object_id.key().index();
272 match object_id.kind() {
273 object::Kind::Static =>
274 *self.object_contacts_static.entry (index).or_insert (0) += 1,
275 object::Kind::Dynamic =>
276 self.object_group_contacts_dynamic[index].1 += 1,
277 _ => unimplemented!()
278 }
279 }
280
281 fn decrement_contact (&mut self, object_id : InternalId) {
283 let index = object_id.key().index();
284 match object_id.kind() {
285 object::Kind::Dynamic => {
286 let count = &mut self.object_group_contacts_dynamic.get_mut (index)
287 .unwrap().1;
288 *count -= 1;
289 if *count == 0 {
290 self.object_group_contacts_dynamic.remove (index);
291 }
292 }
293 object::Kind::Static => {
294 let count = self.object_contacts_static.get_mut (index).unwrap();
295 *count -= 1;
296 if *count == 0 {
297 self.object_contacts_static.remove (index);
298 }
299 }
300 _ => unreachable!()
301 }
302 }
303}
304
305impl Default for Manager {
306 fn default() -> Self {
307 Manager {
308 contact_groups: Some (Stash::default()),
309 object_contacts_static: VecMap::default(),
310 object_group_contacts_dynamic: VecMap::default()
311 }
312 }
313}
314
315impl TryFrom <Proximity> for Contact {
316 type Error = ();
317 fn try_from (proximity : Proximity) -> Result <Self, Self::Error> {
318 if proximity.distance >= 0.0 && proximity.distance < CONTACT_DISTANCE {
319 Ok (Contact { constraint: proximity.into() })
320 } else {
321 Err (())
322 }
323 }
324}
325
326impl std::ops::Deref for Colliding {
327 type Target = Contact;
328 fn deref (&self) -> &Contact {
329 &self.contact
330 }
331}
332impl Eq for Colliding { }
333#[allow(clippy::non_canonical_partial_ord_impl)]
334impl PartialOrd for Colliding {
335 fn partial_cmp (&self, _rhs : &Self) -> Option <std::cmp::Ordering> {
338 unreachable!()
340 }
341}
342impl Ord for Colliding {
343 fn cmp (&self, _other : &Self) -> std::cmp::Ordering {
344 unreachable!()
346 }
347}