// camera.rs use nalgebra::*; use crate::renderer::{Ray,Intersection}; use crate::elements::*; enum Camera { OrthoCamera(OrthoCamera), PerspectiveCamera(PerspectiveCamera), } // TODO: Create a separate scene object pub trait RaySource { fn trace(&self, ray: &Ray) -> Option; } pub struct OrthoCamera { pub pos: Vec3, pub output_img: bmp::Image, pub elements: Vec, pub lights: Vec, //spheres: Vec, //light: LightSrc, pub shadow_bias: f64, pub max_recursion_depth: u32 } impl RaySource for OrthoCamera { fn trace(&self, ray: &Ray) -> Option { self.elements.iter() .filter_map(|s| s.intersect(ray).map(|d| Intersection::new(d, s) )) .min_by(|i1, i2| i1.distance.partial_cmp(&i2.distance).unwrap()) } } pub struct PerspectiveCamera { pub pos: Vec3, pub output_img: bmp::Image, pub elements: Vec, pub lights: Vec, pub shadow_bias: f64, pub max_recursion_depth: u32, pub fov: f64, pub scene_width: u32, pub scene_height: u32, } impl PerspectiveCamera { pub fn create_prime(&self, x: u32, y: u32) -> Ray { let sensor_x = ((x as f64 + 0.5) / self.scene_width as f64) * 2.0 - 1.0; let sensor_y = 1.0 - ((y as f64 + 0.5) / self.scene_height as f64) * 2.0; Ray { pos: self.pos, dir: Vec3::new(sensor_x, sensor_y, 1.0).normalize(), } } pub fn percent_complete(&self, row: u32) -> f64 { let float_row = row as f64; let float_scene_height = self.scene_height as f64; let float_scene_width = self.scene_width as f64; ((float_row * float_scene_width) / (float_scene_width * float_scene_height)) * 100.0 } } impl RaySource for PerspectiveCamera { fn trace(&self, ray: &Ray) -> Option { self.elements.iter() .filter_map(|s| s.intersect(ray).map(|d| Intersection::new(d, s) )) .min_by(|i1, i2| i1.distance.partial_cmp(&i2.distance).unwrap()) } }