diff --git a/src/camera/mod.rs b/src/camera/mod.rs index 1465be7..4d5d3ca 100644 --- a/src/camera/mod.rs +++ b/src/camera/mod.rs @@ -4,13 +4,13 @@ use crate::geometry::HitRecord; use crate::geometry::Hittable; use crate::interval::Interval; use crate::material::Surface; +use crate::math::random_in_unit_disk; use crate::ray::Ray; use image::RgbImage; use itertools::iproduct; use nalgebra::Vector3; use rand::prelude::*; use rand::rngs::ThreadRng; -use std::f64::consts::PI; use std::io::{self, Write}; use std::sync::Arc; use std::sync::mpsc::channel; @@ -41,19 +41,6 @@ pub struct Camera { pub background: Vector3, } -fn random_in_unit_disk(rng: &mut ThreadRng) -> Vector3 { - loop { - let p = Vector3::new( - rng.random_range(-1.0f64..1.0f64), - rng.random_range(-1.0f64..1.0f64), - 0.0, - ); - if p.norm_squared() < 1.0 { - return p; - } - } -} - fn linear_to_gamma(linear_component: f64) -> f64 { if linear_component > 0.0 { linear_component.sqrt() @@ -62,10 +49,6 @@ fn linear_to_gamma(linear_component: f64) -> f64 { } } -fn degrees_to_radians(degress: f64) -> f64 { - degress * PI / 180.0 -} - fn sample_square_stratified( s_i: u32, s_j: u32, @@ -92,7 +75,7 @@ impl Camera { let vup = Vector3::from(options.vup); let fov = options.fov; - let theta = degrees_to_radians(fov); + let theta = fov.to_radians(); let defocus_angle = options.defocus_angle; let focus_dist = options.focus_dist; @@ -116,7 +99,7 @@ impl Camera { let pixel00_loc = viewport_upper_left + 0.5 * (pixel_delta_u + pixel_delta_v); - let defocus_radius = focus_dist * degrees_to_radians(defocus_angle / 2.0).tan(); + let defocus_radius = focus_dist * (defocus_angle / 2.0).to_radians().tan(); let defocus_disk_u = u * defocus_radius; let defocus_disk_v = v * defocus_radius; diff --git a/src/math/mod.rs b/src/math/mod.rs index ecaebc0..f438e37 100644 --- a/src/math/mod.rs +++ b/src/math/mod.rs @@ -1,3 +1,4 @@ +use nalgebra::Vector2; use nalgebra::Vector3; use rand::prelude::*; @@ -23,6 +24,18 @@ pub fn near_zero(v: &Vector3) -> bool { v.x.abs() < 1e-8 && v.y.abs() < 1e-8 && v.z.abs() < 1e-8 } +pub fn random_in_unit_disk(rng: &mut T) -> Vector2 { + loop { + let p = Vector2::new( + rng.random_range(-1.0f64..1.0f64), + rng.random_range(-1.0f64..1.0f64), + ); + if p.norm_squared() < 1.0 { + return p; + } + } +} + pub fn reflect(a: &Vector3, n: &Vector3) -> Vector3 { a - n * (a.dot(n) * 2.0) } @@ -80,6 +93,17 @@ mod tests { } } + #[test] + fn test_random_in_unit_disk() { + let mut rng = ChaCha8Rng::seed_from_u64(0xdeadbeef); + let p = random_in_unit_disk(&mut rng); + assert_eq!(p, Vector2::new(0.7809098202583038, -0.09449568329690283,)); + for _ in 0..10000 { + let p = random_in_unit_disk(&mut rng); + assert!(p.norm_squared() < 1.0); // Ensure point is within the unit disk + } + } + #[test] fn test_near_zero_true() { let v = Vector3::new(1e-9, 1e-9, 1e-9);