ncollide3d/query/visitors/
ray_intersection_cost_fn_visitor.rs1use crate::bounding_volume::BoundingVolume;
2use crate::math::Isometry;
3use crate::partitioning::{BestFirstVisitStatus, BestFirstVisitor};
4use crate::query::{PointQuery, Ray, RayCast, RayIntersection};
5use na::RealField;
6use std::any::Any;
7
8use crate::pipeline::{BroadPhase, BroadPhaseProxyHandle};
9
10pub struct RayIntersectionCostFnVisitor<'a, 'b, N: 'a + RealField + Copy, T, BV>
12where
13 BV: BoundingVolume<N> + RayCast<N> + PointQuery<N> + Any + Send + Sync + Clone,
14 T: Any + Send + Sync,
15{
16 ray: &'b Ray<N>,
18
19 max_toi: N,
21
22 broad_phase: &'a dyn BroadPhase<N, BV, T>,
27
28 cost_fn: &'a dyn Fn(T, &'b Ray<N>, N) -> Option<(T, RayIntersection<N>)>,
30}
31
32impl<'a, 'b, N: RealField + Copy, T, BV> RayIntersectionCostFnVisitor<'a, 'b, N, T, BV>
33where
34 BV: BoundingVolume<N> + RayCast<N> + PointQuery<N> + Any + Send + Sync + Clone,
35 T: Any + Send + Sync,
36{
37 #[inline]
39 pub fn new(
40 ray: &'b Ray<N>,
41 max_toi: N,
42 broad_phase: &'a dyn BroadPhase<N, BV, T>,
43 cost_fn: &'a dyn Fn(T, &'b Ray<N>, N) -> Option<(T, RayIntersection<N>)>,
44 ) -> RayIntersectionCostFnVisitor<'a, 'b, N, T, BV> {
45 RayIntersectionCostFnVisitor {
46 ray,
47 max_toi,
48 broad_phase,
49 cost_fn,
50 }
51 }
52}
53
54impl<'a, 'b, N, BV, T> BestFirstVisitor<N, BroadPhaseProxyHandle, BV>
55 for RayIntersectionCostFnVisitor<'a, 'b, N, T, BV>
56where
57 N: RealField + Copy,
58 BV: BoundingVolume<N> + RayCast<N> + PointQuery<N> + Any + Send + Sync + Clone,
59 T: Any + Send + Sync + Clone,
60{
61 type Result = (T, RayIntersection<N>);
62
63 #[inline]
64 fn visit(
65 &mut self,
66 best_cost_so_far: N,
67 bv: &BV,
68 data: Option<&BroadPhaseProxyHandle>,
69 ) -> BestFirstVisitStatus<N, Self::Result> {
70 if let Some(rough_toi) =
71 bv.toi_with_ray(&Isometry::identity(), self.ray, self.max_toi, true)
72 {
73 let mut res = BestFirstVisitStatus::Continue {
74 cost: rough_toi,
75 result: None,
76 };
77
78 if let Some(data_handle) = data {
80 if rough_toi < best_cost_so_far {
86 if let Some((_, leaf_data)) = self.broad_phase.proxy(*data_handle) {
89 if let Some(result) =
91 (self.cost_fn)(leaf_data.clone(), self.ray, self.max_toi)
92 {
93 res = BestFirstVisitStatus::Continue {
94 cost: result.1.toi,
95 result: Some(result),
96 };
97 }
98 }
99 };
100 }
101
102 res
103 } else {
104 BestFirstVisitStatus::Stop
106 }
107 }
108}