88 lines
2.3 KiB
Rust
88 lines
2.3 KiB
Rust
extern crate rand;
|
|
use std::f32::consts::PI;
|
|
|
|
use self::rand::Rng;
|
|
|
|
use crate::ray::Ray;
|
|
use crate::vec3::cross;
|
|
use crate::vec3::Vec3;
|
|
|
|
fn random_in_unit_disk() -> Vec3 {
|
|
let mut rng = rand::thread_rng();
|
|
let v = Vec3::new(1., 1., 0.);
|
|
loop {
|
|
let p =
|
|
2. * Vec3::new(
|
|
rng.gen_range::<f32>(0., 1.),
|
|
rng.gen_range::<f32>(0., 1.),
|
|
0.,
|
|
) - v;
|
|
if p.squared_length() < 1. {
|
|
return p;
|
|
}
|
|
}
|
|
}
|
|
|
|
pub struct Camera {
|
|
origin: Vec3,
|
|
lower_left_corner: Vec3,
|
|
horizontal: Vec3,
|
|
vertical: Vec3,
|
|
u: Vec3,
|
|
v: Vec3,
|
|
lens_radius: f32,
|
|
time_min: f32,
|
|
time_max: f32,
|
|
}
|
|
|
|
impl Camera {
|
|
// Parameters match the example C++ code.
|
|
#[allow(clippy::too_many_arguments)]
|
|
// vfov is top to bottom in degrees
|
|
pub fn new(
|
|
lookfrom: Vec3,
|
|
lookat: Vec3,
|
|
vup: Vec3,
|
|
vfov: f32,
|
|
aspect: f32,
|
|
aperture: f32,
|
|
focus_dist: f32,
|
|
time_min: f32,
|
|
time_max: f32,
|
|
) -> Camera {
|
|
let theta = vfov * PI / 180.;
|
|
let half_height = (theta / 2.).tan();
|
|
let half_width = aspect * half_height;
|
|
let origin = lookfrom;
|
|
let w = (lookfrom - lookat).unit_vector();
|
|
let u = cross(vup, w).unit_vector();
|
|
let v = cross(w, u);
|
|
Camera {
|
|
lower_left_corner: origin
|
|
- half_width * focus_dist * u
|
|
- half_height * focus_dist * v
|
|
- focus_dist * w,
|
|
horizontal: 2. * half_width * focus_dist * u,
|
|
vertical: 2. * half_height * focus_dist * v,
|
|
origin,
|
|
u: cross(vup, w).unit_vector(),
|
|
v: cross(w, u),
|
|
lens_radius: aperture / 2.,
|
|
time_min,
|
|
time_max,
|
|
}
|
|
}
|
|
|
|
pub fn get_ray(&self, u: f32, v: f32) -> Ray {
|
|
let mut rng = rand::thread_rng();
|
|
let rd = self.lens_radius * random_in_unit_disk();
|
|
let offset = self.u * rd.x + self.v * rd.y;
|
|
let time = self.time_min + rng.gen_range::<f32>(0., 1.) * (self.time_max - self.time_min);
|
|
Ray::new(
|
|
self.origin + offset,
|
|
self.lower_left_corner + self.horizontal * u + self.vertical * v - self.origin - offset,
|
|
time,
|
|
)
|
|
}
|
|
}
|