From b68462f1f76569db699d43eaa7923a0186ebfc0c Mon Sep 17 00:00:00 2001 From: Alan Jian Date: Wed, 17 Jul 2024 15:01:13 +0800 Subject: [PATCH] feat: add Camera struct --- src/camera.rs | 38 ++++++++++++++++++++++++++++++++++++++ src/main.rs | 19 +++++-------------- 2 files changed, 43 insertions(+), 14 deletions(-) create mode 100644 src/camera.rs diff --git a/src/camera.rs b/src/camera.rs new file mode 100644 index 0000000..fba21b4 --- /dev/null +++ b/src/camera.rs @@ -0,0 +1,38 @@ +use crate::Ray; +use nalgebra::{Point2, Point3, Vector3}; + +pub struct Camera { + pos: Point3, + pix_orig: Point3, + pix_delta_x: Vector3, + pix_delta_y: Vector3, +} + +impl Camera { + pub fn new(pos: Point3, width: u32, height: u32, focal_len: f64) -> Self { + let aspect_ratio = width as f64 / height as f64; + let viewport_height = 2.0; + let viewport_width = viewport_height * aspect_ratio; + + let pix_delta_x = Vector3::new(viewport_width, 0.0, 0.0) / width as f64; + let pix_delta_y = Vector3::new(0.0, -viewport_height, 0.0) / height as f64; + let pix_orig = pos + + Vector3::new(0.0, 0.0, -focal_len) - + width as f64 / 2.0 * pix_delta_x - + height as f64 / 2.0 * pix_delta_y; + + Camera { + pos, + pix_orig, + pix_delta_x, + pix_delta_y, + } + } + + pub fn generate_ray(&self, p: Point2) -> Ray { + let pix_pos = self.pix_orig + p.x as f64 * self.pix_delta_x + p.y as f64 * self.pix_delta_y; + let dir = pix_pos - self.pos; + + Ray::new(self.pos, dir) + } +} diff --git a/src/main.rs b/src/main.rs index 8786874..7021153 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,13 +1,15 @@ mod cli; mod core; +mod camera; use clap::Parser; use cli::{Cli, Size}; use core::Ray; use image::{Rgb, RgbImage}; use indicatif::ProgressBar; -use nalgebra::{Point3, Vector3}; +use nalgebra::{Point2, Point3, Vector3}; use palette::{LinSrgb, Srgb}; +use camera::Camera; fn hit_sphere(center: Point3, radius: f64, ray: &Ray) -> Option { let a = ray.dir.magnitude_squared(); @@ -40,22 +42,11 @@ fn main() { let mut image = RgbImage::new(width, height); let progress_bar = ProgressBar::new(height as u64); - let camera_pos = Point3::new(0.0, 0.0, 0.0); - let camera_focal_len = 1.0; - - let viewport_height = 2.0; - let viewport_width = viewport_height * (width as f64 / height as f64); - - let pixel_delta_x = Vector3::new(viewport_width, 0.0, 0.0) / width as f64; - let pixel_delta_y = Vector3::new(0.0, -viewport_height, 0.0) / height as f64; - let pixel_pos_orig = camera_pos + Vector3::new(0.0, 0.0, -camera_focal_len) - - width as f64 / 2.0 * pixel_delta_x - - height as f64 / 2.0 * pixel_delta_y; + let camera = Camera::new(Point3::new(0.0, 0.0, 0.0), width, height, 1.0); for y in 0..height { for x in 0..width { - let pixel_pos = pixel_pos_orig + x as f64 * pixel_delta_x + y as f64 * pixel_delta_y; - let ray = Ray::new(camera_pos, pixel_pos - camera_pos); + let ray = camera.generate_ray(Point2::new(x, y)); let color: Srgb = Srgb::from_linear(ray_color(&ray)); let r = (255.999 * color.red) as u8;