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
use glam::Vec3;
use ivy_base::TransformMatrix;

use crate::{util::support, BoundingBox, Contact, Ray};

pub trait CollisionPrimitive {
    /// Returns the furtherst vertex in `dir`.
    /// Direction is given in collider/model space.
    fn support(&self, dir: Vec3) -> Vec3;
    /// Returns the maximum radius of the primitive. Used for sphere bounding.
    fn max_radius(&self) -> f32;

    /// Dynamically clone type erased collider.
    fn dyn_clone(&self) -> Box<dyn CollisionPrimitive + Send + Sync>;

    /// Returns an axis aligned bounding box enclosing the shape at the current
    /// rotation and scale
    fn bounding_box(&self, transform: TransformMatrix) -> BoundingBox
    where
        Self: Sized,
    {
        let inv = transform.inverse();

        let lx = support(&*transform, &inv, self, -Vec3::X).x;
        let ly = support(&*transform, &inv, self, -Vec3::Y).y;
        let lz = support(&*transform, &inv, self, -Vec3::Z).z;

        let rx = support(&*transform, &inv, self, Vec3::X).x;
        let ry = support(&*transform, &inv, self, Vec3::Y).y;
        let rz = support(&*transform, &inv, self, Vec3::Z).z;

        BoundingBox::from_corners(Vec3::new(lx, ly, lz), Vec3::new(rx, ry, rz))
    }
}

pub trait RayIntersect: CollisionPrimitive + Sized {
    // Returns true if the shape intersects the ray
    fn check_intersect(&self, transform: &TransformMatrix, ray: &Ray) -> bool;
    // Returns the intersection point of a ray onto shape
    fn intersect(&self, transform: &TransformMatrix, ray: &Ray) -> Option<Contact> {
        ray.intersects(self, transform)
    }
}