Translate and scale a ray
This commit is contained in:
parent
8e4f6b06e6
commit
af7d8680a0
|
@ -1,7 +1,6 @@
|
||||||
|
use crate::types::{Matrix, Point, Sphere, Vector};
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
use crate::types::{Point, Sphere, Vector};
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct Intersection<'a> {
|
pub struct Intersection<'a> {
|
||||||
t: f64,
|
t: f64,
|
||||||
|
@ -10,7 +9,7 @@ pub struct Intersection<'a> {
|
||||||
|
|
||||||
pub struct Intersections<'a>(Vec<Intersection<'a>>);
|
pub struct Intersections<'a>(Vec<Intersection<'a>>);
|
||||||
|
|
||||||
impl <'a> Intersections<'a> {
|
impl<'a> Intersections<'a> {
|
||||||
pub fn len(&'a self) -> usize {
|
pub fn len(&'a self) -> usize {
|
||||||
self.0.len()
|
self.0.len()
|
||||||
}
|
}
|
||||||
|
@ -20,14 +19,14 @@ impl <'a> Intersections<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <'a> std::ops::Index<usize> for Intersections<'a> {
|
impl<'a> std::ops::Index<usize> for Intersections<'a> {
|
||||||
type Output = Intersection<'a>;
|
type Output = Intersection<'a>;
|
||||||
fn index(&self, idx: usize) -> &Intersection<'a> {
|
fn index(&self, idx: usize) -> &Intersection<'a> {
|
||||||
&self.0[idx]
|
&self.0[idx]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <'a> From<Vec<Intersection<'a>>> for Intersections<'a> {
|
impl<'a> From<Vec<Intersection<'a>>> for Intersections<'a> {
|
||||||
fn from(mut v: Vec<Intersection<'a>>) -> Self {
|
fn from(mut v: Vec<Intersection<'a>>) -> Self {
|
||||||
v.sort_by(|l, r| l.t.partial_cmp(&r.t).unwrap_or(Ordering::Equal));
|
v.sort_by(|l, r| l.t.partial_cmp(&r.t).unwrap_or(Ordering::Equal));
|
||||||
Self(v)
|
Self(v)
|
||||||
|
@ -65,13 +64,22 @@ impl Ray {
|
||||||
vec![
|
vec![
|
||||||
Intersection { t: t1, object: &s },
|
Intersection { t: t1, object: &s },
|
||||||
Intersection { t: t2, object: &s },
|
Intersection { t: t2, object: &s },
|
||||||
].into()
|
]
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn transform(&self, m: Matrix) -> Self {
|
||||||
|
Self {
|
||||||
|
origin: m.clone() * self.origin,
|
||||||
|
direction: m * self.direction,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::transforms::{scaling, translation};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn computing_point_from_distance() {
|
fn computing_point_from_distance() {
|
||||||
|
@ -135,8 +143,8 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn hit_all_intersections_are_positive() {
|
fn hit_all_intersections_are_positive() {
|
||||||
let s = Sphere::new();
|
let s = Sphere::new();
|
||||||
let i1 = Intersection{ t: 1., object: &s };
|
let i1 = Intersection { t: 1., object: &s };
|
||||||
let i2 = Intersection{ t: 2., object: &s };
|
let i2 = Intersection { t: 2., object: &s };
|
||||||
let xs = Intersections::from(vec![i1.clone(), i2]);
|
let xs = Intersections::from(vec![i1.clone(), i2]);
|
||||||
|
|
||||||
assert_eq!(xs.hit(), Some(&i1));
|
assert_eq!(xs.hit(), Some(&i1));
|
||||||
|
@ -145,8 +153,8 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn hit_some_intersections_are_negative() {
|
fn hit_some_intersections_are_negative() {
|
||||||
let s = Sphere::new();
|
let s = Sphere::new();
|
||||||
let i1 = Intersection{ t: -1., object: &s };
|
let i1 = Intersection { t: -1., object: &s };
|
||||||
let i2 = Intersection{ t: 1., object: &s };
|
let i2 = Intersection { t: 1., object: &s };
|
||||||
let xs = Intersections::from(vec![i1, i2.clone()]);
|
let xs = Intersections::from(vec![i1, i2.clone()]);
|
||||||
|
|
||||||
assert_eq!(xs.hit(), Some(&i2));
|
assert_eq!(xs.hit(), Some(&i2));
|
||||||
|
@ -155,8 +163,8 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn hit_all_intersections_are_negative() {
|
fn hit_all_intersections_are_negative() {
|
||||||
let s = Sphere::new();
|
let s = Sphere::new();
|
||||||
let i1 = Intersection{ t: -2., object: &s };
|
let i1 = Intersection { t: -2., object: &s };
|
||||||
let i2 = Intersection{ t: -1., object: &s };
|
let i2 = Intersection { t: -1., object: &s };
|
||||||
let xs = Intersections::from(vec![i1, i2]);
|
let xs = Intersections::from(vec![i1, i2]);
|
||||||
|
|
||||||
assert_eq!(xs.hit(), None);
|
assert_eq!(xs.hit(), None);
|
||||||
|
@ -165,12 +173,30 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn hit_is_always_lowest_nonnegative() {
|
fn hit_is_always_lowest_nonnegative() {
|
||||||
let s = Sphere::new();
|
let s = Sphere::new();
|
||||||
let i1 = Intersection{ t: 5., object: &s };
|
let i1 = Intersection { t: 5., object: &s };
|
||||||
let i2 = Intersection{ t: 7., object: &s };
|
let i2 = Intersection { t: 7., object: &s };
|
||||||
let i3 = Intersection{ t: -3., object: &s };
|
let i3 = Intersection { t: -3., object: &s };
|
||||||
let i4 = Intersection{ t: 2., object: &s };
|
let i4 = Intersection { t: 2., object: &s };
|
||||||
let xs = Intersections::from(vec![i1, i2, i3, i4.clone()]);
|
let xs = Intersections::from(vec![i1, i2, i3, i4.clone()]);
|
||||||
|
|
||||||
assert_eq!(xs.hit(), Some(&i4));
|
assert_eq!(xs.hit(), Some(&i4));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn translate_a_ray() {
|
||||||
|
let r = Ray::new(Point::new(1., 2., 3.), Vector::new(0., 1., 0.));
|
||||||
|
let m = translation(3., 4., 5.);
|
||||||
|
let r2 = r.transform(m);
|
||||||
|
assert_eq!(r2.origin, Point::new(4., 6., 8.));
|
||||||
|
assert_eq!(r2.direction, Vector::new(0., 1., 0.));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn scale_a_ray() {
|
||||||
|
let r = Ray::new(Point::new(1., 2., 3.), Vector::new(0., 1., 0.));
|
||||||
|
let m = scaling(2., 3., 4.);
|
||||||
|
let r2 = r.transform(m);
|
||||||
|
assert_eq!(r2.origin, Point::new(2., 6., 12.));
|
||||||
|
assert_eq!(r2.direction, Vector::new(0., 3., 0.,));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue