parry3d_f64/query/visitors/
ray_intersections_visitor.rs

1use crate::bounding_volume::SimdAabb;
2use crate::math::{Real, SimdReal, SIMD_WIDTH};
3use crate::partitioning::{SimdVisitStatus, SimdVisitor};
4use crate::query::{Ray, SimdRay};
5use core::marker::PhantomData;
6use simba::simd::{SimdBool as _, SimdValue};
7
8/// Bounding Volume Tree visitor collecting intersections with a given ray.
9pub struct RayIntersectionsVisitor<'a, T, F> {
10    simd_ray: SimdRay,
11    max_time_of_impact: SimdReal,
12    callback: &'a mut F,
13    _phantom: PhantomData<T>,
14}
15
16impl<'a, T, F> RayIntersectionsVisitor<'a, T, F>
17where
18    F: FnMut(&T) -> bool,
19{
20    /// Creates a new `RayIntersectionsVisitor`.
21    #[inline]
22    pub fn new(
23        ray: &Ray,
24        max_time_of_impact: Real,
25        callback: &'a mut F,
26    ) -> RayIntersectionsVisitor<'a, T, F> {
27        RayIntersectionsVisitor {
28            simd_ray: SimdRay::splat(*ray),
29            max_time_of_impact: SimdReal::splat(max_time_of_impact),
30            callback,
31            _phantom: PhantomData,
32        }
33    }
34}
35
36impl<T, F> SimdVisitor<T, SimdAabb> for RayIntersectionsVisitor<'_, T, F>
37where
38    F: FnMut(&T) -> bool,
39{
40    #[inline]
41    fn visit(&mut self, bv: &SimdAabb, b: Option<[Option<&T>; SIMD_WIDTH]>) -> SimdVisitStatus {
42        let mask = bv.cast_local_ray(&self.simd_ray, self.max_time_of_impact).0;
43
44        if let Some(data) = b {
45            let bitmask = mask.bitmask();
46
47            #[allow(clippy::needless_range_loop)] // Easier to read for simd stuffs.
48            for (ii, data) in data.into_iter().enumerate() {
49                if (bitmask & (1 << ii)) != 0 {
50                    if let Some(data) = data {
51                        if !(self.callback)(data) {
52                            return SimdVisitStatus::ExitEarly;
53                        }
54                    }
55                }
56            }
57        }
58
59        SimdVisitStatus::MaybeContinue(mask)
60    }
61}