1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#![deny(missing_docs)]

/*!
This crate defines a generic collider trait, which is meant to be used by collision detection libraries.

You can define new colliders and implement the `Collider` trait, so this collider can be used with different collision detection libraries, which use this trait.

If you create a collision detection library, it can use different collider traits.
A collision detection library might be generic over vector types, scalar types and dimensions, or specialized for specific vector types, scalar types and dimensions.
**/

use std::ops::Neg;
use vector_space::VectorSpace;

/// Information of a detected collision between colliders objects.
/// The information is stored as elements of the specified vector space.
#[derive(Copy, Clone, Debug)]
pub struct CollisionInfo<V: VectorSpace> {
    /// The contact point at the first collider.
    pub self_contact: V,
    /// The contact point at the other collider.
    pub other_contact: V,
    /// The smallest vector by which the first collider needs to be moved, so the objects won't touch each other anymore.
    pub vector: V,
}

impl<V: VectorSpace> Neg for CollisionInfo<V> {
    type Output = Self;
    fn neg(self) -> Self {
        let Self {
            self_contact,
            other_contact,
            vector,
        } = self;
        Self {
            self_contact: other_contact,
            other_contact: self_contact,
            vector: -vector,
        }
    }
}

/// The collider trait, all colliders need to implement.
pub trait Collider<Other = Self> {
    /// The vector type of this collider.
    type Vector: VectorSpace;
    /// Checks the collision between two colliders.
    /// Defaults to a check of the return value of collision info.
    fn check_collision(&self, other: &Other) -> bool {
        self.collision_info(other).is_some()
    }
    /// If both colliders collide, returns some collision info, else returns none.
    fn collision_info(&self, other: &Other) -> Option<CollisionInfo<Self::Vector>>;
}