mod overlap;
pub(super) mod swept;
mod track;
use alloc::vec::Vec;
use concinnity_memory::Pool;
use crate::SensorCrossing;
use super::body::Body;
use super::broadphase::Pair;
use super::world::{body_at, handle_at};
use track::Overlap;
pub(crate) struct Sensors {
overlaps: Vec<Overlap>,
previous: Vec<Overlap>,
crossings: Vec<SensorCrossing>,
overflows: u32,
}
impl Sensors {
pub(crate) fn with_capacity(capacity: usize) -> Self {
Sensors {
overlaps: Vec::with_capacity(capacity),
previous: Vec::with_capacity(capacity),
crossings: Vec::with_capacity(capacity),
overflows: 0,
}
}
pub(crate) fn resolve(&mut self, bodies: &Pool<Body>, pairs: &[Pair]) {
core::mem::swap(&mut self.overlaps, &mut self.previous);
self.overlaps.clear();
let Sensors {
overlaps,
previous,
crossings,
overflows,
} = self;
for &pair in pairs {
let (Some(a), Some(b)) = (
bodies.get_at(pair.0 as usize),
bodies.get_at(pair.1 as usize),
) else {
continue;
};
if !overlap::overlapping(a, b) {
continue;
}
let (Some(a), Some(b)) = (handle_at(bodies, pair.0), handle_at(bodies, pair.1)) else {
continue;
};
if overlaps.len() == overlaps.capacity() {
*overflows = overflows.saturating_add(1);
continue;
}
overlaps.push(Overlap { pair, a, b });
}
track::transitions(previous, overlaps, |crossed, entered| {
for (sensor, other) in [(crossed.a, crossed.b), (crossed.b, crossed.a)] {
let Some(tag) = body_at(bodies, sensor).and_then(Body::sensor_tag) else {
continue;
};
let crossing = SensorCrossing {
tag,
other: body_at(bodies, other).map(|_| other),
entered,
};
if crossings.len() == crossings.capacity() {
*overflows = overflows.saturating_add(1);
continue;
}
crossings.push(crossing);
}
});
}
pub(crate) fn record_pass_through(&mut self, bodies: &Pool<Body>, mover: u32, region: u32) {
let (Some(tag), Some(other)) = (
bodies.get_at(region as usize).and_then(Body::sensor_tag),
handle_at(bodies, mover),
) else {
return;
};
for entered in [true, false] {
if self.crossings.len() == self.crossings.capacity() {
self.overflows = self.overflows.saturating_add(1);
continue;
}
self.crossings.push(SensorCrossing {
tag,
other: Some(other),
entered,
});
}
}
pub(crate) fn drain_into(&mut self, out: &mut Vec<SensorCrossing>) {
out.clear();
out.append(&mut self.crossings);
}
#[cfg(test)]
pub(crate) fn overflows(&self) -> u32 {
self.overflows
}
#[cfg(test)]
pub(crate) fn clear_overflows(&mut self) {
self.overflows = 0;
}
#[cfg(test)]
pub(crate) fn overlap_count(&self) -> usize {
self.overlaps.len()
}
pub(crate) fn reserved_bytes(&self) -> u64 {
((self.overlaps.capacity() + self.previous.capacity()) * size_of::<Overlap>()
+ self.crossings.capacity() * size_of::<SensorCrossing>()) as u64
}
}