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