parry3d_f64/query/visitors/
ray_intersections_visitor.rs1use 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
8pub 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 #[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)] 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}