diff --git a/rtchallenge/src/intersections.rs b/rtchallenge/src/intersections.rs index 71ff327..313a260 100644 --- a/rtchallenge/src/intersections.rs +++ b/rtchallenge/src/intersections.rs @@ -1,6 +1,10 @@ use std::ops::Index; -use crate::{rays::Ray, spheres::Sphere, tuples::Tuple}; +use crate::{ + rays::Ray, + spheres::Sphere, + tuples::{dot, Tuple}, +}; #[derive(Debug, Clone, PartialEq)] pub struct Intersection<'i> { @@ -136,6 +140,7 @@ pub struct PrecomputedData<'i> { pub point: Tuple, pub eyev: Tuple, pub normalv: Tuple, + pub inside: bool, } /// Precomputes data common to all intersections. @@ -149,6 +154,7 @@ pub struct PrecomputedData<'i> { /// tuples::Tuple, /// }; /// +/// // Precomputing the state of an intersection. /// let r = Ray::new(Tuple::point(0., 0., -5.), Tuple::vector(0., 0., 1.)); /// let shape = Sphere::default(); /// let i = Intersection::new(4., &shape); @@ -158,14 +164,40 @@ pub struct PrecomputedData<'i> { /// assert_eq!(comps.point, Tuple::point(0., 0., -1.)); /// assert_eq!(comps.eyev, Tuple::vector(0., 0., -1.)); /// assert_eq!(comps.normalv, Tuple::vector(0., 0., -1.)); +/// +/// // The hit, when an intersection occurs on the outside. +/// let r = Ray::new(Tuple::point(0., 0., -5.), Tuple::vector(0., 0., 1.)); +/// let shape = Sphere::default(); +/// let i = Intersection::new(4., &shape); +/// let comps = prepare_computations(&i, &r); +/// assert_eq!(comps.inside, false); +/// +/// // The hit, when an intersection occurs on the inside. +/// let r = Ray::new(Tuple::point(0., 0., 0.), Tuple::vector(0., 0., 1.)); +/// let shape = Sphere::default(); +/// let i = Intersection::new(1., &shape); +/// let comps = prepare_computations(&i, &r); +/// assert_eq!(comps.point, Tuple::point(0., 0., 1.)); +/// assert_eq!(comps.eyev, Tuple::vector(0., 0., -1.)); +/// assert_eq!(comps.inside, true); +//// // Normal would have been (0, 0, 1), but is inverted when inside. +/// assert_eq!(comps.normalv, Tuple::vector(0., 0., -1.)); /// ``` pub fn prepare_computations<'i>(i: &'i Intersection, r: &Ray) -> PrecomputedData<'i> { let point = r.position(i.t); + let normalv = i.object.normal_at(point); + let eyev = -r.direction; + let (inside, normalv) = if dot(normalv, eyev) < 0. { + (true, -normalv) + } else { + (false, normalv) + }; PrecomputedData { t: i.t, object: i.object, point, - eyev: -r.direction, - normalv: i.object.normal_at(point), + normalv, + inside, + eyev, } }