1use std::collections::{HashMap, HashSet};
6
7use super::functions::{aabb3_overlaps, aabb3_point_dist_sq, axis_is_sorted};
8
9#[derive(Debug, Clone)]
11pub struct SapEndpoint {
12 pub value: f64,
14 pub object_id: u64,
16 pub is_min: bool,
18}
19pub struct StatTrackingSap {
21 pub inner: IncrementalSap,
23 pub stats: SapStats,
25}
26impl StatTrackingSap {
27 pub fn new() -> Self {
29 Self {
30 inner: IncrementalSap::new(),
31 stats: SapStats::default(),
32 }
33 }
34 pub fn insert(&mut self, id: u32, aabb: Aabb3) {
36 self.inner.insert(id, aabb);
37 }
38 pub fn remove(&mut self, id: u32) {
40 self.inner.remove(id);
41 }
42 pub fn update(&mut self, id: u32, aabb: Aabb3) {
44 self.inner.update(id, aabb);
45 }
46 pub fn query_pairs(&mut self) -> Vec<(u32, u32)> {
48 let n_endpoints = self.inner.endpoints_x.len();
49 let pairs = self.inner.query_pairs();
50 self.stats = SapStats {
51 pair_count: pairs.len(),
52 sweep_count: n_endpoints,
53 body_count: self.inner.body_count(),
54 };
55 pairs
56 }
57}
58#[derive(Debug, Clone)]
60pub struct SapObject {
61 pub id: u64,
63 pub min: [f64; 3],
65 pub max: [f64; 3],
67}
68#[derive(Debug, Clone)]
70pub struct BroadphaseResult {
71 pub pairs: Vec<(u32, u32)>,
73 pub new_pairs: Vec<(u32, u32)>,
75 pub lost_pairs: Vec<(u32, u32)>,
77 pub stats: SapStats,
79}
80#[derive(Debug, Clone)]
82pub struct SapEndpointU32 {
83 pub value: f64,
85 pub body_id: u32,
87 pub is_min: bool,
89}
90pub struct GridBroadphase {
92 pub cell_size: f64,
94 pub cells: HashMap<(i32, i32, i32), Vec<u64>>,
96}
97impl GridBroadphase {
98 pub fn new(cell_size: f64) -> Self {
100 Self {
101 cell_size,
102 cells: HashMap::new(),
103 }
104 }
105 pub fn insert(&mut self, id: u64, min: [f64; 3], max: [f64; 3]) {
107 let min_cx = self.cell_coord(min[0]);
108 let min_cy = self.cell_coord(min[1]);
109 let min_cz = self.cell_coord(min[2]);
110 let max_cx = self.cell_coord(max[0]);
111 let max_cy = self.cell_coord(max[1]);
112 let max_cz = self.cell_coord(max[2]);
113 for cx in min_cx..=max_cx {
114 for cy in min_cy..=max_cy {
115 for cz in min_cz..=max_cz {
116 self.cells.entry((cx, cy, cz)).or_default().push(id);
117 }
118 }
119 }
120 }
121 #[inline]
123 pub fn cell_coord(&self, pos: f64) -> i32 {
124 (pos / self.cell_size).floor() as i32
125 }
126 pub fn query_potential_pairs(&self) -> Vec<(u64, u64)> {
128 let mut pairs: Vec<(u64, u64)> = Vec::new();
129 for ids in self.cells.values() {
130 for i in 0..ids.len() {
131 for j in (i + 1)..ids.len() {
132 let (lo, hi) = if ids[i] < ids[j] {
133 (ids[i], ids[j])
134 } else {
135 (ids[j], ids[i])
136 };
137 pairs.push((lo, hi));
138 }
139 }
140 }
141 pairs.sort_unstable();
142 pairs.dedup();
143 pairs
144 }
145 pub fn clear(&mut self) {
147 self.cells.clear();
148 }
149}
150impl GridBroadphase {
151 pub fn query_point(&self, p: [f64; 3]) -> Vec<u64> {
153 let key = (
154 self.cell_coord(p[0]),
155 self.cell_coord(p[1]),
156 self.cell_coord(p[2]),
157 );
158 self.cells.get(&key).cloned().unwrap_or_default()
159 }
160 pub fn total_entries(&self) -> usize {
162 self.cells.values().map(|v| v.len()).sum()
163 }
164 pub fn occupied_cells(&self) -> usize {
166 self.cells.len()
167 }
168 pub fn remove(&mut self, id: u64) {
173 for ids in self.cells.values_mut() {
174 ids.retain(|&x| x != id);
175 }
176 self.cells.retain(|_, v| !v.is_empty());
177 }
178 pub fn query_aabb(&self, min: [f64; 3], max: [f64; 3]) -> Vec<u64> {
181 let min_cx = self.cell_coord(min[0]);
182 let min_cy = self.cell_coord(min[1]);
183 let min_cz = self.cell_coord(min[2]);
184 let max_cx = self.cell_coord(max[0]);
185 let max_cy = self.cell_coord(max[1]);
186 let max_cz = self.cell_coord(max[2]);
187 let mut result = Vec::new();
188 for cx in min_cx..=max_cx {
189 for cy in min_cy..=max_cy {
190 for cz in min_cz..=max_cz {
191 if let Some(ids) = self.cells.get(&(cx, cy, cz)) {
192 for &id in ids {
193 if !result.contains(&id) {
194 result.push(id);
195 }
196 }
197 }
198 }
199 }
200 }
201 result.sort_unstable();
202 result
203 }
204}
205#[derive(Debug, Clone, Default)]
210pub struct SapAxis {
211 pub endpoints: Vec<SapEndpointU32>,
213}
214impl SapAxis {
215 pub fn new() -> Self {
217 Self {
218 endpoints: Vec::new(),
219 }
220 }
221 pub fn insert(&mut self, body_id: u32, min_val: f64, max_val: f64) {
223 self.endpoints.push(SapEndpointU32 {
224 value: min_val,
225 body_id,
226 is_min: true,
227 });
228 self.endpoints.push(SapEndpointU32 {
229 value: max_val,
230 body_id,
231 is_min: false,
232 });
233 let n = self.endpoints.len();
234 for start in [n - 2, n - 1] {
235 let mut i = start;
236 while i > 0 && self.endpoints[i - 1].value > self.endpoints[i].value {
237 self.endpoints.swap(i - 1, i);
238 i -= 1;
239 }
240 }
241 }
242 pub fn remove(&mut self, body_id: u32) {
244 self.endpoints.retain(|e| e.body_id != body_id);
245 }
246 pub fn update(&mut self, body_id: u32, min_val: f64, max_val: f64) {
248 for ep in self.endpoints.iter_mut() {
249 if ep.body_id == body_id {
250 ep.value = if ep.is_min { min_val } else { max_val };
251 }
252 }
253 let n = self.endpoints.len();
254 for i in 1..n {
255 let mut j = i;
256 while j > 0 && self.endpoints[j - 1].value > self.endpoints[j].value {
257 self.endpoints.swap(j - 1, j);
258 j -= 1;
259 }
260 }
261 }
262 pub fn overlapping_pairs(&self) -> HashSet<(u32, u32)> {
264 let mut pairs = HashSet::new();
265 let mut active: Vec<u32> = Vec::new();
266 for ep in &self.endpoints {
267 if ep.is_min {
268 for &aid in &active {
269 let key = if ep.body_id < aid {
270 (ep.body_id, aid)
271 } else {
272 (aid, ep.body_id)
273 };
274 pairs.insert(key);
275 }
276 active.push(ep.body_id);
277 } else {
278 active.retain(|&id| id != ep.body_id);
279 }
280 }
281 pairs
282 }
283}
284impl SapAxis {
285 pub fn is_sorted(&self) -> bool {
287 axis_is_sorted(&self.endpoints)
288 }
289 pub fn body_count(&self) -> usize {
291 self.endpoints.iter().filter(|e| e.is_min).count()
292 }
293 pub fn min_value(&self) -> Option<f64> {
295 self.endpoints.first().map(|e| e.value)
296 }
297 pub fn max_value(&self) -> Option<f64> {
299 self.endpoints.last().map(|e| e.value)
300 }
301 pub fn tracked_bodies(&self) -> Vec<u32> {
303 let mut ids: Vec<u32> = self
304 .endpoints
305 .iter()
306 .filter(|e| e.is_min)
307 .map(|e| e.body_id)
308 .collect();
309 ids.sort_unstable();
310 ids.dedup();
311 ids
312 }
313}
314#[derive(Debug, Clone)]
316pub struct SapSnapshot {
317 pub(super) aabbs: HashMap<u32, Aabb3>,
318}
319impl SapSnapshot {
320 pub fn capture(sap: &IncrementalSap) -> Self {
322 Self {
323 aabbs: sap.aabbs.clone(),
324 }
325 }
326 pub fn restore(self, sap: &mut IncrementalSap) {
331 let current_ids: Vec<u32> = sap.aabbs.keys().copied().collect();
332 for id in ¤t_ids {
333 if !self.aabbs.contains_key(id) {
334 sap.remove(*id);
335 }
336 }
337 for (id, aabb) in self.aabbs {
338 if sap.aabbs.contains_key(&id) {
339 sap.update(id, aabb);
340 } else {
341 sap.insert(id, aabb);
342 }
343 }
344 }
345}
346#[derive(Debug, Clone, PartialEq, Eq)]
348pub enum OverlapEvent {
349 Begin(u32, u32),
351 End(u32, u32),
353}
354#[derive(Debug, Clone)]
356pub struct Aabb3 {
357 pub min: [f64; 3],
359 pub max: [f64; 3],
361}
362#[derive(Debug, Clone, Default)]
364pub struct SapStats {
365 pub pair_count: usize,
367 pub sweep_count: usize,
369 pub body_count: usize,
371}
372pub struct EventDrivenSap {
377 pub(super) inner: IncrementalSap,
378 pub(super) prev_pairs: HashSet<(u32, u32)>,
380}
381impl EventDrivenSap {
382 pub fn new() -> Self {
384 Self {
385 inner: IncrementalSap::new(),
386 prev_pairs: HashSet::new(),
387 }
388 }
389 pub fn insert(&mut self, id: u32, aabb: Aabb3) {
391 self.inner.insert(id, aabb);
392 }
393 pub fn remove(&mut self, id: u32) {
396 self.inner.remove(id);
397 }
398 pub fn update(&mut self, id: u32, aabb: Aabb3) {
400 self.inner.update(id, aabb);
401 }
402 pub fn step_pairs(&mut self) -> (Vec<OverlapEvent>, Vec<(u32, u32)>) {
407 let current_vec = self.inner.query_pairs();
408 let current: HashSet<(u32, u32)> = current_vec.iter().copied().collect();
409 let mut events = Vec::new();
410 for &pair in ¤t {
411 if !self.prev_pairs.contains(&pair) {
412 events.push(OverlapEvent::Begin(pair.0, pair.1));
413 }
414 }
415 for &pair in &self.prev_pairs {
416 if !current.contains(&pair) {
417 events.push(OverlapEvent::End(pair.0, pair.1));
418 }
419 }
420 self.prev_pairs = current;
421 events.sort_by_key(|e| match e {
422 OverlapEvent::Begin(a, b) | OverlapEvent::End(a, b) => (*a, *b),
423 });
424 (events, current_vec)
425 }
426 pub fn body_count(&self) -> usize {
428 self.inner.body_count()
429 }
430}
431pub struct SweepAndPrune {
433 pub objects: Vec<SapObject>,
435 pub sorted_x: Vec<SapEndpoint>,
437}
438impl SweepAndPrune {
439 pub fn new() -> Self {
441 Self {
442 objects: Vec::new(),
443 sorted_x: Vec::new(),
444 }
445 }
446 pub fn add_object(&mut self, id: u64, min: [f64; 3], max: [f64; 3]) {
448 self.objects.push(SapObject { id, min, max });
449 self.sorted_x.push(SapEndpoint {
450 value: min[0],
451 object_id: id,
452 is_min: true,
453 });
454 self.sorted_x.push(SapEndpoint {
455 value: max[0],
456 object_id: id,
457 is_min: false,
458 });
459 self.sort_axis();
460 }
461 pub fn remove_object(&mut self, id: u64) {
463 self.objects.retain(|o| o.id != id);
464 self.sorted_x.retain(|e| e.object_id != id);
465 }
466 pub fn update_object(&mut self, id: u64, min: [f64; 3], max: [f64; 3]) {
468 if let Some(obj) = self.objects.iter_mut().find(|o| o.id == id) {
469 obj.min = min;
470 obj.max = max;
471 }
472 for ep in self.sorted_x.iter_mut().filter(|e| e.object_id == id) {
473 ep.value = if ep.is_min { min[0] } else { max[0] };
474 }
475 self.sort_axis();
476 }
477 pub fn sort_axis(&mut self) {
479 self.sorted_x.sort_by(|a, b| {
480 a.value
481 .partial_cmp(&b.value)
482 .unwrap_or(std::cmp::Ordering::Equal)
483 });
484 }
485 pub fn query_overlapping_pairs(&mut self) -> Vec<(u64, u64)> {
491 self.sort_axis();
492 let obj_map: HashMap<u64, &SapObject> = self.objects.iter().map(|o| (o.id, o)).collect();
493 let mut pairs: Vec<(u64, u64)> = Vec::new();
494 let mut active: Vec<u64> = Vec::new();
495 for ep in &self.sorted_x {
496 if ep.is_min {
497 if let Some(obj_a) = obj_map.get(&ep.object_id) {
498 for &active_id in &active {
499 if let Some(obj_b) = obj_map.get(&active_id)
500 && Self::overlaps_on_axis(
501 obj_a.min[1],
502 obj_a.max[1],
503 obj_b.min[1],
504 obj_b.max[1],
505 )
506 && Self::overlaps_on_axis(
507 obj_a.min[2],
508 obj_a.max[2],
509 obj_b.min[2],
510 obj_b.max[2],
511 )
512 {
513 let (lo, hi) = if ep.object_id < active_id {
514 (ep.object_id, active_id)
515 } else {
516 (active_id, ep.object_id)
517 };
518 pairs.push((lo, hi));
519 }
520 }
521 }
522 active.push(ep.object_id);
523 } else {
524 active.retain(|&id| id != ep.object_id);
525 }
526 }
527 pairs.sort_unstable();
528 pairs.dedup();
529 pairs
530 }
531 #[inline]
533 pub fn overlaps_on_axis(min_a: f64, max_a: f64, min_b: f64, max_b: f64) -> bool {
534 min_a <= max_b && min_b <= max_a
535 }
536 pub fn object_count(&self) -> usize {
538 self.objects.len()
539 }
540}
541impl SweepAndPrune {
542 pub fn add_object_batch(&mut self, objects: &[(u64, [f64; 3], [f64; 3])]) {
547 for &(id, min, max) in objects {
548 self.objects.push(SapObject { id, min, max });
549 self.sorted_x.push(SapEndpoint {
550 value: min[0],
551 object_id: id,
552 is_min: true,
553 });
554 self.sorted_x.push(SapEndpoint {
555 value: max[0],
556 object_id: id,
557 is_min: false,
558 });
559 }
560 self.sort_axis();
561 }
562 pub fn compute_axis_variance(&self) -> [f64; 3] {
568 let n = self.objects.len();
569 if n == 0 {
570 return [0.0; 3];
571 }
572 let mut sum = [0.0_f64; 3];
573 let mut sum_sq = [0.0_f64; 3];
574 for obj in &self.objects {
575 for ax in 0..3 {
576 let c = (obj.min[ax] + obj.max[ax]) * 0.5;
577 sum[ax] += c;
578 sum_sq[ax] += c * c;
579 }
580 }
581 let nf = n as f64;
582 let mut var = [0.0_f64; 3];
583 for ax in 0..3 {
584 let mean = sum[ax] / nf;
585 var[ax] = (sum_sq[ax] / nf) - mean * mean;
586 }
587 var
588 }
589 pub fn reorder_axes(&mut self) -> usize {
596 let var = self.compute_axis_variance();
597 let best_axis = if var[0] >= var[1] && var[0] >= var[2] {
598 0
599 } else if var[1] >= var[2] {
600 1
601 } else {
602 2
603 };
604 self.sorted_x.clear();
605 for obj in &self.objects {
606 self.sorted_x.push(SapEndpoint {
607 value: obj.min[best_axis],
608 object_id: obj.id,
609 is_min: true,
610 });
611 self.sorted_x.push(SapEndpoint {
612 value: obj.max[best_axis],
613 object_id: obj.id,
614 is_min: false,
615 });
616 }
617 self.sort_axis();
618 best_axis
619 }
620}
621pub struct IncrementalSap {
626 pub endpoints_x: Vec<SapEndpointU32>,
628 pub endpoints_y: Vec<SapEndpointU32>,
630 pub endpoints_z: Vec<SapEndpointU32>,
632 pub aabbs: HashMap<u32, Aabb3>,
634 pub active_pairs: HashSet<(u32, u32)>,
636}
637impl IncrementalSap {
638 pub fn new() -> Self {
640 Self {
641 endpoints_x: Vec::new(),
642 endpoints_y: Vec::new(),
643 endpoints_z: Vec::new(),
644 aabbs: HashMap::new(),
645 active_pairs: HashSet::new(),
646 }
647 }
648 pub fn insert(&mut self, body_id: u32, aabb: Aabb3) {
650 self.endpoints_x.push(SapEndpointU32 {
651 value: aabb.min[0],
652 body_id,
653 is_min: true,
654 });
655 self.endpoints_x.push(SapEndpointU32 {
656 value: aabb.max[0],
657 body_id,
658 is_min: false,
659 });
660 self.endpoints_y.push(SapEndpointU32 {
661 value: aabb.min[1],
662 body_id,
663 is_min: true,
664 });
665 self.endpoints_y.push(SapEndpointU32 {
666 value: aabb.max[1],
667 body_id,
668 is_min: false,
669 });
670 self.endpoints_z.push(SapEndpointU32 {
671 value: aabb.min[2],
672 body_id,
673 is_min: true,
674 });
675 self.endpoints_z.push(SapEndpointU32 {
676 value: aabb.max[2],
677 body_id,
678 is_min: false,
679 });
680 self.aabbs.insert(body_id, aabb);
681 }
682 pub fn remove(&mut self, body_id: u32) {
684 self.endpoints_x.retain(|e| e.body_id != body_id);
685 self.endpoints_y.retain(|e| e.body_id != body_id);
686 self.endpoints_z.retain(|e| e.body_id != body_id);
687 self.aabbs.remove(&body_id);
688 self.active_pairs
689 .retain(|&(a, b)| a != body_id && b != body_id);
690 }
691 pub fn update(&mut self, body_id: u32, new_aabb: Aabb3) {
693 for ep in self.endpoints_x.iter_mut().filter(|e| e.body_id == body_id) {
694 ep.value = if ep.is_min {
695 new_aabb.min[0]
696 } else {
697 new_aabb.max[0]
698 };
699 }
700 for ep in self.endpoints_y.iter_mut().filter(|e| e.body_id == body_id) {
701 ep.value = if ep.is_min {
702 new_aabb.min[1]
703 } else {
704 new_aabb.max[1]
705 };
706 }
707 for ep in self.endpoints_z.iter_mut().filter(|e| e.body_id == body_id) {
708 ep.value = if ep.is_min {
709 new_aabb.min[2]
710 } else {
711 new_aabb.max[2]
712 };
713 }
714 self.aabbs.insert(body_id, new_aabb);
715 }
716 pub fn batch_update(&mut self, updates: &[(u32, Aabb3)]) {
718 for (body_id, new_aabb) in updates {
719 for ep in self
720 .endpoints_x
721 .iter_mut()
722 .filter(|e| e.body_id == *body_id)
723 {
724 ep.value = if ep.is_min {
725 new_aabb.min[0]
726 } else {
727 new_aabb.max[0]
728 };
729 }
730 for ep in self
731 .endpoints_y
732 .iter_mut()
733 .filter(|e| e.body_id == *body_id)
734 {
735 ep.value = if ep.is_min {
736 new_aabb.min[1]
737 } else {
738 new_aabb.max[1]
739 };
740 }
741 for ep in self
742 .endpoints_z
743 .iter_mut()
744 .filter(|e| e.body_id == *body_id)
745 {
746 ep.value = if ep.is_min {
747 new_aabb.min[2]
748 } else {
749 new_aabb.max[2]
750 };
751 }
752 self.aabbs.insert(*body_id, new_aabb.clone());
753 }
754 }
755 pub fn query_pairs(&mut self) -> Vec<(u32, u32)> {
757 let pairs_x = Self::sort_and_sweep_axis(&mut self.endpoints_x);
758 let pairs_y = Self::sort_and_sweep_axis(&mut self.endpoints_y);
759 let pairs_z = Self::sort_and_sweep_axis(&mut self.endpoints_z);
760 let result: HashSet<(u32, u32)> = pairs_x
761 .intersection(&pairs_y)
762 .copied()
763 .collect::<HashSet<_>>()
764 .intersection(&pairs_z)
765 .copied()
766 .collect();
767 self.active_pairs = result.clone();
768 let mut pairs: Vec<(u32, u32)> = result.into_iter().collect();
769 pairs.sort_unstable();
770 pairs
771 }
772 pub fn sort_and_sweep_axis(endpoints: &mut [SapEndpointU32]) -> HashSet<(u32, u32)> {
774 endpoints.sort_by(|a, b| {
775 a.value
776 .partial_cmp(&b.value)
777 .unwrap_or(std::cmp::Ordering::Equal)
778 });
779 let mut pairs = HashSet::new();
780 let mut active: Vec<u32> = Vec::new();
781 for ep in endpoints.iter() {
782 if ep.is_min {
783 for &aid in &active {
784 let (lo, hi) = if ep.body_id < aid {
785 (ep.body_id, aid)
786 } else {
787 (aid, ep.body_id)
788 };
789 pairs.insert((lo, hi));
790 }
791 active.push(ep.body_id);
792 } else {
793 active.retain(|&id| id != ep.body_id);
794 }
795 }
796 pairs
797 }
798 pub fn body_count(&self) -> usize {
800 self.aabbs.len()
801 }
802 pub fn current_pairs(&self) -> &HashSet<(u32, u32)> {
804 &self.active_pairs
805 }
806 pub fn insert_aabb(&mut self, id: u32, min: [f64; 3], max: [f64; 3]) {
808 self.insert(id, Aabb3 { min, max });
809 self.query_pairs();
810 }
811 pub fn remove_aabb(&mut self, id: u32) {
813 self.remove(id);
814 self.active_pairs.retain(|&(a, b)| a != id && b != id);
815 }
816 pub fn update_aabb(&mut self, id: u32, min: [f64; 3], max: [f64; 3]) {
818 self.update(id, Aabb3 { min, max });
819 self.query_pairs();
820 }
821 pub fn active_pairs(&self) -> &HashSet<(u32, u32)> {
823 &self.active_pairs
824 }
825 pub fn bipartite_pairs(&self, set_a: &[u32], set_b: &[u32]) -> Vec<(u32, u32)> {
829 let set_a_hs: HashSet<u32> = set_a.iter().copied().collect();
830 let set_b_hs: HashSet<u32> = set_b.iter().copied().collect();
831 let mut temp = IncrementalSap::new();
832 for &id in set_a.iter().chain(set_b.iter()) {
833 if let Some(aabb) = self.aabbs.get(&id) {
834 temp.insert(id, aabb.clone());
835 }
836 }
837 let all_pairs = temp.query_pairs();
838 all_pairs
839 .into_iter()
840 .filter(|&(a, b)| {
841 (set_a_hs.contains(&a) && set_b_hs.contains(&b))
842 || (set_a_hs.contains(&b) && set_b_hs.contains(&a))
843 })
844 .collect()
845 }
846}
847impl IncrementalSap {
848 pub fn compute_axis_variance(&self) -> [f64; 3] {
852 let n = self.aabbs.len();
853 if n == 0 {
854 return [0.0; 3];
855 }
856 let mut sum = [0.0_f64; 3];
857 let mut sum_sq = [0.0_f64; 3];
858 for aabb in self.aabbs.values() {
859 for ax in 0..3 {
860 let c = (aabb.min[ax] + aabb.max[ax]) * 0.5;
861 sum[ax] += c;
862 sum_sq[ax] += c * c;
863 }
864 }
865 let nf = n as f64;
866 let mut var = [0.0_f64; 3];
867 for ax in 0..3 {
868 let mean = sum[ax] / nf;
869 var[ax] = (sum_sq[ax] / nf) - mean * mean;
870 }
871 var
872 }
873 pub fn reorder_axes(&mut self) -> usize {
878 let var = self.compute_axis_variance();
879 let best = if var[0] >= var[1] && var[0] >= var[2] {
880 0
881 } else if var[1] >= var[2] {
882 1
883 } else {
884 2
885 };
886 self.endpoints_x.clear();
887 for (id, aabb) in &self.aabbs {
888 self.endpoints_x.push(SapEndpointU32 {
889 value: aabb.min[best],
890 body_id: *id,
891 is_min: true,
892 });
893 self.endpoints_x.push(SapEndpointU32 {
894 value: aabb.max[best],
895 body_id: *id,
896 is_min: false,
897 });
898 }
899 self.endpoints_x.sort_by(|a, b| {
900 a.value
901 .partial_cmp(&b.value)
902 .unwrap_or(std::cmp::Ordering::Equal)
903 });
904 best
905 }
906}
907impl IncrementalSap {
908 pub fn any_overlap(&self, aabb: &Aabb3) -> bool {
910 for stored in self.aabbs.values() {
911 if aabb3_overlaps(stored, aabb) {
912 return true;
913 }
914 }
915 false
916 }
917 pub fn query_aabb(&self, aabb: &Aabb3) -> Vec<u32> {
919 self.aabbs
920 .iter()
921 .filter_map(|(&id, stored)| {
922 if aabb3_overlaps(stored, aabb) {
923 Some(id)
924 } else {
925 None
926 }
927 })
928 .collect()
929 }
930 pub fn query_sphere_sq(&self, p: [f64; 3], radius_sq: f64) -> Vec<u32> {
932 self.aabbs
933 .iter()
934 .filter_map(|(&id, aabb)| {
935 if aabb3_point_dist_sq(aabb, p) <= radius_sq {
936 Some(id)
937 } else {
938 None
939 }
940 })
941 .collect()
942 }
943 pub fn clear(&mut self) {
945 self.endpoints_x.clear();
946 self.endpoints_y.clear();
947 self.endpoints_z.clear();
948 self.aabbs.clear();
949 self.active_pairs.clear();
950 }
951 pub fn get_aabb(&self, id: u32) -> Option<&Aabb3> {
953 self.aabbs.get(&id)
954 }
955 pub fn body_ids(&self) -> impl Iterator<Item = u32> + '_ {
957 self.aabbs.keys().copied()
958 }
959 pub fn merge_from(&mut self, other: &IncrementalSap) {
963 for (&id, aabb) in &other.aabbs {
964 if self.aabbs.contains_key(&id) {
965 self.update(id, aabb.clone());
966 } else {
967 self.insert(id, aabb.clone());
968 }
969 }
970 }
971 pub fn contains(&self, id: u32) -> bool {
973 self.aabbs.contains_key(&id)
974 }
975}
976pub struct MultiPhaseSap {
978 pub(super) event_sap: EventDrivenSap,
979 pub(super) stat_sap: StatTrackingSap,
980}
981impl MultiPhaseSap {
982 pub fn new() -> Self {
984 Self {
985 event_sap: EventDrivenSap::new(),
986 stat_sap: StatTrackingSap::new(),
987 }
988 }
989 pub fn insert(&mut self, id: u32, aabb: Aabb3) {
991 self.event_sap.insert(id, aabb.clone());
992 self.stat_sap.insert(id, aabb);
993 }
994 pub fn remove(&mut self, id: u32) {
996 self.event_sap.remove(id);
997 self.stat_sap.remove(id);
998 }
999 pub fn update(&mut self, id: u32, aabb: Aabb3) {
1001 self.event_sap.update(id, aabb.clone());
1002 self.stat_sap.update(id, aabb);
1003 }
1004 pub fn step(&mut self) -> BroadphaseResult {
1006 let pairs = self.stat_sap.query_pairs();
1007 let stats = self.stat_sap.stats.clone();
1008 let (events, _) = self.event_sap.step_pairs();
1009 let mut new_pairs = Vec::new();
1010 let mut lost_pairs = Vec::new();
1011 for ev in events {
1012 match ev {
1013 OverlapEvent::Begin(a, b) => new_pairs.push((a, b)),
1014 OverlapEvent::End(a, b) => lost_pairs.push((a, b)),
1015 }
1016 }
1017 BroadphaseResult {
1018 pairs,
1019 new_pairs,
1020 lost_pairs,
1021 stats,
1022 }
1023 }
1024}