diff --git a/src/main.rs b/src/main.rs index 6bc60b4..6a590a9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -125,7 +125,7 @@ fn ray_color(r: Ray, world: &dyn Hittable, depth: u32, srng: &mut SmallRng, dist } } - let unitdir = Vec3::as_unit(&r.dir); + let unitdir = Vec3::as_unit(r.dir); let t = 0.5 * (unitdir.y + 1.0); return Vec3::ones() * (1.0 - t) + Vec3::new(0.5, 0.7, 1.0) * t } @@ -134,17 +134,3 @@ fn degrees_to_radians(degrees: f32) -> f32 { degrees * std::f32::consts::PI / 180.0 } -fn hit_sphere(center: Vec3, radius: f32, ray: &Ray) -> f32{ - let oc = ray.orig - center; - let a = ray.dir.length_squared(); - let half_b = Vec3::dot(oc, ray.dir); - let c = oc.length_squared() - radius*radius; - let discriminant = half_b*half_b - a*c; - - if discriminant < 0.0 { - return -1.0; - } else { - return (-half_b - discriminant.sqrt()) / a; - } -} - diff --git a/src/material.rs b/src/material.rs index b13e8c9..8f21757 100644 --- a/src/material.rs +++ b/src/material.rs @@ -1,9 +1,9 @@ use crate::ray::Ray; use crate::hittable::HitRecord; -use crate::Vec3; +use crate::vec3; +use crate::vec3::Vec3; -use rand::Rng; use rand::rngs::SmallRng; use rand::distributions::Uniform; @@ -49,7 +49,7 @@ impl Material { }, Material::Metal { albedo, fuzz } => { let reflected = Vec3::reflect( - Vec3::as_unit(&ray_in.dir), + Vec3::as_unit(ray_in.dir), rec.normal ); *scattered = Ray{ @@ -63,7 +63,7 @@ impl Material { *attenuation = Vec3::ones(); let refraction_ratio = if rec.front_face { 1.0 / index_refraction } else { *index_refraction }; - let unit_direction = Vec3::as_unit(&ray_in.dir); + let unit_direction = Vec3::as_unit(ray_in.dir); let refracted = Vec3::refract(unit_direction, rec.normal, refraction_ratio); *scattered = Ray { diff --git a/src/vec3.rs b/src/vec3.rs index 191886d..75078d8 100644 --- a/src/vec3.rs +++ b/src/vec3.rs @@ -17,11 +17,7 @@ use rand::Rng; use rand::rngs::SmallRng; use rand::distributions::Uniform; -#[derive(Copy)] -#[derive(Clone)] -#[derive(PartialEq)] -#[derive(PartialOrd)] -#[derive(Debug)] +#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)] pub struct Vec3{ pub x: f32, pub y: f32, @@ -66,7 +62,7 @@ impl Vec3{ } pub fn rand_unit_vector(srng: &mut SmallRng, distrib: Uniform) -> Vec3 { - return Vec3::as_unit(&Vec3::rand_in_unit_sphere(srng, distrib)); + return Vec3::as_unit(Vec3::rand_in_unit_sphere(srng, distrib)); } pub fn length(&self) -> f32 { @@ -74,7 +70,7 @@ impl Vec3{ } pub fn length_squared(&self) -> f32 { - (self.x*self.x) + (self.y*self.y) + (self.z*self.z) + (self.x * self.x) + (self.y * self.y) + (self.z * self.z) } // roughly equivalent to the `void write_color(...)` in the book @@ -126,9 +122,9 @@ impl Vec3{ } } - pub fn as_unit(v: &Vec3) -> Vec3 { + pub fn as_unit(v: Vec3) -> Vec3 { let len = v.length(); - *v / len + v / len } } @@ -194,7 +190,6 @@ impl Mul for Vec3{ z: self.z * other, } } - } impl MulAssign for Vec3 { @@ -232,9 +227,9 @@ impl Div for Vec3 { type Output = Vec3; fn div(self, other: f32) -> Vec3 { Vec3 { - x: self.x / other, - y: self.y / other, - z: self.z / other, + x: 1.0/other * self.x, + y: 1.0/other * self.y, + z: 1.0/other * self.z, } } } @@ -449,6 +444,20 @@ mod test{ assert_eq!(Vec3::dot(v1, v2), 1.0); } + #[test] + fn test_dot_acute(){ + let v1 = Vec3::new(1.0, 1.0, 0.0); + let v2 = Vec3::new(0.5, 1.0, 0.0); + assert_eq!(Vec3::dot(v1, v2), 1.5); + } + + #[test] + fn test_dot_obtuse(){ + let v1 = Vec3::new(1.0, 1.0, 0.0); + let v2 = Vec3::new(0.5, -1.0, 0.0); + assert_eq!(Vec3::dot(v1, v2), -0.5); + } + #[test] fn test_cross_perpendicular(){ let v1 = Vec3::new(1.0, 0.0, 0.0); @@ -483,7 +492,7 @@ mod test{ let v = Vec3::new(2.0, 0.0, 0.0); let expected = Vec3::new(1.0, 0.0, 0.0); - assert_eq!(Vec3::as_unit(&v), expected); + assert_eq!(Vec3::as_unit(v), expected); } #[test] @@ -491,7 +500,7 @@ mod test{ let v = Vec3::new(0.5, 0.0, 0.0); let expected = Vec3::new(1.0, 0.0, 0.0); - assert_eq!(Vec3::as_unit(&v), expected); + assert_eq!(Vec3::as_unit(v), expected); } #[test] @@ -499,8 +508,42 @@ mod test{ let v = Vec3::new(1.0, 1.0, 1.0); let expected = Vec3::new(0.577350269,0.577350269,0.577350269); - assert!(Vec3::as_unit(&v) <= expected * 1.001); // within very small under-estimate - assert!(Vec3::as_unit(&v) >= expected * 0.999); // within very small over-estimate + assert!(Vec3::as_unit(v) <= expected * 1.001); // within very small under-estimate + assert!(Vec3::as_unit(v) >= expected * 0.999); // within very small over-estimate + } + + #[test] + fn test_reflect_flat(){ + let ray = Vec3::new(1.0, 0.0, 0.0); + let normal = Vec3::new(-1.0, 0.0, 0.0); + + let refl = Vec3::reflect(ray, normal); + let expected = Vec3::new(-1.0, 0.0, 0.0); + assert!(refl == expected); + } + + #[test] + fn test_reflect_flat_back(){ + let ray = Vec3::new(1.0, 0.0, 0.0); + let normal = Vec3::new(1.0, 0.0, 0.0); + + let refl = Vec3::reflect(ray, normal); + let expected = Vec3::new(-1.0, 0.0, 0.0); + assert!(refl == expected); + + } + + #[test] + fn test_reflect_45(){ + let ray = Vec3::new(1.0, 0.0, 0.0); + let normal = Vec3::as_unit(Vec3::new(-1.0, 1.0, 0.0)); + + + let refl = Vec3::reflect(ray, normal); + let expected = Vec3::new(0.0, 1.0, 0.0); + let diff = refl - expected; + eprintln!("Diff: {}", diff); + assert!(Vec3::near_zero(&diff)); } }