use std::mem;
use super::{BroadphasePair, BroadphaseProxy};
use crate::bullet::{
collision::{
dispatch::collision_dispatcher::CollisionDispatcher,
narrowphase::persistent_manifold::ContactAddedCallback,
},
dynamics::rigid_body::RigidBody,
};
pub struct OverlappingPairCache {
overlapping_pair_array: Vec<BroadphasePair>,
seen_gens: Vec<u32>,
cur_gen: u32,
}
impl Default for OverlappingPairCache {
fn default() -> Self {
Self {
overlapping_pair_array: Vec::with_capacity(32),
seen_gens: Vec::new(),
cur_gen: 1,
}
}
}
impl OverlappingPairCache {
pub fn add_overlapping_pair(
&mut self,
proxy0: &BroadphaseProxy,
proxy0_idx: usize,
proxy1: &BroadphaseProxy,
proxy1_idx: usize,
) {
if !Self::needs_broadphase_collision(proxy0, proxy1) {
return;
}
let (mut proxy0_id, mut proxy0_idx) = (proxy0.unique_id, proxy0_idx);
let (mut proxy1_id, mut proxy1_idx) = (proxy1.unique_id, proxy1_idx);
if proxy0_id > proxy1_id {
mem::swap(&mut proxy0_id, &mut proxy1_id);
mem::swap(&mut proxy0_idx, &mut proxy1_idx);
}
let (lo, hi) = (proxy0_id as usize, proxy1_id as usize);
debug_assert!(lo <= hi);
let table_idx = hi * (hi + 1) / 2 + lo;
if table_idx >= self.seen_gens.len() {
let needed = (hi + 1).checked_mul(hi + 2).expect("pair table overflow") / 2;
self.seen_gens.resize(needed, 0);
}
debug_assert!(table_idx < self.seen_gens.len());
if self.seen_gens[table_idx] == self.cur_gen {
return;
}
self.seen_gens[table_idx] = self.cur_gen;
self.overlapping_pair_array.push(BroadphasePair {
proxy0: proxy0_idx,
proxy1: proxy1_idx,
});
}
#[inline]
pub fn is_empty(&self) -> bool {
self.overlapping_pair_array.is_empty()
}
#[inline]
pub fn finish_direct_dispatch(&mut self) {
debug_assert!(self.overlapping_pair_array.is_empty());
self.cur_gen = self.cur_gen.wrapping_add(1);
if self.cur_gen == 0 {
self.seen_gens.fill(0);
self.cur_gen = 1;
}
}
#[inline]
pub const fn needs_broadphase_collision(
proxy0: &BroadphaseProxy,
proxy1: &BroadphaseProxy,
) -> bool {
(proxy0.collision_filter_group & proxy1.collision_filter_mask) != 0
&& (proxy1.collision_filter_group & proxy0.collision_filter_mask) != 0
}
pub fn process_all_overlapping_pairs<T: ContactAddedCallback>(
&mut self,
collision_objs: &[RigidBody],
dispatcher: &mut CollisionDispatcher,
handles: &[BroadphaseProxy],
contact_added_callback: &mut T,
) {
for pair in &self.overlapping_pair_array {
dispatcher.near_callback(
collision_objs,
&handles[pair.proxy0],
&handles[pair.proxy1],
contact_added_callback,
);
}
self.overlapping_pair_array.clear();
self.cur_gen = self.cur_gen.wrapping_add(1);
if self.cur_gen == 0 {
self.seen_gens.fill(0);
self.cur_gen = 1;
}
}
}