parry3d_f64/query/visitors/
bounding_volume_intersections_visitor.rs

1use crate::bounding_volume::{Aabb, SimdAabb};
2use crate::math::SIMD_WIDTH;
3use crate::partitioning::{SimdVisitStatus, SimdVisitor};
4use core::marker::PhantomData;
5use simba::simd::SimdBool as _;
6
7/// Spatial partitioning data structure visitor collecting interferences with a given bounding volume.
8pub struct BoundingVolumeIntersectionsVisitor<T, F> {
9    bv: SimdAabb,
10    callback: F,
11    _phantom: PhantomData<T>,
12}
13
14impl<T, F> BoundingVolumeIntersectionsVisitor<T, F>
15where
16    F: FnMut(&T) -> bool,
17{
18    /// Creates a new `BoundingVolumeIntersectionsVisitor`.
19    #[inline]
20    pub fn new(bv: &Aabb, callback: F) -> BoundingVolumeIntersectionsVisitor<T, F> {
21        BoundingVolumeIntersectionsVisitor {
22            bv: SimdAabb::splat(*bv),
23            callback,
24            _phantom: PhantomData,
25        }
26    }
27}
28
29impl<T, F> SimdVisitor<T, SimdAabb> for BoundingVolumeIntersectionsVisitor<T, F>
30where
31    F: FnMut(&T) -> bool,
32{
33    #[inline]
34    fn visit(&mut self, bv: &SimdAabb, b: Option<[Option<&T>; SIMD_WIDTH]>) -> SimdVisitStatus {
35        let mask = bv.intersects(&self.bv);
36
37        if let Some(data) = b {
38            let bitmask = mask.bitmask();
39
40            for (ii, data) in data.iter().enumerate() {
41                if (bitmask & (1 << ii)) != 0 {
42                    let Some(data) = data else { continue };
43                    if !(self.callback)(data) {
44                        return SimdVisitStatus::ExitEarly;
45                    }
46                }
47            }
48        }
49
50        SimdVisitStatus::MaybeContinue(mask)
51    }
52}