Implemented a Camera type.
This commit is contained in:
parent
108bddd712
commit
7c5c2e4308
113
src/camera.rs
Normal file
113
src/camera.rs
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
use std::f32::consts::FRAC_PI_4;
|
||||||
|
|
||||||
|
use math::{Vector, Point, Matrix4x4};
|
||||||
|
use ray::Ray;
|
||||||
|
use lerp::lerp_slice;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Camera {
|
||||||
|
transforms: Vec<Matrix4x4>,
|
||||||
|
fovs: Vec<f32>,
|
||||||
|
tfovs: Vec<f32>,
|
||||||
|
aperture_radii: Vec<f32>,
|
||||||
|
focus_distances: Vec<f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Camera {
|
||||||
|
pub fn new(transforms: Vec<Matrix4x4>,
|
||||||
|
fovs: Vec<f32>,
|
||||||
|
mut aperture_radii: Vec<f32>,
|
||||||
|
mut focus_distances: Vec<f32>)
|
||||||
|
-> Camera {
|
||||||
|
assert!(transforms.len() != 0, "Camera has no transform(s)!");
|
||||||
|
assert!(fovs.len() != 0, "Camera has no fov(s)!");
|
||||||
|
|
||||||
|
// Aperture needs focus distance and vice-versa.
|
||||||
|
if aperture_radii.len() == 0 || focus_distances.len() == 0 {
|
||||||
|
aperture_radii = vec![0.0];
|
||||||
|
focus_distances = vec![1.0];
|
||||||
|
|
||||||
|
if aperture_radii.len() == 0 && focus_distances.len() != 0 {
|
||||||
|
println!("WARNING: camera has aperture radius but no focus distance. Disabling \
|
||||||
|
focal blur.");
|
||||||
|
} else if aperture_radii.len() != 0 && focus_distances.len() == 0 {
|
||||||
|
println!("WARNING: camera has focus distance but no aperture radius. Disabling \
|
||||||
|
focal blur.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Can't have focus distance of zero.
|
||||||
|
if focus_distances.iter().any(|d| *d == 0.0) {
|
||||||
|
println!("WARNING: camera focal distance is zero or less. Disabling focal blur.");
|
||||||
|
aperture_radii = vec![0.0];
|
||||||
|
focus_distances = vec![1.0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert angle fov into linear fov.
|
||||||
|
let tfovs = fovs.iter().map(|n| (n / 2.0).sin() / (n / 2.0).cos()).collect();
|
||||||
|
|
||||||
|
Camera {
|
||||||
|
transforms: transforms,
|
||||||
|
fovs: fovs,
|
||||||
|
tfovs: tfovs,
|
||||||
|
aperture_radii: aperture_radii,
|
||||||
|
focus_distances: focus_distances,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generate_ray(&self, x: f32, y: f32, time: f32, u: f32, v: f32) -> Ray {
|
||||||
|
// Get time-interpolated camera settings
|
||||||
|
let transform = lerp_slice(&self.transforms, time);
|
||||||
|
let tfov = lerp_slice(&self.tfovs, time);
|
||||||
|
let aperture_radius = lerp_slice(&self.aperture_radii, time);
|
||||||
|
let focus_distance = lerp_slice(&self.focus_distances, time);
|
||||||
|
|
||||||
|
// Ray origin
|
||||||
|
let orig = {
|
||||||
|
let (u, v) = square_to_circle(aperture_radius * ((u * 2.0) - 1.0),
|
||||||
|
aperture_radius * ((v * 2.0) - 1.0));
|
||||||
|
Point::new(u, v, 0.0)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Ray direction
|
||||||
|
let dir = Vector::new((x * tfov) - (orig[0] / focus_distance),
|
||||||
|
(y * tfov) - (orig[1] / focus_distance),
|
||||||
|
1.0)
|
||||||
|
.normalized();
|
||||||
|
|
||||||
|
Ray::new(orig * transform, dir * transform, time)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Maps the unit square to the unit circle.
|
||||||
|
/// NOTE: x and y should be distributed within [-1, 1],
|
||||||
|
/// not [0, 1].
|
||||||
|
fn square_to_circle(x: f32, y: f32) -> (f32, f32) {
|
||||||
|
debug_assert!(x >= -1.0 && x <= 1.0);
|
||||||
|
debug_assert!(y >= -1.0 && y <= 1.0);
|
||||||
|
|
||||||
|
if x == 0.0 && y == 0.0 {
|
||||||
|
return (0.0, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
let (radius, angle) = {
|
||||||
|
if x > y.abs() {
|
||||||
|
// Quadrant 1
|
||||||
|
(x, (y / x) * FRAC_PI_4)
|
||||||
|
} else if y > x.abs() {
|
||||||
|
// Quadrant 2
|
||||||
|
(y, (2.0 - (x / y)) * FRAC_PI_4)
|
||||||
|
} else if x < -(y.abs()) {
|
||||||
|
// Quadrant 3
|
||||||
|
(-x, (4.0 + (y / x)) * FRAC_PI_4)
|
||||||
|
} else {
|
||||||
|
// Quadrant 4
|
||||||
|
(-y, (6.0 - (x / y)) * FRAC_PI_4)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (radius * angle.cos(), radius * angle.sin());
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ mod lerp;
|
||||||
mod float4;
|
mod float4;
|
||||||
mod ray;
|
mod ray;
|
||||||
mod bbox;
|
mod bbox;
|
||||||
|
mod camera;
|
||||||
mod data_tree;
|
mod data_tree;
|
||||||
mod image;
|
mod image;
|
||||||
mod triangle;
|
mod triangle;
|
||||||
|
@ -95,6 +96,9 @@ fn main() {
|
||||||
let cx = halton::sample(0, i) * 512.0;
|
let cx = halton::sample(0, i) * 512.0;
|
||||||
let cy = halton::sample(1, i) * 512.0;
|
let cy = halton::sample(1, i) * 512.0;
|
||||||
let cz = halton::sample(2, i) * 512.0;
|
let cz = halton::sample(2, i) * 512.0;
|
||||||
|
// let cx = x as f32 * xinc;
|
||||||
|
// let cy = y as f32 * yinc;
|
||||||
|
// let cz = 1.0;
|
||||||
triangles.push((Point::new(cx, cy, cz + 1.0),
|
triangles.push((Point::new(cx, cy, cz + 1.0),
|
||||||
Point::new(cx + xinc, cy, cz + 1.1),
|
Point::new(cx + xinc, cy, cz + 1.1),
|
||||||
Point::new(cx, cy + yinc, cz + 1.2)));
|
Point::new(cx, cy + yinc, cz + 1.2)));
|
||||||
|
@ -137,7 +141,8 @@ fn main() {
|
||||||
offset + si as u32),
|
offset + si as u32),
|
||||||
1.5),
|
1.5),
|
||||||
0.0),
|
0.0),
|
||||||
Vector::new(0.0, 0.0, 1.0));
|
Vector::new(0.0, 0.0, 1.0),
|
||||||
|
0.0);
|
||||||
ray.id = si as u32;
|
ray.id = si as u32;
|
||||||
rays.push(ray);
|
rays.push(ray);
|
||||||
isects.push((false, 0.0, 0.0));
|
isects.push((false, 0.0, 0.0));
|
||||||
|
|
|
@ -17,13 +17,13 @@ pub struct Ray {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ray {
|
impl Ray {
|
||||||
pub fn new(orig: Point, dir: Vector) -> Ray {
|
pub fn new(orig: Point, dir: Vector, time: f32) -> Ray {
|
||||||
Ray {
|
Ray {
|
||||||
orig: orig,
|
orig: orig,
|
||||||
dir: dir,
|
dir: dir,
|
||||||
dir_inv: Vector { co: Float4::new(1.0, 1.0, 1.0, 1.0) / dir.co },
|
dir_inv: Vector { co: Float4::new(1.0, 1.0, 1.0, 1.0) / dir.co },
|
||||||
max_t: std::f32::INFINITY,
|
max_t: std::f32::INFINITY,
|
||||||
time: 0.0,
|
time: time,
|
||||||
id: 0,
|
id: 0,
|
||||||
flags: 0,
|
flags: 0,
|
||||||
}
|
}
|
||||||
|
@ -32,5 +32,6 @@ impl Ray {
|
||||||
pub fn transform(&mut self, mat: &Matrix4x4) {
|
pub fn transform(&mut self, mat: &Matrix4x4) {
|
||||||
self.orig = self.orig * *mat;
|
self.orig = self.orig * *mat;
|
||||||
self.dir = self.dir * *mat;
|
self.dir = self.dir * *mat;
|
||||||
|
self.dir_inv = Vector { co: Float4::new(1.0, 1.0, 1.0, 1.0) / self.dir.co };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user