diff --git a/rtchallenge/src/intersections.rs b/rtchallenge/src/intersections.rs index fb93503..19dba3c 100644 --- a/rtchallenge/src/intersections.rs +++ b/rtchallenge/src/intersections.rs @@ -114,6 +114,15 @@ impl<'i> Intersections<'i> { } } +impl<'i> IntoIterator for Intersections<'i> { + type Item = Intersection<'i>; + type IntoIter = std::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} + impl<'i> Index for Intersections<'i> { type Output = Intersection<'i>; fn index(&self, idx: usize) -> &Self::Output { diff --git a/rtchallenge/src/world.rs b/rtchallenge/src/world.rs index c940368..de7c93f 100644 --- a/rtchallenge/src/world.rs +++ b/rtchallenge/src/world.rs @@ -1,8 +1,10 @@ use crate::{ + intersections::Intersections, lights::PointLight, materials::Material, matrices::{Matrix2x2, Matrix4x4}, - spheres::Sphere, + rays::Ray, + spheres::{intersect, Sphere}, tuples::{Color, Tuple}, }; @@ -51,4 +53,32 @@ impl World { objects: vec![s1, s2], } } + + /// Intesects the ray with this world. + /// # Examples + /// ``` + /// use rtchallenge::{rays::Ray, tuples::Tuple, world::World}; + /// + /// let w = World::test_world(); + /// let r = Ray::new(Tuple::point(0., 0., -5.), Tuple::vector(0., 0., 1.)); + /// let xs = w.intersect(&r); + /// assert_eq!(xs.len(), 4); + /// assert_eq!(xs[0].t, 4.); + /// assert_eq!(xs[1].t, 4.5); + /// assert_eq!(xs[2].t, 5.5); + /// assert_eq!(xs[3].t, 6.); + /// ``` + pub fn intersect(&self, r: &Ray) -> Intersections { + let mut xs: Vec<_> = self + .objects + .iter() + .map(|o| intersect(&o, &r)) + .flatten() + .collect(); + xs.sort_by(|i1, i2| { + i1.t.partial_cmp(&i2.t) + .expect("an intersection has a t value that is NaN") + }); + Intersections::new(xs) + } }