Calculate the normal of the transformed sphere
This commit is contained in:
parent
4f47d65ba5
commit
fa4ec059f7
|
@ -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 mut file = File::create("projectile.ppm").unwrap();
|
||||||
let _ = file.write(ppm.as_bytes());
|
let _ = file.write(ppm.as_bytes());
|
||||||
|
|
|
@ -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 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";
|
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);
|
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\
|
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";
|
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);
|
assert_eq!(*ppm, expected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
impl std::ops::Mul<Point> for &Matrix {
|
||||||
type Output = Point;
|
type Output = Point;
|
||||||
fn mul(self, rside: Point) -> 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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
type Output = Vector;
|
||||||
fn sub(self, r: Point) -> Self::Output {
|
fn sub(self, r: Point) -> Self::Output {
|
||||||
Vector::from(self.0 - r.0)
|
&self - &r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::types::{Matrix, Point};
|
use crate::types::{Matrix, Point, Vector};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct Sphere {
|
pub struct Sphere {
|
||||||
|
@ -14,6 +14,15 @@ impl Sphere {
|
||||||
pub fn set_transformation(&mut self, m: Matrix) {
|
pub fn set_transformation(&mut self, m: Matrix) {
|
||||||
self.transformation = m
|
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 {
|
impl Default for Sphere {
|
||||||
|
@ -28,7 +37,7 @@ impl Default for Sphere {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::transforms::translation;
|
use crate::transforms::{rotation_z, scaling, translation};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn sphere_has_default_transformation() {
|
fn sphere_has_default_transformation() {
|
||||||
|
@ -43,4 +52,55 @@ mod test {
|
||||||
s.set_transformation(t.clone());
|
s.set_transformation(t.clone());
|
||||||
assert_eq!(*s.transformation(), t);
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,4 +108,3 @@ impl std::ops::Div<f64> for Tuple {
|
||||||
&self / scalar
|
&self / scalar
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue