pub use collision::{CollisionStrategy, ComputeBound, Contact};
pub use collision::prelude::Primitive;
pub mod narrow;
pub mod broad;
pub mod prelude2d;
pub mod prelude3d;
use std::fmt::Debug;
use cgmath::prelude::*;
use collision::prelude::*;
pub trait Collider {
fn should_generate_contacts(&self, other: &Self) -> bool;
}
impl<'a> Collider for () {
fn should_generate_contacts(&self, _: &Self) -> bool {
true
}
}
#[derive(Debug, Clone, PartialOrd, PartialEq)]
#[cfg_attr(feature = "eders", derive(Serialize, Deserialize))]
pub enum CollisionMode {
Discrete,
Continuous,
}
#[derive(Debug, Clone)]
pub struct ContactEvent<ID, P>
where
P: EuclideanSpace,
P::Diff: Debug,
{
pub bodies: (ID, ID),
pub contact: Contact<P>,
}
impl<ID, P> ContactEvent<ID, P>
where
ID: Clone + Debug,
P: EuclideanSpace,
P::Diff: VectorSpace + Zero + Debug,
{
pub fn new(bodies: (ID, ID), contact: Contact<P>) -> Self {
Self { bodies, contact }
}
pub fn new_simple(strategy: CollisionStrategy, bodies: (ID, ID)) -> Self {
Self::new(bodies, Contact::new(strategy))
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "eders", derive(Serialize, Deserialize))]
pub struct CollisionShape<P, T, B, Y = ()>
where
P: Primitive,
{
pub enabled: bool,
base_bound: B,
transformed_bound: B,
primitives: Vec<(P, T)>,
strategy: CollisionStrategy,
mode: CollisionMode,
ty: Y,
}
impl<P, T, B, Y> CollisionShape<P, T, B, Y>
where
P: Primitive + ComputeBound<B>,
B: Bound<Point = P::Point> + Union<B, Output = B> + Clone,
T: Transform<P::Point>,
Y: Default,
{
pub fn new_complex(
strategy: CollisionStrategy,
mode: CollisionMode,
primitives: Vec<(P, T)>,
ty: Y,
) -> Self {
let bound: B = get_bound(&primitives);
Self {
base_bound: bound.clone(),
primitives,
enabled: true,
transformed_bound: bound,
strategy,
mode,
ty,
}
}
pub fn new_simple(strategy: CollisionStrategy, mode: CollisionMode, primitive: P) -> Self {
Self::new_complex(
strategy,
mode,
vec![(primitive, T::one())],
Default::default(),
)
}
pub fn new_simple_with_type(
strategy: CollisionStrategy,
mode: CollisionMode,
primitive: P,
ty: Y,
) -> Self {
Self::new_complex(strategy, mode, vec![(primitive, T::one())], ty)
}
pub fn new_simple_offset(
strategy: CollisionStrategy,
mode: CollisionMode,
primitive: P,
transform: T,
) -> Self {
Self::new_complex(
strategy,
mode,
vec![(primitive, transform)],
Default::default(),
)
}
pub fn update(&mut self, start: &T, end: Option<&T>) {
self.transformed_bound = match end {
None => self.base_bound.transform_volume(start),
Some(end_t) => {
let base = self.base_bound.transform_volume(end_t);
if self.mode == CollisionMode::Continuous {
base.union(&self.base_bound.transform_volume(start))
} else {
base
}
}
};
}
pub fn bound(&self) -> &B {
&self.transformed_bound
}
pub fn primitives(&self) -> &Vec<(P, T)> {
&self.primitives
}
}
impl<P, T, B, Y> HasBound for CollisionShape<P, T, B, Y>
where
P: Primitive + ComputeBound<B>,
B: Bound<Point = P::Point> + Union<B, Output = B> + Clone,
T: Transform<P::Point>,
Y: Default,
{
type Bound = B;
fn bound(&self) -> &Self::Bound {
&self.transformed_bound
}
}
fn get_bound<P, T, B>(primitives: &Vec<(P, T)>) -> B
where
P: Primitive + ComputeBound<B>,
B: Bound<Point = P::Point> + Union<B, Output = B>,
T: Transform<P::Point>,
{
primitives
.iter()
.map(|&(ref p, ref t)| p.compute_bound().transform_volume(t))
.fold(B::empty(), |bound, b| bound.union(&b))
}