1use na::RealField;
2
3use crate::interpolation::RigidMotion;
4use crate::math::{Isometry, Vector};
5use crate::query::{self, Unsupported, TOI};
6use crate::shape::Shape;
7
8pub trait TOIDispatcher<N: RealField + Copy>: Send + Sync {
14 fn nonlinear_time_of_impact(
16 &self,
17 root_dispatcher: &dyn TOIDispatcher<N>,
18 motion1: &dyn RigidMotion<N>,
19 g1: &dyn Shape<N>,
20 motion2: &dyn RigidMotion<N>,
21 g2: &dyn Shape<N>,
22 max_toi: N,
23 target_distance: N,
24 ) -> Result<Option<TOI<N>>, Unsupported>;
25
26 fn time_of_impact(
31 &self,
32 root_dispatcher: &dyn TOIDispatcher<N>,
33 m1: &Isometry<N>,
34 vel1: &Vector<N>,
35 g1: &dyn Shape<N>,
36 m2: &Isometry<N>,
37 vel2: &Vector<N>,
38 g2: &dyn Shape<N>,
39 max_toi: N,
40 target_distance: N,
41 ) -> Result<Option<TOI<N>>, Unsupported>;
42
43 fn chain<U: TOIDispatcher<N>>(self, other: U) -> Chain<Self, U>
45 where
46 Self: Sized,
47 {
48 Chain(self, other)
49 }
50}
51
52#[derive(Debug, Clone)]
54pub struct DefaultTOIDispatcher;
55
56impl<N: RealField + Copy> TOIDispatcher<N> for DefaultTOIDispatcher {
57 fn nonlinear_time_of_impact(
58 &self,
59 root_dispatcher: &dyn TOIDispatcher<N>,
60 motion1: &dyn RigidMotion<N>,
61 g1: &dyn Shape<N>,
62 motion2: &dyn RigidMotion<N>,
63 g2: &dyn Shape<N>,
64 max_toi: N,
65 target_distance: N,
66 ) -> Result<Option<TOI<N>>, Unsupported> {
67 query::nonlinear_time_of_impact(
68 root_dispatcher,
69 motion1,
70 g1,
71 motion2,
72 g2,
73 max_toi,
74 target_distance,
75 )
76 }
77
78 fn time_of_impact(
79 &self,
80 root_dispatcher: &dyn TOIDispatcher<N>,
81 m1: &Isometry<N>,
82 vel1: &Vector<N>,
83 g1: &dyn Shape<N>,
84 m2: &Isometry<N>,
85 vel2: &Vector<N>,
86 g2: &dyn Shape<N>,
87 max_toi: N,
88 target_distance: N,
89 ) -> Result<Option<TOI<N>>, Unsupported> {
90 query::time_of_impact(
91 root_dispatcher,
92 m1,
93 vel1,
94 g1,
95 m2,
96 vel2,
97 g2,
98 max_toi,
99 target_distance,
100 )
101 }
102}
103
104pub struct Chain<T, U>(T, U);
106
107macro_rules! chain_method {
108 ($name:ident ( $( $arg:ident : $ty:ty,)*) -> $result:ty) => {
109 fn $name(&self, root_dispatcher: &dyn TOIDispatcher<N>,
110 $($arg : $ty,)*
111 ) -> Result<$result, Unsupported> {
112 (self.0).$name(root_dispatcher, $($arg,)*)
113 .or_else(|Unsupported| (self.1).$name(root_dispatcher, $($arg,)*))
114 }
115 }
116}
117
118impl<N, T, U> TOIDispatcher<N> for Chain<T, U>
119where
120 N: RealField + Copy,
121 T: TOIDispatcher<N>,
122 U: TOIDispatcher<N>,
123{
124 chain_method!(nonlinear_time_of_impact(
125 motion1: &dyn RigidMotion<N>,
126 g1: &dyn Shape<N>,
127 motion2: &dyn RigidMotion<N>,
128 g2: &dyn Shape<N>,
129 max_toi: N,
130 target_distance: N,
131 ) -> Option<TOI<N>>);
132
133 chain_method!(time_of_impact(
134 m1: &Isometry<N>,
135 vel1: &Vector<N>,
136 g1: &dyn Shape<N>,
137 m2: &Isometry<N>,
138 vel2: &Vector<N>,
139 g2: &dyn Shape<N>,
140 max_toi: N,
141 target_distance: N,
142 ) -> Option<TOI<N>>);
143}