use crate::math::{Isometry, Real, Vector};
use crate::motion::RigidMotion;
use crate::query::contact_manifolds::ContactManifoldsWorkspace;
use crate::query::{ClosestPoints, Contact, ContactManifold, Unsupported, TOI};
use crate::shape::Shape;
pub trait PersistentQueryDispatcher<ManifoldData, ContactData>: QueryDispatcher {
fn contact_manifolds(
&self,
pos12: &Isometry<Real>,
g1: &dyn Shape,
g2: &dyn Shape,
prediction: Real,
manifolds: &mut Vec<ContactManifold<ManifoldData, ContactData>>,
workspace: &mut Option<ContactManifoldsWorkspace>,
) -> Result<(), Unsupported>;
fn contact_manifold_convex_convex(
&self,
pos12: &Isometry<Real>,
g1: &dyn Shape,
g2: &dyn Shape,
prediction: Real,
manifold: &mut ContactManifold<ManifoldData, ContactData>,
) -> Result<(), Unsupported>;
}
pub trait QueryDispatcher: Send + Sync {
fn intersection_test(
&self,
pos12: &Isometry<Real>,
g1: &dyn Shape,
g2: &dyn Shape,
) -> Result<bool, Unsupported>;
fn distance(
&self,
pos12: &Isometry<Real>,
g1: &dyn Shape,
g2: &dyn Shape,
) -> Result<Real, Unsupported>;
fn contact(
&self,
pos12: &Isometry<Real>,
g1: &dyn Shape,
g2: &dyn Shape,
prediction: Real,
) -> Result<Option<Contact>, Unsupported>;
fn closest_points(
&self,
pos12: &Isometry<Real>,
g1: &dyn Shape,
g2: &dyn Shape,
max_dist: Real,
) -> Result<ClosestPoints, Unsupported>;
fn time_of_impact(
&self,
pos12: &Isometry<Real>,
vel12: &Vector<Real>,
g1: &dyn Shape,
g2: &dyn Shape,
max_toi: Real,
target_distance: Real,
) -> Result<Option<TOI>, Unsupported>;
fn chain<U: QueryDispatcher>(self, other: U) -> QueryDispatcherChain<Self, U>
where
Self: Sized,
{
QueryDispatcherChain(self, other)
}
fn nonlinear_time_of_impact(
&self,
motion12: &dyn RigidMotion,
g1: &dyn Shape,
g2: &dyn Shape,
max_toi: Real,
target_distance: Real,
) -> Result<Option<TOI>, Unsupported>;
}
pub struct QueryDispatcherChain<T, U>(T, U);
macro_rules! chain_method {
($name:ident ( $( $arg:ident : $ty:ty,)*) -> $result:ty) => {
fn $name(&self, $($arg : $ty,)*
) -> Result<$result, Unsupported> {
(self.0).$name($($arg,)*)
.or_else(|Unsupported| (self.1).$name($($arg,)*))
}
}
}
impl<T, U> QueryDispatcher for QueryDispatcherChain<T, U>
where
T: QueryDispatcher,
U: QueryDispatcher,
{
chain_method!(intersection_test(
pos12: &Isometry<Real>,
g1: &dyn Shape,
g2: &dyn Shape,
) -> bool);
chain_method!(distance(pos12: &Isometry<Real>, g1: &dyn Shape, g2: &dyn Shape,) -> Real);
chain_method!(contact(
pos12: &Isometry<Real>,
g1: &dyn Shape,
g2: &dyn Shape,
prediction: Real,
) -> Option<Contact>);
chain_method!(closest_points(
pos12: &Isometry<Real>,
g1: &dyn Shape,
g2: &dyn Shape,
max_dist: Real,
) -> ClosestPoints);
chain_method!(time_of_impact(
pos12: &Isometry<Real>,
vel12: &Vector<Real>,
g1: &dyn Shape,
g2: &dyn Shape,
max_toi: Real,
target_distance: Real,
) -> Option<TOI>);
chain_method!(nonlinear_time_of_impact(
motion12: &dyn RigidMotion,
g1: &dyn Shape,
g2: &dyn Shape,
max_toi: Real,
target_distance: Real,
) -> Option<TOI>);
}