ncollide3d/query/
toi_dispatcher.rs

1use na::RealField;
2
3use crate::interpolation::RigidMotion;
4use crate::math::{Isometry, Vector};
5use crate::query::{self, Unsupported, TOI};
6use crate::shape::Shape;
7
8/// Dispatcher for time-of-impact queries
9///
10/// Custom implementations allow crates that support an abstract `TOIDispatcher` to handle custom
11/// shapes. Methods take `root_dispatcher` to allow dispatchers to delegate to eachother. Callers
12/// that will not themselves be used to implement a `TOIDispatcher` should pass `self`.
13pub trait TOIDispatcher<N: RealField + Copy>: Send + Sync {
14    /// Computes the smallest time of impact of two shapes under translational movement.
15    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    /// Computes the smallest time at with two shapes under translational movement are separated by a
27    /// distance smaller or equal to `distance`.
28    ///
29    /// Returns `0.0` if the objects are touching or penetrating.
30    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    /// Construct a `TOIDispatcher` that falls back on `other` for cases not handled by `self`
44    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/// A dispatcher that exposes built-in queries
53#[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
104/// The composition of two dispatchers
105pub 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}