rust_tracer/
camera.rs

1use rand::rngs::ThreadRng;
2
3use crate::{
4    math::{Point3, Ray, Vector3},
5    utils::random_in_unit_disk,
6};
7
8pub struct Camera {
9    origin: Point3,
10    lower_left_corner: Point3,
11    horizontal: Vector3,
12    vertical: Vector3,
13    u: Vector3,
14    v: Vector3,
15    lens_radius: f64,
16    pub aspect_ratio: f64,
17}
18
19impl Camera {
20    pub fn new(
21        lookfrom: Point3,
22        lookat: Point3,
23        vup: Vector3,
24        vfov: f64,
25        aspect_ratio: f64,
26        apeture: f64,
27        focus_dist: f64,
28    ) -> Self {
29        let viewport_height = 2.0 * (vfov.to_radians() / 2.0).tan();
30        let viewport_width = aspect_ratio * viewport_height;
31
32        let w = (lookfrom - lookat).unit_vector();
33        let u = Vector3::cross(&vup, &w).unit_vector();
34        let v = Vector3::cross(&w, &u);
35
36        let origin = lookfrom;
37        let horizontal = focus_dist * viewport_width * u;
38        let vertical = focus_dist * viewport_height * v;
39
40        let lens_radius = apeture / 2.0;
41
42        Camera {
43            origin,
44            horizontal,
45            vertical,
46            lower_left_corner: origin - horizontal / 2.0 - vertical / 2.0 - focus_dist * w,
47            aspect_ratio,
48            u,
49            v,
50            lens_radius,
51        }
52    }
53
54    pub fn ray(&self, s: f64, t: f64, rng: &mut ThreadRng) -> Ray {
55        let focus_disk = self.lens_radius * random_in_unit_disk(rng);
56        let offset = self.u * focus_disk.x() + self.v * focus_disk.y();
57
58        Ray::new(
59            self.origin + offset,
60            self.lower_left_corner + s * self.horizontal + t * self.vertical - self.origin - offset,
61        )
62    }
63}