summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRosyid Haryadi <rosyid_haryadi@protonmail.com>2025-03-03 02:49:39 +0700
committerRosyid Haryadi <rosyid_haryadi@protonmail.com>2025-03-03 02:49:39 +0700
commit8eec1dd60e966f068cd62fba87ca5dbc1aeb1978 (patch)
tree31f57a20fb600dd8fb3c328d65560d658ff38582
parent988a418f8907fb5e3abb77222929d6ab7b60c1b6 (diff)
upd camera field of view
-rw-r--r--src/camera.rs43
-rw-r--r--src/common.rs11
-rw-r--r--src/main.rs2
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);