spheres: implement basic unit sphere and intersect.

This commit is contained in:
Bill Thiede 2021-07-16 20:42:46 -07:00
parent f44d671573
commit da98744288

View File

@ -0,0 +1,59 @@
use crate::{
rays::Ray,
tuples::{dot, Tuple},
};
#[derive(Default)]
pub struct Sphere {}
pub struct Intersection {}
/// Intersect a ray with a sphere.
///
/// # Examples
/// ```
/// use rtchallenge::{
/// rays::Ray,
/// spheres::{intersect, Sphere},
/// tuples::Tuple,
/// };
///
/// // A ray intersects a sphere in two points.
/// let r = Ray::new(Tuple::point(0., 0., -5.), Tuple::vector(0., 0., 1.));
/// let s = Sphere::default();
/// let xs = intersect(&s, &r);
/// assert_eq!(xs, vec![4., 6.]);
///
/// // A ray intersects a sphere at a tangent.
/// let r = Ray::new(Tuple::point(0., 2., -5.), Tuple::vector(0., 0., 1.));
/// let s = Sphere::default();
/// let xs = intersect(&s, &r);
/// assert_eq!(xs, vec![]);
///
/// // A ray originates inside a sphere.
/// let r = Ray::new(Tuple::point(0., 0., 0.), Tuple::vector(0., 0., 1.));
/// let s = Sphere::default();
/// let xs = intersect(&s, &r);
/// assert_eq!(xs, vec![-1., 1.]);
///
/// // A sphere is behind a ray.
/// let r = Ray::new(Tuple::point(0., 0., 5.), Tuple::vector(0., 0., 1.));
/// let s = Sphere::default();
/// let xs = intersect(&s, &r);
/// assert_eq!(xs, vec![-6., -4.]);
/// ```
pub fn intersect(_sphere: &Sphere, ray: &Ray) -> Vec<f32> {
let sphere_to_ray = ray.origin - Tuple::point(0., 0., 0.);
let a = dot(ray.direction, ray.direction);
let b = 2. * dot(ray.direction, sphere_to_ray);
let c = dot(sphere_to_ray, sphere_to_ray) - 1.;
let discriminant = b * b - 4. * a * c;
if discriminant < 0. {
vec![]
} else {
vec![
(-b - discriminant.sqrt()) / (2. * a),
(-b + discriminant.sqrt()) / (2. * a),
]
}
}