use rand::Rng; use crate::{Point3, Ray, Vec3}; pub struct Camera { aspect_ratio: f64, viewport_height: f64, viewport_width: f64, origin: Point3, horizontal: Vec3, vertical: Vec3, lower_left_corner: Vec3, lens_radius: f64, u: Vec3, v: Vec3, w: Vec3, time0: f64, time1: f64 } impl Camera { pub fn get_ray(&self, s: f64, t: f64) -> Ray { let rd = self.lens_radius * Vec3::random_unit_disk(); let offset = self.u * rd.x() + self.v * rd.y(); let time = rand::thread_rng().gen_range(self.time0..self.time1); Ray::new( self.origin + offset, self.lower_left_corner + s*self.horizontal + t*self.vertical - self.origin - offset, time) } pub fn still( look_from: Point3, look_at: Point3, up: Vec3, aspect_ratio: f64, vfov: f64, aperture: f64, focus_dist: f64) -> Self { Camera::new( look_from, look_at, up, aspect_ratio, vfov, aperture, focus_dist, 0.0, 0.0) } pub fn new( look_from: Point3, look_at: Point3, up: Vec3, aspect_ratio: f64, vfov: f64, aperture: f64, focus_dist: f64, time0: f64, time1: f64) -> Self { let theta = vfov.to_radians(); let h = (theta / 2.0).tan(); let viewport_height = 2.0 * h; let viewport_width = aspect_ratio * viewport_height; let w = (look_from - look_at).unit_vector(); let u = up.cross(&w).unit_vector(); let v = w.cross(&u); let horizontal = focus_dist * viewport_width * u; let vertical = focus_dist * viewport_height * v; Camera { aspect_ratio, viewport_height, viewport_width, origin: look_from, horizontal, vertical, lower_left_corner: look_from - horizontal/2.0 - vertical/2.0 - focus_dist*w, lens_radius: aperture / 2.0, u, v, w, time0, time1 } } pub fn aspect_ratio(&self) -> f64 { self.aspect_ratio } }