use collide::{Collider, CollisionInfo};
use collide_ray::Ray;
use inner_space::InnerSpace;
use crate::Sphere;
impl<V: Copy + InnerSpace> Collider<Ray<V>> for Sphere<V> {
type Vector = V;
fn collision_info(&self, ray: &Ray<V>) -> Option<CollisionInfo<V>> {
let (_, info) = ray.intersect_sphere(self.center, self.radius)?;
Some(-info)
}
}
#[cfg(test)]
mod tests {
use super::*;
use simple_vectors::Vector;
type Vec3 = Vector<f32, 3>;
#[test]
fn ray_hits_sphere() {
let sphere = Sphere::new(Vec3::from([0.0, 0.0, 0.0]), 1.0);
let ray = Ray::new(Vec3::from([-5.0, 0.0, 0.0]), Vec3::from([1.0, 0.0, 0.0]));
let info = sphere.collision_info(&ray).unwrap();
let distance = info.vector.magnitude();
assert!((distance - 4.0).abs() < 0.001);
}
#[test]
fn ray_misses_sphere() {
let sphere = Sphere::new(Vec3::from([0.0, 0.0, 0.0]), 1.0);
let ray = Ray::new(Vec3::from([-5.0, 0.0, 0.0]), Vec3::from([0.0, 1.0, 0.0]));
assert!(sphere.collision_info(&ray).is_none());
}
#[test]
fn ray_behind_origin_misses() {
let sphere = Sphere::new(Vec3::from([0.0, 0.0, 0.0]), 1.0);
let ray = Ray::new(Vec3::from([5.0, 0.0, 0.0]), Vec3::from([1.0, 0.0, 0.0]));
assert!(sphere.collision_info(&ray).is_none());
}
}