Scale a sphere and ray with respect to one another

This commit is contained in:
Savanni D'Gerinel 2024-06-23 15:34:08 -04:00
parent 40bfe6d74f
commit b07925a2c3
2 changed files with 57 additions and 5 deletions

View File

@ -48,9 +48,10 @@ impl Ray {
} }
pub fn intersect<'a>(&self, s: &'a Sphere) -> Intersections<'a> { pub fn intersect<'a>(&self, s: &'a Sphere) -> Intersections<'a> {
let sphere_to_ray = self.origin - Point::new(0., 0., 0.); let r2 = self.transform(s.transformation().inverse());
let a = self.direction.dot(&self.direction); let sphere_to_ray = r2.origin - Point::new(0., 0., 0.);
let b = 2. * self.direction.dot(&sphere_to_ray); let a = r2.direction.dot(&r2.direction);
let b = 2. * r2.direction.dot(&sphere_to_ray);
let c = sphere_to_ray.dot(&sphere_to_ray) - 1.; let c = sphere_to_ray.dot(&sphere_to_ray) - 1.;
let discriminant = b * b - 4. * a * c; let discriminant = b * b - 4. * a * c;
@ -199,4 +200,24 @@ mod tests {
assert_eq!(r2.origin, Point::new(2., 6., 12.)); assert_eq!(r2.origin, Point::new(2., 6., 12.));
assert_eq!(r2.direction, Vector::new(0., 3., 0.,)); assert_eq!(r2.direction, Vector::new(0., 3., 0.,));
} }
#[test]
fn intersect_scaled_sphere_with_ray() {
let r = Ray::new(Point::new(0., 0., -5.), Vector::new(0., 0., 1.));
let mut s = Sphere::new();
s.set_transformation(scaling(2., 2., 2.));
let xs = r.intersect(&s);
assert_eq!(xs.len(), 2);
assert_eq!(xs[0].t, 3.);
assert_eq!(xs[1].t, 7.);
}
#[test]
fn intersect_translated_sphere_with_ray() {
let r = Ray::new(Point::new(0., 0., -5.), Vector::new(0., 0., 1.));
let mut s = Sphere::new();
s.set_transformation(translation(5., 0., 0.));
let xs = r.intersect(&s);
assert_eq!(xs.len(), 0);
}
} }

View File

@ -1,13 +1,44 @@
use crate::types::Point; use crate::types::{Matrix, Point};
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct Sphere { pub struct Sphere {
origin: Point, origin: Point,
transformation: Matrix,
} }
impl Sphere { impl Sphere {
pub fn new() -> Self { pub fn new() -> Self {
Self{ origin: Point::new(0., 0., 0.) } Self {
origin: Point::new(0., 0., 0.),
transformation: Matrix::identity(),
}
}
pub fn transformation(&self) -> &Matrix {
&self.transformation
}
pub fn set_transformation(&mut self, m: Matrix) {
self.transformation = m
} }
} }
#[cfg(test)]
mod test {
use crate::transforms::translation;
use super::*;
#[test]
fn sphere_has_default_transformation() {
let s = Sphere::new();
assert_eq!(s.transformation(), &Matrix::identity());
}
#[test]
fn change_a_spheres_transformation() {
let mut s = Sphere::new();
let t = translation(2., 3., 4.);
s.set_transformation(t.clone());
assert_eq!(*s.transformation(), t);
}
}