intersections: add inside/outside to prepare_computations.

This commit is contained in:
Bill Thiede 2021-07-17 15:46:02 -07:00
parent 2316df896a
commit 9924330f98

View File

@ -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,
}
}