diff options
author | Rosyid Haryadi <rosyid_haryadi@protonmail.com> | 2025-03-03 02:49:39 +0700 |
---|---|---|
committer | Rosyid Haryadi <rosyid_haryadi@protonmail.com> | 2025-03-03 02:49:39 +0700 |
commit | 8eec1dd60e966f068cd62fba87ca5dbc1aeb1978 (patch) | |
tree | 31f57a20fb600dd8fb3c328d65560d658ff38582 | |
parent | 988a418f8907fb5e3abb77222929d6ab7b60c1b6 (diff) |
upd camera field of view
-rw-r--r-- | src/camera.rs | 43 | ||||
-rw-r--r-- | src/common.rs | 11 | ||||
-rw-r--r-- | src/main.rs | 2 |
3 files changed, 41 insertions, 15 deletions
diff --git a/src/camera.rs b/src/camera.rs index 1f211de..033f962 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -1,5 +1,5 @@ -use crate::calculus::calculus::{sample_square, Point3, Ray, Vec3}; -use crate::common::{get_image_height, Color, DisplayBuffer, Pixel, ASPECT_RATIO, CAMERA_CENTER, FOCAL_LENGTH, IMG_WIDTH, MAX_DEPTH, SAMPLES_PER_PIXEL, VIEWPORT_HEIGHT}; +use crate::calculus::calculus::{deg2rad, sample_square, Point3, Ray, Vec3}; +use crate::common::{get_image_height, Color, DisplayBuffer, Pixel, ASPECT_RATIO, CAMERA_CENTER, FOCAL_LENGTH, IMG_WIDTH, LOOK_AT, LOOK_FROM, MAX_DEPTH, SAMPLES_PER_PIXEL, VFOV, VIEWPORT_HEIGHT, VUP}; use crate::interval::Interval; use crate::material::{Material, MaterialType}; use crate::object::{HitRecord, Hittable, HittableList}; @@ -8,6 +8,10 @@ pub struct Camera { pub aspect_ratio: f32, pub image_width: usize, pub samples_per_pixel: usize, + pub vfov: f32, + pub look_from: Point3, + pub look_at: Point3, + pub vup: Vec3, image_height: usize, center: Point3, pixel_upper_left: Point3, @@ -17,30 +21,41 @@ pub struct Camera { max_depth: usize, } -impl Camera { - pub fn new() -> Self { +impl Default for Camera { + fn default() -> Self { let aspect_ratio = ASPECT_RATIO; let image_width = IMG_WIDTH; let image_height = get_image_height(image_width, aspect_ratio); - let center = CAMERA_CENTER; - let focal_length = FOCAL_LENGTH; + let vfov = VFOV; + let look_from = LOOK_FROM; + let look_at = LOOK_AT; + let vup = VUP; + + let center = look_from; + let focal_length = look_from.sub(&look_at).mag(); + let theta = deg2rad(vfov); + let h = (theta / 2.0).tan(); + + let w = look_from.sub(&look_at).unit(); + let u = vup.cross_prod(&w).unit(); + let v = w.cross_prod(&u).unit(); let samples_per_pixel = SAMPLES_PER_PIXEL; let pixel_samples_scale = 1.0 / samples_per_pixel as f32; - let viewport_height = VIEWPORT_HEIGHT; + let viewport_height = 2.0 * h * focal_length; let viewport_width = viewport_height * (image_width as f32 / image_height as f32); - let viewport_hor_vector = Vec3{ x: viewport_width, y: 0.0, z: 0.0 }; - let viewport_ver_vector = Vec3 { x: 0.0, y: -1f32 * viewport_height, z: 0.0 }; + let viewport_hor_vector = u.scalar_mul(viewport_height); + let viewport_ver_vector = v.scalar_mul(-1.0 * viewport_width); let delta_pixel_u = viewport_hor_vector.scalar_mul(1.0 / image_width as f32); let delta_pixel_v = viewport_ver_vector.scalar_mul(1.0 / image_height as f32); let viewport_upper_left = center - .sub(&Vec3 { x: 0f32, y: 0f32, z: focal_length}) + .sub(&w.scalar_mul(focal_length)) .sub(&viewport_hor_vector.scalar_mul(0.5)) .sub(&viewport_ver_vector.scalar_mul(0.5)); let pixel_upper_left = viewport_upper_left.add( @@ -59,10 +74,16 @@ impl Camera { delta_pixel_v, samples_per_pixel, pixel_samples_scale, - max_depth + max_depth, + vfov, + look_from, + look_at, + vup, } } +} +impl Camera { fn get_ray(&self, i: usize, j: usize) -> Ray { let offset = sample_square(); let pixel_sample = self.pixel_upper_left diff --git a/src/common.rs b/src/common.rs index 120d8b4..75bf600 100644 --- a/src/common.rs +++ b/src/common.rs @@ -1,18 +1,23 @@ -use crate::calculus::calculus::Point3; +use crate::calculus::calculus::{Point3, Vec3}; use crate::interval::Interval; // "Ideal" aspect ratio, allowing fraction -pub const ASPECT_RATIO: f32 = 16.0f32 / 9.0f32; +pub const ASPECT_RATIO: f32 = 16.0 / 9.0; pub const IMG_WIDTH: usize = 400; pub const IMG_HEIGHT: usize = get_image_height(IMG_WIDTH, ASPECT_RATIO); pub const VIEWPORT_HEIGHT: f32 = 2.0; pub const FOCAL_LENGTH: f32 = 1.0; -pub const CAMERA_CENTER: Point3 = Point3 { x: 0f32, y: 0f32, z: 0f32 }; +pub const CAMERA_CENTER: Point3 = Point3 { x: 0.0, y: 0.0, z: 0.0 }; pub const SAMPLES_PER_PIXEL: usize = 100; pub const MAX_DEPTH: usize = 50; +pub const VFOV: f32 = 90.0; +pub const LOOK_FROM: Point3 = Point3 { x: -2.0, y: -2.0, z: 1.0 }; +pub const LOOK_AT: Point3 = Point3 { x: 0.0, y: 0.0, z: -1.0 }; +pub const VUP: Vec3 = Vec3 { x: 0.0, y: 1.0, z: 0.0 }; + pub const fn get_image_height(image_width: usize, aspect_ratio: f32) -> usize { let image_height = (image_width as f32 / aspect_ratio) as usize; if image_width < 1 { 1 } else { image_height } diff --git a/src/main.rs b/src/main.rs index 5772ffb..b33664e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -37,7 +37,7 @@ fn main() { Sphere::new(Point3::new(1.0, 0.0, -1.0), 0.5, steel) ); - let camera = Camera::new(); + let camera = Camera::default(); // test_render(&mut display_buffer); camera.render(&mut display_buffer, &world); |