1use std;
4#[cfg(feature = "debug_dump")]
5use std::sync::atomic;
6use std::cmp::Reverse;
7use either::Either;
8use derive_more::Into;
9use log;
10use sorted_vec::{SortedSet, ReverseSortedSet};
11use stash::Stash;
12use vec_map::VecMap;
13#[cfg(feature = "derive_serdes")]
14use serde::{Deserialize, Serialize};
15
16use crate::{component, event, geometry, math, object};
17use math::*;
18use geometry::Aabb3;
19
20pub mod contact;
21pub mod proximity;
22pub mod intersection;
23mod broad;
24
25pub use self::contact::Contact;
26pub use self::proximity::Proximity;
27pub use self::intersection::Intersection;
28use self::broad::Broad;
29
30pub const CONTACT_DISTANCE : f64 = 0.005; pub const RESTING_VELOCITY : f64 = (1.0/120.0) * CONTACT_DISTANCE;
45pub const OBJECT_KEY_MAX : object::KeyType = INTERNAL_ID_DYNAMIC_BIT - 1;
48
49pub (crate) const INTERNAL_ID_DYNAMIC_BIT : object::KeyType =
52 1 << (object::KeyType::BITS - 1); #[cfg(feature = "debug_dump")]
55pub static DEBUG_DUMP : atomic::AtomicBool = atomic::AtomicBool::new (false);
56#[cfg(feature = "debug_dump")]
57pub const DEBUG_DUMP_DETECT_RESOLVE_MAX_ITERS : u64 = 200;
58
59#[cfg_attr(feature = "derive_serdes", derive(Deserialize, Serialize))]
65#[derive(Clone, Debug, Default)]
66pub struct Collision {
67 broad : Broad,
69 pseudo_velocities : VecMap <Vector3 <f64>>,
74 #[cfg_attr(feature = "derive_serdes", serde(skip))]
80 pipeline : Pipeline,
81 persistent : contact::Manager,
83 #[cfg(debug_assertions)]
85 detect_resolve_max_iter_count : u64,
86 #[cfg(debug_assertions)]
88 narrow_toi_max_iter_count : u64
89}
90
91#[derive(Clone, Debug, Default, PartialEq)]
95struct Pipeline {
96 pub detect_resolve_iter : u64,
99 pub broad_overlap_pairs : Vec <ObjectPair>,
101 pub mid_toi_pairs :
103 ReverseSortedSet <(Normalized <f64>, Normalized <f64>, ObjectPair)>,
104 pub narrow_toi_contacts :
106 ReverseSortedSet <(Normalized <f64>, ObjectPair, contact::Colliding)>,
107 pub resolved_collisions : Vec <event::CollisionResolve>,
108 pub overlaps : Vec <event::Overlap>,
110}
111
112#[cfg_attr(feature = "derive_serdes", derive(Deserialize, Serialize))]
114#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Into)]
115pub (crate) struct ObjectPair (InternalId, InternalId);
116
117#[cfg_attr(feature = "derive_serdes", derive(Deserialize, Serialize))]
120#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
121pub (crate) struct InternalId (object::KeyType);
122
123#[derive(Debug)]
124struct ContactImpulses {
125 pub impulse_normal_a : Vector3 <f64>,
126 pub impulse_normal_b : Vector3 <f64>,
127 pub impulse_tangent_a : Vector3 <f64>,
128 pub impulse_tangent_b : Vector3 <f64>
129}
130
131#[derive(Debug)]
132struct ContactPostImpulses {
133 pub pseudo_impulse_a : Vector3 <f64>,
134 pub pseudo_impulse_b : Vector3 <f64>
135}
136
137pub fn report_sizes() {
142 use std::mem::size_of;
143 println!("collision report sizes...");
144
145 println!(" size of Collision: {}", size_of::<Collision>());
146
147 println!("...collision report sizes");
148}
149
150fn lerp_object <O : object::Temporal> (
152 object : &mut O, pseudovelocity : Vector3 <f64>, t_relative : f64
153) {
154 let component::Position (position) = object.position().clone();
155 object.position_mut().0 = position +
156 t_relative * object.derivatives().velocity + t_relative * pseudovelocity;
157}
158
159fn contact_constrain_velocity (
160 contact : contact::Contact,
161 restitution : f64, mut object_a : Either <&object::Static, &mut object::Dynamic>,
163 object_b : &mut object::Dynamic,
164 pseudovelocity_a : Option <Vector3 <f64>>,
165 pseudovelocity_b : Vector3 <f64>
166) -> Option <ContactImpulses> {
167 let velocity_effective_a = match &object_a {
168 Either::Left (_) => {
169 debug_assert!(pseudovelocity_a.is_none());
170 Vector3::zero()
171 }
172 Either::Right (object_a) => object_a.derivatives.velocity +
173 pseudovelocity_a.unwrap_or (Vector3::zero())
174 };
175 let velocity_effective_b =
176 object_b.derivatives.velocity + pseudovelocity_b;
177 let velocity_effective_relative =
178 velocity_effective_a - velocity_effective_b;
179 let velocity_normal_component =
180 velocity_effective_relative.dot (*contact.constraint.normal());
181 let mut impulses = None;
182 let mut mass_relative_a = 0.0;
183 let mut mass_relative_b = 0.0;
184 if velocity_normal_component < 0.0 {
185 let velocity_normal =
186 velocity_normal_component * *contact.constraint.normal();
187 let impulse_normal = velocity_normal + restitution * velocity_normal;
189 let impulse_normal_magnitude2 = impulse_normal.magnitude_squared();
190 if impulse_normal_magnitude2 < RESTING_VELOCITY * RESTING_VELOCITY {
191 return None
192 }
193 let (impulse_normal_a, impulse_normal_b) = match &mut object_a {
194 Either::Right (object_a) => {
195 let mass_combined = object_a.mass.clone() + object_b.mass.clone();
196 mass_relative_a =
197 object_a.mass.mass() * mass_combined.mass_reciprocal();
198 mass_relative_b =
199 object_b.mass.mass() * mass_combined.mass_reciprocal();
200 let impulse_normal_a = -mass_relative_b * impulse_normal;
201 let impulse_normal_b = mass_relative_a * impulse_normal;
202 object_a.derivatives.velocity += impulse_normal_a;
203 object_b.derivatives.velocity += impulse_normal_b;
204 (impulse_normal_a, impulse_normal_b)
205 }
206 Either::Left (_) => {
207 object_b.derivatives.velocity += impulse_normal;
208 (Vector3::zero(), impulse_normal)
209 }
210 };
211 let (impulse_tangent_a, impulse_tangent_b) = {
213 let velocity_tangent = velocity_effective_relative - velocity_normal;
214 let velocity_tangent_magnitude2 = velocity_tangent.magnitude_squared();
215 if velocity_tangent_magnitude2 > 0.0 {
216 let friction_a = match &object_a {
217 Either::Left (x) => x.material.friction,
218 Either::Right (x) => x.material.friction
219 };
220 let friction_coefficient = friction_a * object_b.material.friction;
221 let impulse_tangent_potential_magnitude2 =
222 friction_coefficient * impulse_normal_magnitude2;
223 let impulse_tangent = if impulse_tangent_potential_magnitude2 <
224 velocity_tangent_magnitude2
225 {
226 (impulse_tangent_potential_magnitude2.sqrt()
227 / velocity_tangent_magnitude2.sqrt()) * velocity_tangent
228 } else {
229 velocity_tangent
230 };
231 match object_a {
232 Either::Right (object_a) => {
233 let impulse_tangent_a = -mass_relative_b * impulse_tangent;
234 let impulse_tangent_b = mass_relative_a * impulse_tangent;
235 object_a.derivatives.velocity += impulse_tangent_a;
236 object_b.derivatives.velocity += impulse_tangent_b;
237 (impulse_tangent_a, impulse_tangent_b)
238 }
239 Either::Left (_) => {
240 object_b.derivatives.velocity += impulse_tangent;
241 (Vector3::zero(), impulse_tangent)
242 }
243 }
244 } else {
245 (Vector3::zero(), Vector3::zero())
246 }
247 };
248 impulses = Some (ContactImpulses {
249 impulse_normal_a, impulse_normal_b,
250 impulse_tangent_a, impulse_tangent_b
251 });
252 }
253 impulses
254}
255
256fn contact_constrain_position (
257 t_reverse : f64,
258 mut object_a : Either <&object::Static, &mut object::Dynamic>,
259 object_b : &mut object::Dynamic,
260 pseudovelocity_a : Option <&mut Vector3 <f64>>,
261 pseudovelocity_b : &mut Vector3 <f64>
262) -> (Option <ContactPostImpulses>, Proximity) {
263 let t_forward = -t_reverse;
264 let mut impulses = None;
265 let mut proximity = match &object_a {
266 Either::Left (object_a) => Proximity::query (*object_a, object_b),
267 Either::Right (object_a) => Proximity::query (*object_a, object_b)
268 };
269 log::trace!(distance=proximity.distance; "post impulse contact @ T==1.0");
270 if proximity.distance < 0.0 {
271 let (pseudo_impulse_a, pseudo_impulse_b) = match &mut object_a {
272 Either::Left (object_a) => {
273 lerp_object (object_b, *pseudovelocity_b, t_reverse);
274 let pseudo_impulse_b = -(2.0 * proximity.half_axis +
275 0.5 * CONTACT_DISTANCE * *proximity.normal) / t_forward;
276 *pseudovelocity_b += pseudo_impulse_b;
277 lerp_object (object_b, *pseudovelocity_b, t_forward);
278 proximity = Proximity::query (*object_a, object_b);
279 (Vector3::zero(), pseudo_impulse_b)
280 }
281 Either::Right (object_a) => {
282 let pseudovelocity_a = pseudovelocity_a.unwrap();
283 lerp_object (*object_a, *pseudovelocity_a, t_reverse);
284 lerp_object (object_b, *pseudovelocity_b, t_reverse);
285 let mass_combined = object_a.mass.clone() + object_b.mass.clone();
286 let mass_relative_a =
287 object_a.mass.mass() * mass_combined.mass_reciprocal();
288 let mass_relative_b =
289 object_b.mass.mass() * mass_combined.mass_reciprocal();
290 let pseudo_impulse = (2.0 * proximity.half_axis +
291 0.5 * CONTACT_DISTANCE * *proximity.normal) / t_forward;
292 let pseudo_impulse_a = mass_relative_b * pseudo_impulse;
293 let pseudo_impulse_b = -mass_relative_a * pseudo_impulse;
294 *pseudovelocity_a += pseudo_impulse_a;
295 *pseudovelocity_b += pseudo_impulse_b;
296 lerp_object (*object_a, *pseudovelocity_a, t_forward);
297 lerp_object (object_b, *pseudovelocity_b, t_forward);
298 proximity = Proximity::query (*object_a, object_b);
299 (pseudo_impulse_a, pseudo_impulse_b)
300 }
301 };
302 log::trace!(distance=proximity.distance;
303 "position corrected distance @ T==1.0");
304 debug_assert!(proximity.distance >= 0.0);
305 if cfg!(debug_assertions) {
306 math::approx::assert_abs_diff_eq!(
307 proximity.distance, 0.5 * CONTACT_DISTANCE, epsilon=0.000000001);
308 }
309 impulses = Some (ContactPostImpulses { pseudo_impulse_a, pseudo_impulse_b });
310 }
311 (impulses, proximity)
312}
313
314impl Collision {
319 pub (crate) fn broad (&self) -> &Broad {
320 &self.broad
321 }
322 pub fn try_add_object_static (&mut self,
329 objects_dynamic : &VecMap <object::Dynamic>,
330 object : &object::Static,
331 key : object::Key
332 ) -> Result <(), Vec <(object::Id, Intersection)>> {
333 let mut intersections = Vec::new();
334 if object.collidable {
335 let aabb_discrete = object.aabb_dilated();
336 let overlaps : Vec <object::Id> = self.broad
337 .overlaps_discrete (aabb_discrete).into_iter().map (|id| id.into())
338 .collect::<Vec <_>>();
339 for object_id in overlaps {
340 let proximity = match object_id.kind {
341 object::Kind::Static => continue, object::Kind::Dynamic => {
343 let object_dynamic = &objects_dynamic[object_id.key.index()];
344 if !object_dynamic.collidable {
345 continue }
347 Proximity::query (object_dynamic, object)
348 }
349 _ => unreachable!()
350 };
351 if let Ok (intersection) = proximity.try_into() {
352 intersections.push ((object_id, intersection));
353 }
354 }
355 }
356 if intersections.is_empty() {
357 self.add_object_static (object, key);
358 Ok (())
359 } else {
360 Err (intersections)
361 }
362 }
363
364 #[inline]
365 pub fn remove_object_static (&mut self, object_key : object::Key) {
366 debug_assert!(self.pipeline.is_empty());
367 let id = InternalId::new_static (object_key);
368 self.broad.remove_object (id);
369 let _ = self.persistent.remove_object (id);
370 }
371
372 pub fn try_add_object_dynamic (&mut self,
380 objects_static : &VecMap <object::Static>,
381 objects_dynamic : &VecMap <object::Dynamic>,
382 object : &object::Dynamic,
383 key : object::Key
384 ) -> Result <(), Vec <(object::Id, Intersection)>> {
385 let mut intersections = Vec::new();
386 if object.collidable {
387 let aabb_discrete = object.aabb_dilated();
388 let overlaps : Vec <object::Id> = self.broad
389 .overlaps_discrete (aabb_discrete).into_iter().map (|id| id.into())
390 .collect::<Vec <_>>();
391 for object_id in overlaps {
392 let proximity = match object_id.kind {
393 object::Kind::Static => {
394 let object_static = &objects_static[object_id.key.index()];
395 if !object_static.collidable {
396 continue }
398 Proximity::query (object_static, object)
399 }
400 object::Kind::Dynamic => {
401 let object_dynamic = &objects_dynamic[object_id.key.index()];
402 if !object_dynamic.collidable {
403 continue }
405 Proximity::query (object_dynamic, object)
406 }
407 _ => unreachable!()
408 };
409 if let Ok (intersection) = proximity.try_into() {
410 intersections.push ((object_id, intersection));
411 }
412 }
413 }
414 if intersections.is_empty() {
415 self.add_object_dynamic (object, key);
416 Ok (())
417 } else {
418 Err (intersections)
419 }
420 }
421
422 #[inline]
423 pub fn remove_object_dynamic (&mut self, key : object::Key) {
424 debug_assert!(self.pipeline.is_empty());
425 let id = InternalId::new_dynamic (key);
426 self.broad.remove_object (id);
427 self.pseudo_velocities.remove (key.index()).unwrap();
428 let _ = self.persistent.remove_object (id);
429 }
430
431 #[inline]
432 pub fn update_object_static (&mut self,
433 object : &object::Static, key : object::Key
434 ) {
435 debug_assert!(self.pipeline.is_empty());
436 self.broad.update_aabb_static (object.aabb_dilated(), key);
437 unimplemented!("TODO: collision detect and resolve any overlaps caused by \
438 updating the static object")
439 }
440
441 #[inline]
442 pub fn update_object_dynamic (&mut self,
443 object : &object::Dynamic, key : object::Key
444 ) {
445 debug_assert!(self.pipeline.is_empty());
446 let aabb = object.aabb_dilated();
447 self.broad.update_aabb_dynamic_discrete (aabb, key);
448 self.broad.update_aabb_dynamic_continuous (aabb, key);
450 log::warn!("TODO: collision detect and resolve any overlaps caused by \
451 updating the dynamic object")
452 }
453
454 pub fn detect_resolve_loop (&mut self,
473 objects_static : &mut VecMap <object::Static>,
474 objects_dynamic : &mut VecMap <object::Dynamic>,
475 step : u64,
476 output : &mut Vec <event::Output>
477 ) {
478 log::trace!(step; "detect/resolve loop");
479
480 debug_assert!(self.pipeline.is_empty());
482 self.pipeline.detect_resolve_iter = 0;
483
484 self.broad.begin_step (&objects_dynamic, step);
489
490 loop {
492 log::debug!(iter=self.pipeline.detect_resolve_iter;
493 "detect/resolve loop iteration");
494 self.detect_continuous (objects_static, objects_dynamic);
496 if !self.resolve_collision (objects_static, objects_dynamic) {
499 debug_assert!(self.pipeline.mid_toi_pairs.is_empty());
500 debug_assert!(self.pipeline.narrow_toi_contacts.is_empty());
501 break
502 }
503 self.pipeline.detect_resolve_iter += 1;
504 }
505
506 log::trace!(iters=self.pipeline.detect_resolve_iter+1;
507 "detect/resolve loop complete");
508 #[cfg(debug_assertions)]
509 {
510 if self.detect_resolve_max_iter_count
511 < (self.pipeline.detect_resolve_iter + 1)
512 {
513 #[cfg(feature = "debug_dump")]
514 if self.pipeline.detect_resolve_iter >
515 DEBUG_DUMP_DETECT_RESOLVE_MAX_ITERS
516 {
517 DEBUG_DUMP.store (true, atomic::Ordering::SeqCst);
518 }
519 self.detect_resolve_max_iter_count = self.pipeline.detect_resolve_iter;
520 }
521 log::debug!(max_iter_count=self.detect_resolve_max_iter_count;
522 "detect/resolve loop max iters");
523 }
524
525 for collision_resolve in self.pipeline.resolved_collisions.drain (..) {
527 output.push (collision_resolve.into());
528 }
529 for overlap in self.pipeline.overlaps.drain (..) {
530 output.push (overlap.into());
531 }
532
533 self.persistent.output_contacts (output);
535
536 for (_, pseudovelocity) in self.pseudo_velocities.iter_mut() {
538 *pseudovelocity = Vector3::zero();
539 }
540
541 debug_assert!(self.pipeline.is_empty());
543 }
544
545 pub fn constrain_contact_positions (&mut self,
547 objects_static : &VecMap <object::Static>,
548 objects_dynamic : &mut VecMap <object::Dynamic>
549 ) {
550 let mut remove_groups = vec![];
551 let mut new_groups = vec![];
552 let mut contact_groups = self.persistent.contact_groups.take().unwrap();
553 for (group_index, group) in contact_groups.iter_mut() {
554 log::debug!(group_index, contacts_count=group.contacts.len();
555 "group constrain positions");
556 log::trace!(group_index, contacts:?=group.contacts;
557 "group constrain positions contacts");
558 let mut iter = 0;
559 let mut remove_contacts = vec![];
560 loop {
561 remove_contacts.clear();
562 let mut satisfied = true;
563 for (contact_index, (object_pair, contact)) in
564 group.contacts.iter_mut().enumerate()
565 {
566 let (object_id_a, object_id_b) = (*object_pair).into();
567 let index_a = object_id_a.key().index();
568 let index_b = object_id_b.key().index();
569 let mut object_a = match object_id_a.kind() {
570 object::Kind::Static =>
571 Either::Left (objects_static[index_a].clone()),
572 object::Kind::Dynamic =>
573 Either::Right (objects_dynamic[index_a].clone()),
574 _ => unreachable!()
575 };
576 debug_assert_eq!(object_id_b.kind(), object::Kind::Dynamic);
577 let mut object_b = objects_dynamic[index_b].clone();
578 let mut pseudovelocity_a = match object_a {
579 Either::Left (_) => None,
580 Either::Right (_) => Some (self.pseudo_velocities[index_a].clone())
581 };
582 let mut pseudovelocity_b = self.pseudo_velocities[index_b].clone();
583 let (maybe_impulses, proximity) = contact_constrain_position (
584 -1.0,
585 object_a.as_mut().map_left (|object_static| &*object_static),
586 &mut object_b, pseudovelocity_a.as_mut(), &mut pseudovelocity_b
587 );
588 if maybe_impulses.is_some() {
589 satisfied = false;
590 match object_a {
591 Either::Right (object_a) => {
592 objects_dynamic[index_a] = object_a;
593 self.pseudo_velocities[index_a] = pseudovelocity_a.unwrap();
594 }
595 Either::Left (_) => {}
596 }
597 objects_dynamic[index_b] = object_b;
598 self.pseudo_velocities[index_b] = pseudovelocity_b;
599 }
600 if proximity.distance >= CONTACT_DISTANCE {
604 log::debug!(object_pair:?, contact:?, proximity:?;
605 "removing contact @ T==1.0");
606 remove_contacts.push (contact_index as u32);
607 } else {
608 *contact = proximity.try_into().unwrap();
610 }
611 }
612 iter += 1;
613 if satisfied {
614 log::debug!(group_index, iters=iter;
616 "group position constraint satisfied");
617 if !remove_contacts.is_empty() {
618 self.persistent.remove_contacts (group, remove_contacts.as_slice());
619 if group.contacts.is_empty() {
620 remove_groups.push (group_index as contact::group::KeyType);
621 } else {
622 let partitions = group.partition();
623 if !partitions.is_empty() {
624 remove_groups.push (group_index as contact::group::KeyType);
625 new_groups.extend (partitions);
626 }
627 }
628 }
629 break
630 }
631 }
632 }
633 for group_key in remove_groups {
634 let _ = contact_groups.take (group_key as usize).unwrap();
635 }
636 for new_group in new_groups {
637 let dynamic_ids = new_group.dynamic_ids();
638 let group_key = contact_groups.put (new_group) as contact::group::KeyType;
639 for dynamic_id in dynamic_ids.into_vec() {
640 self.persistent.change_dynamic_group_key (dynamic_id, group_key);
641 }
642 }
643 self.persistent.contact_groups = Some (contact_groups);
644 }
645
646 pub fn constrain_contact_velocities (&self,
648 objects_static : &VecMap <object::Static>,
649 objects_dynamic : &mut VecMap <object::Dynamic>
650 ) {
651 for (group_index, group) in self.contact_groups().iter() {
652 log::debug!(group_index, contacts_count=group.contacts.len();
653 "group constrain velocities");
654 log::trace!(group_index, contacts:?=group.contacts;
655 "group constrain velocities contacts");
656 let mut iter = 0;
657 loop {
658 let mut satisfied = true;
659 for (object_pair, contact) in group.contacts.iter() {
660 let (object_id_a, object_id_b) = (*object_pair).into();
661 let index_a = object_id_a.key().index();
662 let index_b = object_id_b.key().index();
663 let mut object_a = match object_id_a.kind() {
664 object::Kind::Static =>
665 Either::Left (objects_static[index_a].clone()),
666 object::Kind::Dynamic =>
667 Either::Right (objects_dynamic[index_a].clone()),
668 _ => unreachable!()
669 };
670 debug_assert_eq!(object_id_b.kind(), object::Kind::Dynamic);
671 let mut object_b = objects_dynamic[index_b].clone();
672 if contact_constrain_velocity (
674 contact.clone(), 0.0,
675 object_a.as_mut().map_left (|object_static| &*object_static),
676 &mut object_b, None, Vector3::zero()
677 ).is_some() {
678 match object_a {
679 Either::Right (object_a) => objects_dynamic[index_a] = object_a,
680 Either::Left (_) => {}
681 }
682 objects_dynamic[index_b] = object_b;
683 satisfied = false;
684 }
685 }
686 iter += 1;
687 if satisfied {
688 log::debug!(group_index, iters=iter;
690 "group velocity constraint satisfied");
691 break
692 }
693 }
694 }
695 }
696
697 pub (crate) fn contact_groups (&self) -> &Stash <contact::Group> {
698 self.persistent.contact_groups.as_ref().unwrap()
699 }
700
701 fn detect_continuous (&mut self,
707 objects_static : &VecMap <object::Static>,
708 objects_dynamic : &VecMap <object::Dynamic>
709 ) {
710 self.broad_overlap_pairs_continuous();
712 self.mid_toi_pairs (&objects_dynamic);
714 self.narrow_toi_contacts (&objects_static, &objects_dynamic);
716 }
717
718 fn resolve_collision (&mut self,
728 objects_static : &VecMap <object::Static>,
729 objects_dynamic : &mut VecMap <object::Dynamic>
730 ) -> bool {
731 if let Some (Reverse ((toi, object_pair, contact))) =
732 self.pipeline.narrow_toi_contacts.pop()
733 {
734 let (object_id_a, object_id_b) = object_pair.into();
737 let kind_a = object_id_a.kind();
738 let kind_b = object_id_b.kind();
739 let index_a = object_id_a.key().index();
740 let index_b = object_id_b.key().index();
741 let collidable = {
743 let collidable_a = match kind_a {
744 object::Kind::Static => objects_static[index_a].collidable,
745 object::Kind::Dynamic => objects_dynamic[index_a].collidable,
746 _ => unreachable!()
747 };
748 debug_assert_eq!(kind_b, object::Kind::Dynamic);
749 let collidable_b = objects_dynamic[index_b].collidable;
750 collidable_a && collidable_b
751 };
752 if !collidable {
753 let overlap = event::Overlap {
754 object_id_a: object_id_a.into(),
755 object_id_b: object_id_b.into()
756 };
757 log::debug!(toi=*toi, overlap:?; "nocollide overlap");
758 self.pipeline.overlaps.push (overlap);
759 return true
760 }
761 log::debug!(toi=*toi, object_pair:?=(object_id_a, object_id_b);
762 "resolve collision");
763 let maybe_group_a = self.persistent.get_group_key (object_id_a);
765 let maybe_group_b = {
766 let maybe_group_b = self.persistent.get_group_key (object_id_b);
767 if maybe_group_a == maybe_group_b {
768 None
770 } else {
771 maybe_group_b
772 }
773 };
774 let collision_resolve = self.resolve (objects_static, objects_dynamic,
776 toi, object_id_a, object_id_b, contact.clone(), maybe_group_a,
777 maybe_group_b);
778 log::trace!(collision_resolve:?; "resolved collision");
779 self.pipeline.resolved_collisions.push (collision_resolve);
780 true
781 } else {
782 debug_assert!(self.pipeline.mid_toi_pairs.is_empty());
784 false
785 }
786 }
787
788 fn resolve (
789 &mut self,
790 objects_static : &VecMap <object::Static>,
791 objects_dynamic : &mut VecMap <object::Dynamic>,
792 toi : Normalized <f64>,
793 object_id_a : InternalId,
794 object_id_b : InternalId,
795 contact : contact::Colliding,
796 group_key_a : Option <contact::group::KeyType>,
797 group_key_b : Option <contact::group::KeyType>
798 ) -> event::CollisionResolve {
799 use math::num_traits::Zero;
806 let mut dynamic_ids = SortedSet::new();
807 if object_id_a.kind() == object::Kind::Dynamic {
808 dynamic_ids.push (object_id_a);
809 };
810 dynamic_ids.push (object_id_b);
811 let group_a = group_key_a
812 .map (|group_key| self.persistent.get_group (group_key).unwrap());
813 let group_b = group_key_b
814 .map (|group_key| self.persistent.get_group (group_key).unwrap());
815 group_a.map (|group| dynamic_ids.extend (group.dynamic_ids().into_vec()));
816 group_b.map (|group| dynamic_ids.extend (group.dynamic_ids().into_vec()));
817 let mut dynamic_modified = SortedSet::new();
821 let lerp_objects =
823 |objects_dynamic : &mut VecMap <object::Dynamic>, time_delta|
824 for id in dynamic_ids.iter() {
825 let index = id.key().index();
826 let object = &mut objects_dynamic[index];
827 let pseudovelocity = self.pseudo_velocities[index].clone();
828 lerp_object (object, pseudovelocity, time_delta);
829 };
830 let (t_reverse, t_forward) = {
831 let toi_f64 : f64 = *toi; (-1.0 + toi_f64, 1.0 - toi_f64)
833 };
834 lerp_objects (objects_dynamic, t_reverse);
835 let toi_aabbs = dynamic_ids.iter().map (|id|{
836 let index = id.key().index();
837 objects_dynamic[index].aabb_dilated()
838 }).collect::<Vec <_>>();
839 let constrain_velocity = |
841 objects_dynamic : &mut VecMap <object::Dynamic>,
842 pseudovelocities : &VecMap <Vector3 <f64>>,
843 contact : Contact,
844 restitution : f64,
845 object_id_a : InternalId,
846 object_id_b : InternalId
847 | {
848 let key_a = object_id_a.key();
849 let key_b = object_id_b.key();
850 let index_a = key_a.index();
851 let index_b = key_b.index();
852 let mut object_a = match object_id_a.kind() {
853 object::Kind::Static => Either::Left (objects_static[index_a].clone()),
854 object::Kind::Dynamic => Either::Right (objects_dynamic[index_a].clone()),
855 _ => unreachable!()
856 };
857 debug_assert_eq!(object_id_b.kind(), object::Kind::Dynamic);
858 let mut object_b = objects_dynamic[index_b].clone();
859 let pseudovelocity_a = if object_id_a.kind() == object::Kind::Dynamic {
860 Some (pseudovelocities[index_a].clone())
861 } else {
862 None
863 };
864 let pseudovelocity_b = pseudovelocities[index_b].clone();
865 let maybe_impulses = contact_constrain_velocity (
866 contact, restitution,
867 object_a.as_mut().map_left (|object_static| &*object_static),
868 &mut object_b, pseudovelocity_a, pseudovelocity_b
869 );
870 if maybe_impulses.is_some() {
871 match object_a {
872 Either::Right (object_a) => objects_dynamic[index_a] = object_a,
873 Either::Left (_) => {}
874 }
875 objects_dynamic[index_b] = object_b;
876 }
877 maybe_impulses
878 };
879 let mut impulse_normal_a = Vector3::zero();
880 let mut impulse_normal_b = Vector3::zero();
881 let mut impulse_tangent_a = Vector3::zero();
882 let mut impulse_tangent_b = Vector3::zero();
883 let mut iter = 0;
884 loop {
885 let mut satisfied = true;
886 if let Some (impulses) = constrain_velocity (
887 objects_dynamic, &self.pseudo_velocities, contact.contact.clone(),
888 contact.restitution, object_id_a, object_id_b
889 ) {
890 satisfied = group_a.is_none() && group_b.is_none();
892 impulse_normal_a += impulses.impulse_normal_a;
893 impulse_normal_b += impulses.impulse_normal_b;
894 impulse_tangent_a += impulses.impulse_tangent_a;
895 impulse_tangent_b += impulses.impulse_tangent_b;
896 }
897 let mut constrain_group = |group : &contact::Group|
898 for (object_pair, contact) in group.contacts.iter().cloned() {
899 let (object_id_a, object_id_b) = object_pair.into();
900 if constrain_velocity (
901 objects_dynamic, &self.pseudo_velocities, contact, 0.0,
902 object_id_a, object_id_b
903 ).is_some() {
904 if object_id_a.kind() == object::Kind::Dynamic {
905 dynamic_modified.push (object_id_a);
906 }
907 dynamic_modified.push (object_id_b);
908 satisfied = false;
909 }
910 };
911 if let Some (group) = group_a {
912 constrain_group (group);
913 }
914 if let Some (group) = group_b {
915 constrain_group (group);
916 }
917 iter += 1;
918 if satisfied {
919 log::debug!(iters=iter; "collision velocity constraint satisfied");
920 break
921 }
922 }
923 lerp_objects (objects_dynamic, t_forward);
925 let constrain_position = |
927 objects_dynamic : &mut VecMap <object::Dynamic>,
928 pseudovelocities : &mut VecMap <Vector3 <f64>>,
929 object_id_a : InternalId,
930 object_id_b : InternalId
931 | {
932 let key_a = object_id_a.key();
933 let key_b = object_id_b.key();
934 let index_a = key_a.index();
935 let index_b = key_b.index();
936 let mut object_a = match object_id_a.kind() {
937 object::Kind::Static => Either::Left (objects_static[index_a].clone()),
938 object::Kind::Dynamic => Either::Right (objects_dynamic[index_a].clone()),
939 _ => unreachable!()
940 };
941 debug_assert_eq!(object_id_b.kind(), object::Kind::Dynamic);
942 let mut object_b = objects_dynamic[index_b].clone();
943 let mut pseudovelocity_a = if object_id_a.kind() == object::Kind::Dynamic {
944 Some (pseudovelocities[index_a].clone())
945 } else {
946 None
947 };
948 let mut pseudovelocity_b = pseudovelocities[index_b].clone();
949 let (maybe_impulses, proximity) = contact_constrain_position (
950 t_reverse,
951 object_a.as_mut().map_left (|object_static| &*object_static),
952 &mut object_b, pseudovelocity_a.as_mut(), &mut pseudovelocity_b
953 );
954 if maybe_impulses.is_some() {
955 match object_a {
956 Either::Right (object_a) => {
957 objects_dynamic[index_a] = object_a;
958 pseudovelocities[index_a] = pseudovelocity_a.unwrap();
959 }
960 Either::Left (_) => {}
961 }
962 objects_dynamic[index_b] = object_b;
963 pseudovelocities[index_b] = pseudovelocity_b;
964 }
965 (maybe_impulses, proximity)
966 };
967 let mut final_proximities = vec![
968 Proximity {
969 distance: 0.0,
970 half_axis: Vector3::zero(),
971 midpoint: Point::origin(),
972 normal: Unit3::axis_z()
973 };
974 1 + group_a.map (|group| group.contacts.len()).unwrap_or (0) +
975 group_b.map (|group| group.contacts.len()).unwrap_or (0)
976 ];
977 let mut pseudo_impulse_a = Vector3::zero();
978 let mut pseudo_impulse_b = Vector3::zero();
979 let mut iter = 0;
980 loop {
981 let mut satisfied = true;
982 let mut contact_index = 0;
983 let (maybe_impulses, proximity) = constrain_position (
984 objects_dynamic, &mut self.pseudo_velocities, object_id_a, object_id_b
985 );
986 final_proximities[contact_index] = proximity;
987 contact_index += 1;
988 if let Some (impulses) = maybe_impulses {
989 satisfied = group_a.is_none() && group_b.is_none();
991 pseudo_impulse_a += impulses.pseudo_impulse_a;
992 pseudo_impulse_b += impulses.pseudo_impulse_b;
993 }
994 let mut constrain_group = |group : &contact::Group|
995 for (object_pair, _) in group.contacts.iter() {
996 let (object_id_a, object_id_b) = object_pair.clone().into();
997 let (maybe_impulses, proximity) = constrain_position (
998 objects_dynamic, &mut self.pseudo_velocities,
999 object_id_a, object_id_b
1000 );
1001 final_proximities[contact_index] = proximity;
1002 contact_index += 1;
1003 if maybe_impulses.is_some() {
1004 if object_id_a.kind() == object::Kind::Dynamic {
1005 dynamic_modified.push (object_id_a);
1006 }
1007 dynamic_modified.push (object_id_b);
1008 satisfied = false;
1009 }
1010 };
1011 if let Some (group) = group_a {
1012 constrain_group (group);
1013 }
1014 if let Some (group) = group_b {
1015 constrain_group (group);
1016 }
1017 iter += 1;
1018 if satisfied {
1019 log::debug!(iters=iter; "collision position constraint satisfied");
1020 break
1021 }
1022 }
1023 let object_pair = (object_id_a, object_id_b).into();
1027 if !impulse_normal_b.is_zero() || !impulse_tangent_b.is_zero() ||
1028 !pseudo_impulse_b.is_zero()
1029 {
1030 if object_id_a.kind() == object::Kind::Dynamic {
1031 debug_assert!(!impulse_normal_a.is_zero() ||
1032 !impulse_tangent_a.is_zero() || !pseudo_impulse_a.is_zero());
1033 dynamic_modified.push (object_id_a);
1034 }
1035 dynamic_modified.push (object_id_b);
1036 }
1037 self.broad.add_resolved (object_pair);
1038 let mut final_proximities = final_proximities.into_iter();
1039 let collision_final_proximity = final_proximities.next().unwrap();
1040 let mut update_group = |
1043 final_proximities : &mut std::vec::IntoIter <Proximity>,
1044 group_key : contact::group::KeyType
1045 | {
1046 let mut contact_groups = self.persistent.contact_groups.take().unwrap();
1047 let group = &mut contact_groups[group_key as usize];
1048 let mut remove_contacts = vec![];
1049 for (i, proximity) in
1050 final_proximities.take (group.contacts.len()).enumerate()
1051 {
1052 let contact = &mut group.contacts[i];
1053 self.broad.add_resolved (contact.0);
1054 if let Ok (update_contact) = Contact::try_from (proximity) {
1055 contact.1 = update_contact;
1056 } else {
1057 remove_contacts.push (i as u32);
1058 }
1059 }
1060 if !remove_contacts.is_empty() {
1061 self.persistent.remove_contacts (group, remove_contacts.as_slice());
1062 if group.contacts.is_empty() {
1063 let _ = contact_groups.take (group_key as usize).unwrap();
1064 } else {
1065 let partitions = group.partition();
1066 if !partitions.is_empty() {
1067 let _ = contact_groups.take (group_key as usize).unwrap();
1068 for new_group in partitions {
1069 let dynamic_ids = new_group.dynamic_ids();
1070 let group_key = contact_groups.put (new_group)
1071 as contact::group::KeyType;
1072 for dynamic_id in dynamic_ids.into_vec() {
1073 self.persistent.change_dynamic_group_key (dynamic_id, group_key);
1074 }
1075 }
1076 }
1077 }
1078 }
1079 self.persistent.contact_groups = Some (contact_groups);
1080 };
1081 if let Some (group_key) = group_key_a {
1082 update_group (&mut final_proximities, group_key);
1083 }
1084 if let Some (group_key) = group_key_b {
1085 update_group (&mut final_proximities, group_key);
1086 }
1087 if let Ok (contact) = collision_final_proximity.try_into() {
1088 log::trace!(object_pair:?, contact:?; "creating contact @ T==1.0");
1089 self.persistent.add_contact (object_pair, contact);
1090 }
1091 for id in dynamic_modified.iter() {
1094 let i = dynamic_ids.binary_search_by_key (&id, |x| x).unwrap();
1095 let key = id.key();
1096 let index = key.index();
1097 let object = &objects_dynamic[index];
1098 let aabb_discrete = object.aabb_dilated();
1099 let aabb_continuous = Aabb3::union (&toi_aabbs[i], &aabb_discrete);
1100 self.broad.update_aabb_dynamic_discrete (aabb_discrete, key);
1101 self.broad.update_aabb_dynamic_continuous (aabb_continuous, key);
1102 }
1103 self.pipeline.remove_resolved_dynamic (&dynamic_modified);
1104 self.broad.set_modified (dynamic_modified);
1106 let object_id_a = object_id_a.into();
1108 let object_id_b = object_id_b.into();
1109 event::CollisionResolve {
1110 toi, contact,
1111 object_id_a, object_id_b,
1112 impulse_normal_a, impulse_normal_b,
1113 impulse_tangent_a, impulse_tangent_b,
1114 pseudo_impulse_a, pseudo_impulse_b
1115 }
1116 }
1117
1118 #[inline]
1123 fn broad_overlap_pairs_continuous (&mut self) {
1124 self.broad.overlap_pairs_continuous (
1125 &mut self.pipeline.broad_overlap_pairs, self.pipeline.detect_resolve_iter);
1126 self.pipeline.broad_overlap_pairs.retain (
1128 |pair|{
1129 let (id_a, id_b) = (*pair).into();
1130 let id_a = object::Id::from (id_a);
1131 let id_b = object::Id::from (id_b);
1132 for event::Overlap { object_id_a, object_id_b } in
1133 self.pipeline.overlaps.iter()
1134 {
1135 if object_id_a == &id_a && object_id_b == &id_b {
1136 return false
1137 }
1138 }
1139 true
1140 }
1141 );
1142 log::trace!(overlap_pairs:?=self.pipeline.broad_overlap_pairs;
1143 "broad overlap pairs");
1144 }
1145
1146 fn mid_toi_pairs (&mut self, objects_dynamic : &VecMap <object::Dynamic>) {
1153 use sorted_vec::FindOrInsert;
1154 let last_toi = self.pipeline.resolved_collisions.last()
1155 .map_or (0.0, |collision_resolve| *collision_resolve.toi);
1156 'outer: for object_pair in self.pipeline.broad_overlap_pairs.drain (..) {
1157 let (object_id_a, object_id_b) = object_pair.into();
1158 debug_assert_eq!(object_id_b.kind(), object::Kind::Dynamic);
1159 match object_id_a.kind() {
1160 object::Kind::Static => {
1164 let id_static = object::Id::from (object_id_a);
1165 let id_dynamic = object::Id::from (object_id_b);
1166 let key_static = id_static.key;
1167 let key_dynamic = id_dynamic.key;
1168 let _index_static = key_static.index();
1169 let index_dynamic = key_dynamic.index();
1170 match (
1171 self.persistent.get_contact_count (object_id_a),
1172 self.persistent.get_group_key (object_id_b)
1173 ) {
1174 (Some (static_contact_count), Some (dynamic_group_key)) => {
1175 debug_assert!(static_contact_count > 0);
1176 let group = self.persistent.get_group (dynamic_group_key)
1177 .unwrap();
1178 for (pair, _) in group.contacts.iter() {
1179 if *pair == object_pair {
1180 continue 'outer
1181 }
1182 }
1183 }
1184 _ => {}
1185 }
1186 let dynamic_object = &objects_dynamic[index_dynamic];
1188 let dynamic_velocity = dynamic_object.derivatives.velocity;
1189 let dynamic_pseudovelocity = self.pseudo_velocities[index_dynamic];
1190 let dynamic_velocity_effective = dynamic_velocity + dynamic_pseudovelocity;
1191 let static_aabb = self.broad.get_aabb_static (key_static);
1192 let dynamic_aabb_current = self.broad
1193 .get_aabb_dynamic_discrete (key_dynamic);
1194 let _dynamic_aabb_swept = self.broad
1195 .get_aabb_dynamic_continuous (key_dynamic);
1196 let dynamic_aabb_previous = Aabb3::with_minmax (
1197 dynamic_aabb_current.min() - dynamic_velocity_effective,
1198 dynamic_aabb_current.max() - dynamic_velocity_effective);
1199 let dynamic_velocity_effective_reciprocal =
1201 dynamic_velocity_effective.recip();
1202 let t_margin_x =
1204 (0.5 * CONTACT_DISTANCE * dynamic_velocity_effective_reciprocal.x)
1205 .abs();
1206 let t_margin_y =
1207 (0.5 * CONTACT_DISTANCE * dynamic_velocity_effective_reciprocal.y)
1208 .abs();
1209 let t_margin_z =
1210 (0.5 * CONTACT_DISTANCE * dynamic_velocity_effective_reciprocal.z)
1211 .abs();
1212
1213 let (interval_start_x, interval_end_x) = if
1214 dynamic_velocity_effective.x == 0.0
1215 {
1216 debug_assert!(
1217 dynamic_aabb_current.max().0.x > static_aabb.min().0.x &&
1218 static_aabb.max().0.x > dynamic_aabb_current.min().0.x);
1219 debug_assert!(
1220 dynamic_aabb_previous.max().0.x > static_aabb.min().0.x &&
1221 static_aabb.max().0.x > dynamic_aabb_previous.min().0.x);
1222 (std::f64::NEG_INFINITY, std::f64::INFINITY)
1223 } else if dynamic_velocity_effective.x > 0.0 {
1224 ( (static_aabb.min().0.x - dynamic_aabb_previous.max().0.x) *
1225 dynamic_velocity_effective_reciprocal.x - t_margin_x,
1226 (static_aabb.max().0.x - dynamic_aabb_previous.min().0.x) *
1227 dynamic_velocity_effective_reciprocal.x + t_margin_x
1228 )
1229 } else {
1230 debug_assert!(dynamic_velocity_effective.x < 0.0);
1231 ( (static_aabb.max().0.x - dynamic_aabb_previous.min().0.x) *
1232 dynamic_velocity_effective_reciprocal.x - t_margin_x,
1233 (static_aabb.min().0.x - dynamic_aabb_previous.max().0.x) *
1234 dynamic_velocity_effective_reciprocal.x + t_margin_x
1235 )
1236 };
1237
1238 let (interval_start_y, interval_end_y) = if
1239 dynamic_velocity_effective.y == 0.0
1240 {
1241 debug_assert!(
1242 dynamic_aabb_current.max().0.y > static_aabb.min().0.y &&
1243 static_aabb.max().0.y > dynamic_aabb_current.min().0.y);
1244 debug_assert!(
1245 dynamic_aabb_previous.max().0.y > static_aabb.min().0.y &&
1246 static_aabb.max().0.y > dynamic_aabb_previous.min().0.y);
1247 (std::f64::NEG_INFINITY, std::f64::INFINITY)
1248 } else if dynamic_velocity_effective.y > 0.0 {
1249 ( dynamic_velocity_effective_reciprocal.y *
1250 (static_aabb.min().0.y - dynamic_aabb_previous.max().0.y)
1251 - t_margin_y,
1252 dynamic_velocity_effective_reciprocal.y *
1253 (static_aabb.max().0.y - dynamic_aabb_previous.min().0.y)
1254 + t_margin_y
1255 )
1256 } else {
1257 debug_assert!(dynamic_velocity_effective.y < 0.0);
1258 ( dynamic_velocity_effective_reciprocal.y *
1259 (static_aabb.max().0.y - dynamic_aabb_previous.min().0.y)
1260 - t_margin_y,
1261 dynamic_velocity_effective_reciprocal.y *
1262 (static_aabb.min().0.y - dynamic_aabb_previous.max().0.y)
1263 + t_margin_y
1264 )
1265 };
1266
1267 let (interval_start_z, interval_end_z) = if
1268 dynamic_velocity_effective.z == 0.0
1269 {
1270 debug_assert!(
1271 dynamic_aabb_current.max().0.z > static_aabb.min().0.z &&
1272 static_aabb.max().0.z > dynamic_aabb_current.min().0.z);
1273 debug_assert!(
1274 dynamic_aabb_previous.max().0.z > static_aabb.min().0.z &&
1275 static_aabb.max().0.z > dynamic_aabb_previous.min().0.z);
1276 (std::f64::NEG_INFINITY, std::f64::INFINITY)
1277 } else if dynamic_velocity_effective.z > 0.0 {
1278 ( dynamic_velocity_effective_reciprocal.z *
1279 (static_aabb.min().0.z - dynamic_aabb_previous.max().0.z)
1280 - t_margin_z,
1281 dynamic_velocity_effective_reciprocal.z *
1282 (static_aabb.max().0.z - dynamic_aabb_previous.min().0.z)
1283 + t_margin_z
1284 )
1285 } else {
1286 debug_assert!(dynamic_velocity_effective.z < 0.0);
1287 ( dynamic_velocity_effective_reciprocal.z *
1288 (static_aabb.max().0.z - dynamic_aabb_previous.min().0.z)
1289 - t_margin_z,
1290 dynamic_velocity_effective_reciprocal.z *
1291 (static_aabb.min().0.z - dynamic_aabb_previous.max().0.z)
1292 + t_margin_z
1293 )
1294 };
1295
1296 if let Some ((interval_start, interval_end)) =
1297 if let Some ((interval_start_xy, interval_end_xy)) =
1298 if interval_start_x < interval_end_y &&
1299 interval_start_y < interval_end_x
1300 {
1301 Some ((
1302 f64::max (interval_start_x, interval_start_y),
1303 f64::min (interval_end_x, interval_end_y)
1304 ))
1305 } else {
1306 None
1307 }
1308 {
1309 if interval_start_xy < interval_end_z &&
1310 interval_start_z < interval_end_xy
1311 {
1312 Some ((
1313 f64::max (interval_start_xy, interval_start_z),
1314 f64::min (interval_end_xy, interval_end_z)
1315 ))
1316 } else {
1317 None
1318 }
1319 } else {
1320 None
1321 }
1322 {
1323 if interval_start < 1.0 && 0.0 < interval_end {
1324 let mid_toi_pair = (
1325 Normalized::clamp (f64::max (interval_start, last_toi)),
1326 Normalized::clamp (interval_end),
1327 object_pair
1328 );
1329 match self.pipeline.mid_toi_pairs
1330 .find_or_insert (Reverse (mid_toi_pair))
1331 {
1332 FindOrInsert::Inserted (_) => {}
1333 FindOrInsert::Found (_) => unreachable!()
1334 }
1335 }
1336 }
1337 }
1338 object::Kind::Dynamic => {
1342 let key_a = object_id_a.key();
1343 let key_b = object_id_b.key();
1344 let index_a = key_a.index();
1345 let index_b = key_b.index();
1346 match (
1347 self.persistent.get_group_key (object_id_a),
1348 self.persistent.get_group_key (object_id_b)
1349 ) {
1350 (Some (group_key_a), Some (group_key_b)) =>
1351 if group_key_a == group_key_b {
1352 let group = self.persistent.get_group (group_key_a).unwrap();
1353 for (pair, _) in group.contacts.iter() {
1354 if *pair == object_pair {
1355 continue 'outer
1356 }
1357 }
1358 }
1359 _ => {}
1360 }
1361 let object_a = &objects_dynamic[index_a];
1364 let object_b = &objects_dynamic[index_b];
1365 let velocity_a = object_a.derivatives.velocity;
1366 let velocity_b = object_b.derivatives.velocity;
1367 let pseudovelocity_a = self.pseudo_velocities[key_a.index()];
1368 let pseudovelocity_b = self.pseudo_velocities[key_b.index()];
1369 let velocity_effective_a = velocity_a + pseudovelocity_a;
1370 let velocity_effective_b = velocity_b + pseudovelocity_b;
1371 let velocity_effective_relative =
1372 velocity_effective_a - velocity_effective_b;
1373 let velocity_effective_relative_reciprocal =
1374 velocity_effective_relative.recip();
1375 let aabb_current_a = self.broad.get_aabb_dynamic_discrete (key_a);
1376 let aabb_current_b = self.broad.get_aabb_dynamic_discrete (key_b);
1377 let _aabb_swept_a = self.broad.get_aabb_dynamic_continuous (key_a);
1378 let _aabb_swept_b = self.broad.get_aabb_dynamic_continuous (key_b);
1379 let aabb_previous_a = Aabb3::with_minmax (
1380 aabb_current_a.min() - velocity_effective_a,
1381 aabb_current_a.max() - velocity_effective_a);
1382 let aabb_previous_b = Aabb3::with_minmax (
1383 aabb_current_b.min() - velocity_effective_b,
1384 aabb_current_b.max() - velocity_effective_b);
1385
1386 let overlap_interval_axis = |axis : Axis3| {
1388 let axis_index = axis as usize;
1389 let t_margin = (0.5 * CONTACT_DISTANCE *
1392 velocity_effective_relative_reciprocal[axis_index]).abs();
1393 let velocity_relative = velocity_effective_relative[axis_index];
1394 let velocity_relative_reciprocal =
1395 velocity_effective_relative_reciprocal[axis_index];
1396 let prev_a_min = aabb_previous_a.min().0[axis_index];
1397 let prev_a_max = aabb_previous_a.max().0[axis_index];
1398 let prev_b_min = aabb_previous_b.min().0[axis_index];
1399 let prev_b_max = aabb_previous_b.max().0[axis_index];
1400 if velocity_relative == 0.0 {
1401 geometry::Interval::with_minmax (
1405 std::f64::NEG_INFINITY, std::f64::INFINITY)
1406 } else if velocity_relative > 0.0 {
1407 geometry::Interval::with_minmax (
1408 (prev_b_min - prev_a_max) * velocity_relative_reciprocal -
1409 t_margin,
1410 (prev_b_max - prev_a_min) * velocity_relative_reciprocal +
1411 t_margin
1412 )
1413 } else {
1414 debug_assert!(velocity_relative < 0.0);
1415 geometry::Interval::with_minmax (
1416 (prev_b_max - prev_a_min) * velocity_relative_reciprocal -
1417 t_margin,
1418 (prev_b_min - prev_a_max) * velocity_relative_reciprocal +
1419 t_margin
1420 )
1421 }
1422 };
1423 let overlap_interval_x = overlap_interval_axis (Axis3::X);
1424 let overlap_interval_y = overlap_interval_axis (Axis3::Y);
1425 let overlap_interval_z = overlap_interval_axis (Axis3::Z);
1426
1427 if let Some (interval) = overlap_interval_x
1428 .intersection (overlap_interval_y).and_then (|overlap_interval_xy|
1429 overlap_interval_xy.intersection (overlap_interval_z))
1430 {
1431 if interval.min() < 1.0 && 0.0 < interval.max() {
1432 let mid_toi_pair = (
1433 Normalized::clamp (f64::max (interval.min(), last_toi)),
1434 Normalized::clamp (interval.max()),
1435 object_pair
1436 );
1437 match self.pipeline.mid_toi_pairs
1438 .find_or_insert (Reverse (mid_toi_pair))
1439 {
1440 FindOrInsert::Inserted (_) => {}
1441 FindOrInsert::Found (_) => unreachable!()
1442 }
1443 }
1444 }
1445 }
1446 _ => unreachable!()
1447 }
1448 }
1449
1450 log::trace!(mid_toi_pairs:?=self.pipeline.mid_toi_pairs; "mid TOI pairs");
1451
1452 self.pipeline.broad_overlap_pairs.clear();
1453 }
1454
1455 fn narrow_toi_contacts (&mut self,
1460 objects_static : &VecMap <object::Static>,
1461 objects_dynamic : &VecMap <object::Dynamic>
1462 ) {
1463 use sorted_vec::FindOrInsert;
1464
1465 let narrow_toi_contacts = &mut self.pipeline.narrow_toi_contacts;
1466 while let Some (mid_toi_pair) = self.pipeline.mid_toi_pairs.last().cloned() {
1467 let earliest_toi_contact = if !narrow_toi_contacts.is_empty() {
1468 narrow_toi_contacts[0].0.0
1469 } else {
1470 Normalized::clamp (1.0)
1471 };
1472
1473 if mid_toi_pair.0.0 < earliest_toi_contact {
1474 let (mid_toi_start, _mid_toi_end, object_pair) =
1475 mid_toi_pair.0.clone();
1476 let (object_id_a, object_id_b) = object_pair.into();
1477 let kind_a = object_id_a.kind();
1478 let kind_b = object_id_b.kind();
1479 match (kind_a, kind_b) {
1480 (object::Kind::Static, object::Kind::Dynamic) => {
1481 let key_static = object_id_a.key();
1482 let key_dynamic = object_id_b.key();
1483 let index_static = key_static.index();
1484 let index_dynamic = key_dynamic.index();
1485 let mut dynamic_object = objects_dynamic[index_dynamic].clone();
1487 let dynamic_velocity = dynamic_object.derivatives.velocity;
1488 let dynamic_pseudovelocity = self.pseudo_velocities[index_dynamic];
1489 let dynamic_velocity_effective =
1490 dynamic_velocity - dynamic_pseudovelocity;
1491 let static_object = objects_static[index_static].clone();
1492 let mut narrow_toi = *mid_toi_start;
1493 lerp_object (&mut dynamic_object, dynamic_pseudovelocity,
1496 -1.0 + narrow_toi);
1497 let mut t_remaining = 1.0 - narrow_toi;
1498 #[allow(unused_variables)]
1499 let mut iter = 0;
1500 loop {
1501 #[cfg(debug_assertions)]
1502 if self.narrow_toi_max_iter_count < iter {
1503 self.narrow_toi_max_iter_count = iter;
1504 }
1505 let proximity = Proximity::query (&static_object, &dynamic_object);
1506 if cfg!(debug_assertions) {
1507 if dynamic_object.collidable && static_object.collidable {
1508 debug_assert!(proximity.distance >= 0.0);
1509 }
1510 }
1511 let dynamic_velocity_effective_normal =
1512 dynamic_velocity_effective.dot (-*proximity.normal);
1513 if dynamic_velocity_effective_normal > 0.0 &&
1514 dynamic_object.collidable && static_object.collidable
1515 {
1516 log::trace!(
1518 t=narrow_toi, velocity=dynamic_velocity_effective_normal;
1519 "collision rejected, separating velocity");
1520 break
1521 } else if proximity.distance < CONTACT_DISTANCE {
1522 debug_assert!(dynamic_velocity_effective_normal <= 0.0 ||
1523 !dynamic_object.collidable || !static_object.collidable);
1524 log::trace!(t=narrow_toi, proximity:?; "collision detected");
1526 let contact = Contact { constraint: proximity.into() };
1527 let restitution = dynamic_object.material.restitution *
1528 static_object.material.restitution;
1529 let collision = contact::Colliding { contact, restitution };
1530 let narrow_toi_contact = Reverse ((
1531 Normalized::noisy (narrow_toi), object_pair, collision
1532 ));
1533 match narrow_toi_contacts.find_or_insert (narrow_toi_contact) {
1534 FindOrInsert::Inserted (_) => {}
1535 FindOrInsert::Found (_) => unreachable!()
1536 }
1537 break
1538 } else if dynamic_velocity_effective_normal == 0.0 {
1539 log::trace!(
1540 t=narrow_toi, velocity=dynamic_velocity_effective_normal;
1541 "collision rejected, zero relative velocity and objects not \
1542 in contact");
1543 break
1544 }
1545 let dynamic_velocity_effective_normal_reciprocal =
1546 1.0 / dynamic_velocity_effective_normal;
1547 let toi_axis = narrow_toi +
1548 (proximity.distance - 0.5 * CONTACT_DISTANCE) *
1549 (-dynamic_velocity_effective_normal_reciprocal);
1550 debug_assert!(toi_axis > narrow_toi ||
1551 !dynamic_object.collidable || !static_object.collidable);
1552 if toi_axis > 1.0 || toi_axis < 0.0 {
1553 log::trace!(t=narrow_toi, proximity:?;
1555 "collision rejected, final proximity");
1556 break
1557 }
1558 let t_advance = toi_axis - narrow_toi;
1559 lerp_object (&mut dynamic_object, dynamic_pseudovelocity, t_advance);
1560 narrow_toi = toi_axis;
1561 t_remaining -= t_advance;
1562 debug_assert!(t_remaining > 0.0);
1563 iter += 1;
1564 }
1565 }
1566
1567 (object::Kind::Dynamic, object::Kind::Dynamic) => {
1568 let key_a = object_id_a.key();
1569 let key_b = object_id_b.key();
1570 let index_a = key_a.index();
1571 let index_b = key_b.index();
1572 let mut object_a = objects_dynamic[index_a].clone();
1575 let mut object_b = objects_dynamic[index_b].clone();
1576 let pseudovelocity_a = self.pseudo_velocities[index_a];
1577 let pseudovelocity_b = self.pseudo_velocities[index_b];
1578 let velocity_a = object_a.derivatives.velocity;
1579 let velocity_b = object_b.derivatives.velocity;
1580 let velocity_effective_a = velocity_a + pseudovelocity_a;
1581 let velocity_effective_b = velocity_b + pseudovelocity_b;
1582 let velocity_effective_relative =
1583 velocity_effective_a - velocity_effective_b;
1584 let mut narrow_toi = *mid_toi_start;
1585 let mut t_remaining = 1.0 - narrow_toi;
1586 lerp_object (&mut object_a, pseudovelocity_a, -1.0 + narrow_toi);
1587 lerp_object (&mut object_b, pseudovelocity_b, -1.0 + narrow_toi);
1588 loop {
1589 debug_assert!(narrow_toi <= 1.0);
1590 debug_assert!(t_remaining >= 0.0);
1591 let proximity = Proximity::query (&object_a, &object_b);
1592 if cfg!(debug_assertions) {
1593 if object_a.collidable && object_b.collidable {
1594 debug_assert!(proximity.distance >= 0.0);
1595 }
1596 }
1597 let velocity_effective_relative_normal =
1598 velocity_effective_relative.dot (*proximity.normal);
1599 if velocity_effective_relative_normal > 0.0 &&
1600 object_a.collidable && object_b.collidable
1601 {
1602 log::trace!(
1604 t=narrow_toi, velocity=velocity_effective_relative_normal;
1605 "collision rejected, separating velocity");
1606 break
1607 } else if proximity.distance < CONTACT_DISTANCE {
1608 debug_assert!(velocity_effective_relative_normal <= 0.0 ||
1609 !object_a.collidable || !object_b.collidable);
1610 log::trace!(t=narrow_toi, proximity:?; "collision detected");
1612 let contact = Contact { constraint: proximity.into() };
1613 let restitution =
1614 object_a.material.restitution * object_b.material.restitution;
1615 let collision = contact::Colliding { contact, restitution };
1616 let narrow_toi_contact = Reverse ((
1617 Normalized::noisy (narrow_toi), object_pair, collision
1618 ));
1619 match narrow_toi_contacts.find_or_insert (narrow_toi_contact) {
1620 FindOrInsert::Inserted (_) => {}
1621 FindOrInsert::Found (_) => unreachable!()
1622 }
1623 break
1624 } else if velocity_effective_relative_normal == 0.0 {
1625 log::trace!(
1626 t=narrow_toi, velocity=velocity_effective_relative_normal;
1627 "collision rejected, zero relative velocity and objects not \
1628 in contact");
1629 break
1630 }
1631 let velocity_effective_relative_normal_reciprocal =
1632 1.0 / velocity_effective_relative_normal;
1633 let toi_axis = narrow_toi +
1634 (proximity.distance - 0.5 * CONTACT_DISTANCE) *
1635 (-velocity_effective_relative_normal_reciprocal);
1636 debug_assert!(toi_axis > narrow_toi ||
1637 !object_a.collidable || !object_b.collidable);
1638 if toi_axis > 1.0 || toi_axis < 0.0 {
1639 log::trace!(t=narrow_toi, proximity:?;
1641 "collision rejected, final proximity");
1642 break
1643 }
1644 let t_advance = toi_axis - narrow_toi;
1645 lerp_object (&mut object_a, pseudovelocity_a, t_advance);
1646 lerp_object (&mut object_b, pseudovelocity_b, t_advance);
1647 narrow_toi = toi_axis;
1648 t_remaining -= t_advance;
1649 }
1650 }
1651 _ => unreachable!()
1652 }
1653 self.pipeline.mid_toi_pairs.pop();
1654 } else { break }
1655 }
1656 #[cfg(debug_assertions)]
1657 log::debug!(max_iter_count=self.narrow_toi_max_iter_count;
1658 "narrow TOI max iters");
1659 log::trace!(contacts:?=narrow_toi_contacts; "narrow TOI contacts");
1660 }
1661
1662 #[inline]
1663 fn add_object_static (&mut self,
1664 object : &object::Static,
1665 object_key : object::Key,
1666 ) {
1667 self.broad.add_object_static (object.aabb_dilated(), object_key);
1668 }
1669
1670 #[inline]
1671 fn add_object_dynamic (&mut self,
1672 object : &object::Dynamic,
1673 object_key : object::Key
1674 ) {
1675 let aabb_discrete = object.aabb_dilated();
1676 let aabb_continuous = Aabb3::with_minmax (
1677 aabb_discrete.min() - object.derivatives.velocity,
1678 aabb_discrete.max() - object.derivatives.velocity);
1679 self.broad.add_object_dynamic (aabb_discrete, aabb_continuous, object_key);
1683 assert!(self.pseudo_velocities
1684 .insert (object_key.index(), Vector3::zero()).is_none());
1685 }
1686
1687}
1688
1689impl Pipeline {
1690 #[inline]
1691 pub fn is_empty (&self) -> bool {
1692 self.broad_overlap_pairs.is_empty() &&
1693 self.mid_toi_pairs.is_empty() &&
1694 self.narrow_toi_contacts.is_empty() &&
1695 self.resolved_collisions.is_empty() &&
1696 self.overlaps.is_empty()
1697 }
1698
1699 #[inline]
1711 pub fn remove_resolved_dynamic (&mut self, resolved : &SortedSet <InternalId>) {
1712 debug_assert!(self.broad_overlap_pairs.is_empty());
1713
1714 let (mut i, mut len);
1715
1716 i = 0;
1718 len = self.mid_toi_pairs.len();
1719 while i < len {
1720 let (_, _, object_pair) = self.mid_toi_pairs[i].clone().0;
1721 let (id_a, id_b) = object_pair.into();
1722 if id_a.kind() == object::Kind::Dynamic {
1723 if resolved.binary_search (&id_a).is_ok() {
1724 self.mid_toi_pairs.remove_index (i);
1725 len -= 1;
1726 continue
1727 }
1728 }
1729 debug_assert_eq!(id_b.kind(), object::Kind::Dynamic);
1730 if resolved.binary_search (&id_b).is_ok() {
1731 self.mid_toi_pairs.remove_index (i);
1732 len -= 1;
1733 continue
1734 }
1735 i += 1;
1736 }
1737
1738 i = 0;
1740 len = self.narrow_toi_contacts.len();
1741 while i < len {
1742 let (_, object_pair, _) = self.narrow_toi_contacts[i].clone().0;
1743 let (id_a, id_b) = object_pair.into();
1744 if id_a.kind() == object::Kind::Dynamic {
1745 if resolved.binary_search (&id_a).is_ok() {
1746 self.narrow_toi_contacts.remove_index (i);
1747 len -= 1;
1748 continue
1749 }
1750 }
1751 debug_assert_eq!(id_b.kind(), object::Kind::Dynamic);
1752 if resolved.binary_search (&id_b).is_ok() {
1753 self.narrow_toi_contacts.remove_index (i);
1754 len -= 1;
1755 continue
1756 }
1757 i += 1;
1758 }
1759 }
1760}
1761
1762impl ObjectPair {
1763 pub fn new (id_a : InternalId, id_b : InternalId) -> Self {
1768 debug_assert!(id_a.kind() == object::Kind::Dynamic ||
1769 id_b.kind() == object::Kind::Dynamic);
1770 if id_a < id_b {
1771 ObjectPair (id_a, id_b)
1772 } else {
1773 debug_assert!(id_a > id_b, "overlap ids should not be identical");
1774 ObjectPair (id_b, id_a)
1775 }
1776 }
1777}
1778
1779impl From <(InternalId, InternalId)> for ObjectPair {
1780 fn from ((id_a, id_b) : (InternalId, InternalId)) -> Self {
1781 ObjectPair::new (id_a, id_b)
1782 }
1783}
1784
1785impl InternalId {
1786 #[inline]
1787 pub fn new_static (key : object::Key) -> Self {
1788 debug_assert!(key.value() < OBJECT_KEY_MAX);
1789 InternalId (key.value())
1790 }
1791 #[inline]
1792 pub fn new_dynamic (key : object::Key) -> Self {
1793 debug_assert!(key.value() < OBJECT_KEY_MAX);
1794 InternalId (key.value() | INTERNAL_ID_DYNAMIC_BIT)
1795 }
1796 #[inline]
1797 pub fn kind (&self) -> object::Kind {
1798 match self.0 & INTERNAL_ID_DYNAMIC_BIT > 0 {
1799 true => object::Kind::Dynamic,
1800 false => object::Kind::Static
1801 }
1802 }
1803 #[inline]
1804 pub fn key (&self) -> object::Key {
1805 object::Key::from (self.0 & !INTERNAL_ID_DYNAMIC_BIT)
1806 }
1807}
1808impl From <InternalId> for object::Id {
1809 fn from (id : InternalId) -> Self {
1810 object::Id {
1811 kind: id.kind(),
1812 key: id.key()
1813 }
1814 }
1815}