collide_sphere/
lib.rs

1#![deny(missing_docs)]
2
3/*!
4This crate contains a sphere collider, which implements the collide trait from the `collide` crate.
5**/
6
7use collide::{Collider, CollisionInfo};
8use num_traits::real::Real;
9use vector_space::{InnerSpace, VectorSpace};
10
11#[derive(Copy, Clone)]
12/// The sphere collider.
13pub struct Sphere<V: VectorSpace> {
14    /// The position of the sphere collider.
15    pub pos: V,
16    /// The radius of the sphere collider.
17    pub rad: V::Scalar,
18}
19
20impl<V: InnerSpace> Sphere<V> {
21    /// Creates a new sphere collider from a position and a radius.
22    pub fn new(pos: V, rad: V::Scalar) -> Self {
23        Self { pos, rad }
24    }
25}
26
27impl<V: InnerSpace> Collider for Sphere<V> {
28    type Vector = V;
29
30    fn check_collision(&self, other: &Self) -> bool {
31        let rad = self.rad + other.rad;
32        let rad2 = rad * rad;
33        let vec = other.pos - self.pos;
34        vec.magnitude2() <= rad2
35    }
36
37    fn collision_info(&self, other: &Self) -> Option<CollisionInfo<Self::Vector>> {
38        let rad = self.rad + other.rad;
39        let rad2 = rad * rad;
40        let vec = other.pos - self.pos;
41        let mag2 = vec.magnitude2();
42        if mag2 <= rad2 {
43            let mag = mag2.sqrt();
44            let direction = vec / mag;
45            Some(CollisionInfo {
46                self_contact: self.pos + direction * self.rad,
47                other_contact: other.pos - direction * other.rad,
48                vector: direction * (mag - rad),
49            })
50        } else {
51            None
52        }
53    }
54}