Calculate the normal of the transformed sphere

This commit is contained in:
Savanni D'Gerinel 2024-06-23 17:09:06 -04:00
parent 4f47d65ba5
commit fa4ec059f7
6 changed files with 90 additions and 9 deletions

View File

@ -46,7 +46,7 @@ fn main() {
}
}
let ppm = PPM::from(canvas);
let ppm = PPM::from(&canvas);
let mut file = File::create("projectile.ppm").unwrap();
let _ = file.write(ppm.as_bytes());

View File

@ -91,7 +91,7 @@ mod tests {
0 0 0 0 0 0 0 128 0 0 0 0 0 0 0\n\
0 0 0 0 0 0 0 0 0 0 0 0 0 0 255\n";
let ppm = PPM::from(c);
let ppm = PPM::from(&c);
assert_eq!(*ppm, expected);
}
@ -112,7 +112,7 @@ mod tests {
255 204 153 255 204 153 255 204 153 255 204 153 255 204 153 255 204\n\
153 255 204 153 255 204 153 255 204 153 255 204 153\n";
let ppm = PPM::from(c);
let ppm = PPM::from(&c);
assert_eq!(*ppm, expected);
}
}

View File

@ -235,10 +235,25 @@ impl std::ops::Mul<Tuple> for Matrix {
}
}
impl std::ops::Mul<&Point> for &Matrix {
type Output = Point;
fn mul(self, rside: &Point) -> Point {
let t: Tuple = **rside;
Point::from(self * t)
}
}
impl std::ops::Mul<Point> for &Matrix {
type Output = Point;
fn mul(self, rside: Point) -> Point {
Point::from(self * *rside)
self * &rside
}
}
impl std::ops::Mul<&Point> for Matrix {
type Output = Point;
fn mul(self, rside: &Point) -> Point {
&self * rside
}
}

View File

@ -51,10 +51,17 @@ impl std::ops::Add<Vector> for Point {
}
}
impl std::ops::Sub for Point {
impl std::ops::Sub<&Point> for &Point {
type Output = Vector;
fn sub(self, r: &Point) -> Self::Output {
Vector::from(self.0 - r.0)
}
}
impl std::ops::Sub<Point> for Point {
type Output = Vector;
fn sub(self, r: Point) -> Self::Output {
Vector::from(self.0 - r.0)
&self - &r
}
}

View File

@ -1,4 +1,4 @@
use crate::types::{Matrix, Point};
use crate::types::{Matrix, Point, Vector};
#[derive(Debug, PartialEq)]
pub struct Sphere {
@ -14,6 +14,15 @@ impl Sphere {
pub fn set_transformation(&mut self, m: Matrix) {
self.transformation = m
}
pub fn normal_at(&self, world_point: &Point) -> Vector {
let inverted_transform = self.transformation.inverse();
let object_point = &inverted_transform * world_point;
let object_normal = object_point - Point::new(0., 0., 0.);
let mut world_normal = inverted_transform.transpose() * *object_normal;
world_normal.3 = 0.;
Vector::from(world_normal).normalize()
}
}
impl Default for Sphere {
@ -28,7 +37,7 @@ impl Default for Sphere {
#[cfg(test)]
mod test {
use super::*;
use crate::transforms::translation;
use crate::transforms::{rotation_z, scaling, translation};
#[test]
fn sphere_has_default_transformation() {
@ -43,4 +52,55 @@ mod test {
s.set_transformation(t.clone());
assert_eq!(*s.transformation(), t);
}
#[test]
fn normal_of_sphere_on_x() {
let s = Sphere::default();
let n = s.normal_at(&Point::new(1., 0., 0.));
assert_eq!(n, Vector::new(1., 0., 0.));
}
#[test]
fn normal_of_sphere_on_y() {
let s = Sphere::default();
let n = s.normal_at(&Point::new(0., 1., 0.));
assert_eq!(n, Vector::new(0., 1., 0.));
}
#[test]
fn normal_of_sphere_on_z() {
let s = Sphere::default();
let n = s.normal_at(&Point::new(0., 0., 1.));
assert_eq!(n, Vector::new(0., 0., 1.));
}
#[test]
fn normal_of_sphere_on_nonaxial() {
let s = Sphere::default();
let n = s.normal_at(&Point::new(3_f64.sqrt() / 3., 3_f64.sqrt() / 3., 3_f64.sqrt() / 3.));
assert_eq!(n, Vector::new(3_f64.sqrt() / 3., 3_f64.sqrt() / 3., 3_f64.sqrt() / 3.));
}
#[test]
fn normal_is_normalized() {
let s = Sphere::default();
let n = s.normal_at(&Point::new(3_f64.sqrt() / 3., 3_f64.sqrt() / 3., 3_f64.sqrt() / 3.));
assert_eq!(n.normalize(), n);
}
#[test]
fn compute_normal_of_translated_sphere() {
let mut s = Sphere::default();
s.set_transformation(translation(0., 1., 0.));
let n = s.normal_at(&Point::new(0., 1.70711, -0.70711));
assert_eq!(n, Vector::new(0., 0.70711, -0.70711));
}
#[test]
fn compute_normal_of_transformed_sphere() {
let mut s = Sphere::default();
s.set_transformation(scaling(1., 0.5, 1.) * rotation_z(std::f64::consts::PI / 5.));
let n = s.normal_at(&Point::new(0., 2_f64.sqrt() / 2., -2_f64.sqrt() / 2.));
assert_eq!(n, Vector::new(0., 0.97014, -0.24254));
}
}

View File

@ -108,4 +108,3 @@ impl std::ops::Div<f64> for Tuple {
&self / scalar
}
}