93 lines
2.2 KiB
Rust
93 lines
2.2 KiB
Rust
use rand::Rng;
|
|
|
|
use crate::{Point3, Ray, Vec3};
|
|
|
|
pub struct Camera {
|
|
aspect_ratio: f64,
|
|
viewport_height: f64,
|
|
viewport_width: f64,
|
|
origin: Point3,
|
|
horizontal: Vec3,
|
|
vertical: Vec3,
|
|
lower_left_corner: Vec3,
|
|
lens_radius: f64,
|
|
u: Vec3,
|
|
v: Vec3,
|
|
w: Vec3,
|
|
time0: f64,
|
|
time1: f64
|
|
}
|
|
|
|
impl Camera {
|
|
pub fn get_ray(&self, s: f64, t: f64) -> Ray {
|
|
let rd = self.lens_radius * Vec3::random_unit_disk();
|
|
let offset = self.u * rd.x() + self.v * rd.y();
|
|
let time = rand::thread_rng().gen_range(self.time0..self.time1);
|
|
Ray::new(
|
|
self.origin + offset,
|
|
self.lower_left_corner + s*self.horizontal + t*self.vertical - self.origin - offset,
|
|
time)
|
|
}
|
|
pub fn still(
|
|
look_from: Point3,
|
|
look_at: Point3,
|
|
up: Vec3,
|
|
aspect_ratio: f64,
|
|
vfov: f64,
|
|
aperture: f64,
|
|
focus_dist: f64) -> Self {
|
|
|
|
Camera::new(
|
|
look_from,
|
|
look_at,
|
|
up,
|
|
aspect_ratio,
|
|
vfov,
|
|
aperture,
|
|
focus_dist,
|
|
0.0,
|
|
0.0)
|
|
}
|
|
|
|
pub fn new(
|
|
look_from: Point3,
|
|
look_at: Point3,
|
|
up: Vec3,
|
|
aspect_ratio: f64,
|
|
vfov: f64,
|
|
aperture: f64,
|
|
focus_dist: f64,
|
|
time0: f64,
|
|
time1: f64) -> Self {
|
|
|
|
let theta = vfov.to_radians();
|
|
let h = (theta / 2.0).tan();
|
|
let viewport_height = 2.0 * h;
|
|
let viewport_width = aspect_ratio * viewport_height;
|
|
|
|
let w = (look_from - look_at).unit_vector();
|
|
let u = up.cross(&w).unit_vector();
|
|
let v = w.cross(&u);
|
|
|
|
let horizontal = focus_dist * viewport_width * u;
|
|
let vertical = focus_dist * viewport_height * v;
|
|
Camera {
|
|
aspect_ratio,
|
|
viewport_height,
|
|
viewport_width,
|
|
origin: look_from,
|
|
horizontal,
|
|
vertical,
|
|
lower_left_corner: look_from - horizontal/2.0 - vertical/2.0 - focus_dist*w,
|
|
lens_radius: aperture / 2.0,
|
|
u,
|
|
v,
|
|
w,
|
|
time0,
|
|
time1
|
|
}
|
|
}
|
|
|
|
pub fn aspect_ratio(&self) -> f64 { self.aspect_ratio }
|
|
}
|