use na::RealField;
use crate::interpolation::RigidMotion;
use crate::math::{Isometry, Vector};
use crate::query::{self, Unsupported, TOI};
use crate::shape::Shape;
pub trait TOIDispatcher<N: RealField + Copy>: Send + Sync {
fn nonlinear_time_of_impact(
&self,
root_dispatcher: &dyn TOIDispatcher<N>,
motion1: &dyn RigidMotion<N>,
g1: &dyn Shape<N>,
motion2: &dyn RigidMotion<N>,
g2: &dyn Shape<N>,
max_toi: N,
target_distance: N,
) -> Result<Option<TOI<N>>, Unsupported>;
fn time_of_impact(
&self,
root_dispatcher: &dyn TOIDispatcher<N>,
m1: &Isometry<N>,
vel1: &Vector<N>,
g1: &dyn Shape<N>,
m2: &Isometry<N>,
vel2: &Vector<N>,
g2: &dyn Shape<N>,
max_toi: N,
target_distance: N,
) -> Result<Option<TOI<N>>, Unsupported>;
fn chain<U: TOIDispatcher<N>>(self, other: U) -> Chain<Self, U>
where
Self: Sized,
{
Chain(self, other)
}
}
#[derive(Debug, Clone)]
pub struct DefaultTOIDispatcher;
impl<N: RealField + Copy> TOIDispatcher<N> for DefaultTOIDispatcher {
fn nonlinear_time_of_impact(
&self,
root_dispatcher: &dyn TOIDispatcher<N>,
motion1: &dyn RigidMotion<N>,
g1: &dyn Shape<N>,
motion2: &dyn RigidMotion<N>,
g2: &dyn Shape<N>,
max_toi: N,
target_distance: N,
) -> Result<Option<TOI<N>>, Unsupported> {
query::nonlinear_time_of_impact(
root_dispatcher,
motion1,
g1,
motion2,
g2,
max_toi,
target_distance,
)
}
fn time_of_impact(
&self,
root_dispatcher: &dyn TOIDispatcher<N>,
m1: &Isometry<N>,
vel1: &Vector<N>,
g1: &dyn Shape<N>,
m2: &Isometry<N>,
vel2: &Vector<N>,
g2: &dyn Shape<N>,
max_toi: N,
target_distance: N,
) -> Result<Option<TOI<N>>, Unsupported> {
query::time_of_impact(
root_dispatcher,
m1,
vel1,
g1,
m2,
vel2,
g2,
max_toi,
target_distance,
)
}
}
pub struct Chain<T, U>(T, U);
macro_rules! chain_method {
($name:ident ( $( $arg:ident : $ty:ty,)*) -> $result:ty) => {
fn $name(&self, root_dispatcher: &dyn TOIDispatcher<N>,
$($arg : $ty,)*
) -> Result<$result, Unsupported> {
(self.0).$name(root_dispatcher, $($arg,)*)
.or_else(|Unsupported| (self.1).$name(root_dispatcher, $($arg,)*))
}
}
}
impl<N, T, U> TOIDispatcher<N> for Chain<T, U>
where
N: RealField + Copy,
T: TOIDispatcher<N>,
U: TOIDispatcher<N>,
{
chain_method!(nonlinear_time_of_impact(
motion1: &dyn RigidMotion<N>,
g1: &dyn Shape<N>,
motion2: &dyn RigidMotion<N>,
g2: &dyn Shape<N>,
max_toi: N,
target_distance: N,
) -> Option<TOI<N>>);
chain_method!(time_of_impact(
m1: &Isometry<N>,
vel1: &Vector<N>,
g1: &dyn Shape<N>,
m2: &Isometry<N>,
vel2: &Vector<N>,
g2: &dyn Shape<N>,
max_toi: N,
target_distance: N,
) -> Option<TOI<N>>);
}