diff options
-rw-r--r-- | src/camera.rs | 124 |
1 files changed, 70 insertions, 54 deletions
diff --git a/src/camera.rs b/src/camera.rs index 587e75c..1b96575 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -26,78 +26,94 @@ pub struct Camera { impl Default for Camera { fn default() -> Self { - let aspect_ratio = ASPECT_RATIO; + Self::new( + ASPECT_RATIO, + IMG_WIDTH, + VFOV, + LOOK_FROM, + LOOK_AT, + VUP, + SAMPLES_PER_PIXEL, + FOCUS_DIST, + DEFOCUS_ANGLE, + MAX_DEPTH + ) + } +} - let image_width = IMG_WIDTH; - let image_height = get_image_height(image_width, aspect_ratio); +impl Camera { + pub fn new( + aspect_ratio: f32, + image_width: usize, + vfov: f32, + look_from: Point3, + look_at: Point3, + vup: Vec3, + samples_per_pixel: usize, + focus_dist: f32, + defocus_angle: f32, + max_depth: usize, + ) -> Self { + let mut new_camera = Self { + aspect_ratio, + image_width, + image_height: 1, + center: Point3::new(0.0, 0.0, 0.0), + pixel_upper_left: Point3::new(0.0, 0.0, 0.0), + delta_pixel_u: Vec3::new(0.0, 0.0, 0.0), + delta_pixel_v: Vec3::new(0.0, 0.0, 0.0), + samples_per_pixel, + pixel_samples_scale: 1.0, + max_depth, + vfov, + look_from, + look_at, + vup, + defocus_angle, + focus_dist, + defocus_disk_u: Vec3::new(0.0, 0.0, 0.0), + defocus_disk_v: Vec3::new(0.0, 0.0, 0.0), + }; - let vfov = VFOV; - let look_from = LOOK_FROM; - let look_at = LOOK_AT; - let vup = VUP; + new_camera.compute_dependent_fields(); + new_camera + } - let center = look_from; - // let focal_length = look_from.sub(&look_at).mag(); - let theta = deg2rad(vfov); - let h = (theta / 2.0).tan(); + fn compute_dependent_fields(&mut self) { + self.image_height = get_image_height(self.image_width, self.aspect_ratio); + self.center = self.look_from; - let w = look_from.sub(&look_at).unit(); - let u = vup.cross_prod(&w).unit(); - let v = w.cross_prod(&u).unit(); + self.pixel_samples_scale = 1.0 / self.samples_per_pixel as f32; - let samples_per_pixel = SAMPLES_PER_PIXEL; - let pixel_samples_scale = 1.0 / samples_per_pixel as f32; + let theta = deg2rad(self.vfov); + let h = (theta / 2.0).tan(); - let focus_dist = FOCUS_DIST; - let defocus_angle = DEFOCUS_ANGLE; + let w = self.look_from.sub(&self.look_at).unit(); + let u = self.vup.cross_prod(&w).unit(); + let v = w.cross_prod(&u).unit(); - let viewport_height = 2.0 * h * focus_dist; - let viewport_width = viewport_height * (image_width as f32 / image_height as f32); + let viewport_height = 2.0 * h * self.focus_dist; + let viewport_width = viewport_height * (self.image_width as f32 / self.image_height as f32); let viewport_u = u.scalar_mul(viewport_width); let viewport_v = v.scalar_mul(-1.0).scalar_mul(viewport_height); - let delta_pixel_u = viewport_u.scalar_mul(1.0 / image_width as f32); - let delta_pixel_v = viewport_v.scalar_mul(1.0 / image_height as f32); + self.delta_pixel_u = viewport_u.scalar_mul(1.0 / self.image_width as f32); + self.delta_pixel_v = viewport_v.scalar_mul(1.0 / self.image_height as f32); - let viewport_upper_left = center - .sub(&w.scalar_mul(focus_dist)) + let viewport_upper_left = self.center + .sub(&w.scalar_mul(self.focus_dist)) .sub(&viewport_u.scalar_mul(0.5)) .sub(&viewport_v.scalar_mul(0.5)); - let pixel_upper_left = viewport_upper_left.add( - &delta_pixel_u.add(&delta_pixel_v).scalar_mul(0.5) + self.pixel_upper_left = viewport_upper_left.add( + &self.delta_pixel_u.add(&self.delta_pixel_v).scalar_mul(0.5) ); - let defocus_radius = focus_dist * deg2rad(defocus_angle / 2.0).tan(); - let defocus_disk_u = u.scalar_mul(defocus_radius); - let defocus_disk_v = v.scalar_mul(defocus_radius); - - let max_depth = MAX_DEPTH; - - Self { - aspect_ratio, - image_width, - image_height, - center, - pixel_upper_left, - delta_pixel_u, - delta_pixel_v, - samples_per_pixel, - pixel_samples_scale, - max_depth, - vfov, - look_from, - look_at, - vup, - defocus_angle, - focus_dist, - defocus_disk_u, - defocus_disk_v, - } + let defocus_radius = self.focus_dist * deg2rad(self.defocus_angle / 2.0).tan(); + self.defocus_disk_u = u.scalar_mul(defocus_radius); + self.defocus_disk_v = v.scalar_mul(defocus_radius); } -} -impl Camera { fn get_ray(&self, i: usize, j: usize) -> Ray { let offset = sample_square(); let pixel_sample = self.pixel_upper_left |