use crate::ray::Ray; use crate::utils::random_in_unit_disk; use cgmath::prelude::*; use cgmath::{vec3, Vector3}; use rand::prelude::*; pub struct Camera { origin: Vector3, lower_left_corner: Vector3, horizontal: Vector3, vertical: Vector3, u: Vector3, v: Vector3, w: Vector3, lens_radius: f64, time0: f64, time1: f64, } impl Camera { pub fn new( lookfrom: &Vector3, lookat: &Vector3, vup: &Vector3, vfov: f64, aspect: f64, aperture: f64, focus_dist: f64, time0: f64, time1: f64, ) -> Camera { let lens_radius = aperture / 2.0; let half_height = (vfov / 2.0).tan(); let half_width = aspect * half_height; let w = (lookfrom - lookat).normalize(); let u = vup.cross(w).normalize(); let v = w.cross(u); Camera { origin: *lookfrom, lower_left_corner: lookfrom - half_width * focus_dist * u - half_height * focus_dist * v - focus_dist * w, horizontal: 2.0 * half_width * focus_dist * u, vertical: 2.0 * half_height * focus_dist * v, lens_radius, u, v, w, time0, time1, } } pub fn get_ray(&self, rng: &mut ThreadRng, s: f64, t: f64) -> Ray { let rd = self.lens_radius * random_in_unit_disk(rng); let offset = self.u * rd.x + self.v * rd.y; Ray::new( self.origin + offset, self.lower_left_corner + s * self.horizontal + t * self.vertical - self.origin - offset, rng.gen_range(self.time0, self.time1), ) } }