ft: 12: movable camera + camera init overhaul
This commit is contained in:
141
src/camera.rs
141
src/camera.rs
@@ -1,6 +1,6 @@
|
||||
use std::cmp::max;
|
||||
use std::f32::consts::PI;
|
||||
|
||||
use log::info;
|
||||
use log::{info, warn};
|
||||
|
||||
use crate::{
|
||||
objects::{hit::Hit, traits::Hittable},
|
||||
@@ -8,50 +8,129 @@ use crate::{
|
||||
vec3::{Colour, Vec3},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Camera {
|
||||
// output
|
||||
image_width: u32,
|
||||
image_height: u32,
|
||||
|
||||
// raytracing
|
||||
anti_alias_rate: u32,
|
||||
max_depth: u32,
|
||||
center: Vec3,
|
||||
pixel00_loc: Vec3,
|
||||
pixel_delta_u: Vec3,
|
||||
pixel_delta_v: Vec3,
|
||||
|
||||
// camera
|
||||
dirty: bool,
|
||||
fov: f32,
|
||||
look_from: Vec3,
|
||||
look_at: Vec3,
|
||||
vup: Vec3,
|
||||
|
||||
// camera helpers
|
||||
u: Vec3,
|
||||
v: Vec3,
|
||||
w: Vec3,
|
||||
}
|
||||
|
||||
// FIXME: kinda out of place in this file.
|
||||
fn deg_to_rad(deg: f32) -> f32 {
|
||||
deg * PI / 180.
|
||||
}
|
||||
|
||||
impl Camera {
|
||||
pub fn new(aspect_ratio: f32, image_width: u32, anti_alias_rate: u32, max_depth: u32) -> Self {
|
||||
let image_height = max(1, (image_width as f32 / aspect_ratio) as u32);
|
||||
|
||||
//camera
|
||||
let focal_length = 1.;
|
||||
let viewport_height = 2.;
|
||||
let viewport_width = viewport_height * (image_width as f32 / image_height as f32);
|
||||
let camera_center = Vec3::nil();
|
||||
|
||||
//viewport
|
||||
let viewport_u = Vec3::new(viewport_width as f32, 0., 0.);
|
||||
let viewport_v = Vec3::new(0., -viewport_height as f32, 0.);
|
||||
|
||||
let pixel_delta_u = viewport_u / image_width as f32;
|
||||
let pixel_delta_v = viewport_v / image_height as f32;
|
||||
|
||||
let pixel00_loc =
|
||||
camera_center - Vec3::new(0., 0., focal_length) - viewport_u / 2 - viewport_v / 2;
|
||||
|
||||
pub fn new(image_width: u32, image_height: u32) -> Self {
|
||||
Self {
|
||||
image_width: image_width,
|
||||
image_height: image_height,
|
||||
anti_alias_rate: anti_alias_rate,
|
||||
max_depth: max_depth,
|
||||
center: camera_center,
|
||||
pixel00_loc: pixel00_loc,
|
||||
pixel_delta_u: pixel_delta_u,
|
||||
pixel_delta_v: pixel_delta_v,
|
||||
anti_alias_rate: 1,
|
||||
max_depth: 10,
|
||||
dirty: true,
|
||||
fov: 60.,
|
||||
pixel00_loc: Vec3::nil(),
|
||||
pixel_delta_u: Vec3::nil(),
|
||||
pixel_delta_v: Vec3::nil(),
|
||||
look_from: Vec3::nil(),
|
||||
look_at: Vec3::new(0., 0., -1.),
|
||||
vup: Vec3::new(0., 1., 0.),
|
||||
u: Vec3::nil(),
|
||||
v: Vec3::nil(),
|
||||
w: Vec3::nil(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render<T: Hittable>(&self, hittables: &Vec<T>) {
|
||||
fn init(&mut self) {
|
||||
// camera
|
||||
let focal_length = (self.look_from - self.look_at).length();
|
||||
let theta = deg_to_rad(self.fov);
|
||||
let h = (theta / 2.).tan();
|
||||
self.w = (self.look_from - self.look_at).get_unit();
|
||||
self.u = self.vup.cross(&self.w).get_unit();
|
||||
self.v = self.w.cross(&self.u);
|
||||
|
||||
// viewport
|
||||
let viewport_height = 2. * h * focal_length;
|
||||
let viewport_width = viewport_height * (self.image_width as f32 / self.image_height as f32);
|
||||
let viewport_u = viewport_width * self.u;
|
||||
let viewport_v = viewport_height * -self.v;
|
||||
|
||||
// variables
|
||||
self.pixel_delta_u = viewport_u / self.image_width as f32;
|
||||
self.pixel_delta_v = viewport_v / self.image_height as f32;
|
||||
self.pixel00_loc =
|
||||
self.look_from - (focal_length * self.w) - viewport_u / 2. - viewport_v / 2.;
|
||||
self.dirty = false;
|
||||
}
|
||||
|
||||
pub fn set_fov(&mut self, fov: f32) {
|
||||
if self.fov != fov {
|
||||
self.fov = fov;
|
||||
self.dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_max_depth(&mut self, depth: u32) {
|
||||
if self.max_depth != depth {
|
||||
self.max_depth = depth;
|
||||
self.dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_anti_alias_rate(&mut self, rate: u32) {
|
||||
if self.anti_alias_rate != rate {
|
||||
self.anti_alias_rate = rate;
|
||||
self.dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_look_from(&mut self, look_from: Vec3) {
|
||||
if self.look_from != look_from {
|
||||
self.look_from = look_from;
|
||||
self.dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_look_at(&mut self, look_at: Vec3) {
|
||||
if self.look_at != look_at {
|
||||
self.look_at = look_at;
|
||||
self.dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_vup(&mut self, vup: Vec3) {
|
||||
if self.vup != vup {
|
||||
self.vup = vup;
|
||||
self.dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render<T: Hittable>(&mut self, hittables: &Vec<T>) {
|
||||
if self.dirty {
|
||||
self.init()
|
||||
}
|
||||
warn!("{}", format!("{self:#?}"));
|
||||
|
||||
let mut imgbuf = image::ImageBuffer::new(self.image_width, self.image_height);
|
||||
|
||||
// render
|
||||
@@ -67,8 +146,8 @@ impl Camera {
|
||||
let pixel_loc = pixel_tl
|
||||
+ (x * self.pixel_delta_u / (self.anti_alias_rate + 1) as f32)
|
||||
+ (y * self.pixel_delta_v / (self.anti_alias_rate + 1) as f32);
|
||||
let ray_dir = pixel_loc - self.center;
|
||||
let r = Ray::new(self.center, ray_dir);
|
||||
let ray_dir = pixel_loc - self.look_from;
|
||||
let r = Ray::new(self.look_from, ray_dir);
|
||||
pixel_colour += self.ray_colour(&hittables, &r, self.max_depth);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,12 @@ fn main() {
|
||||
world.push(Sphere::xyz(1., 0., -1.0, 0.5, right.clone()));
|
||||
world.push(Sphere::xyz(0., 0.7, -0.4, 0.2, blue.clone()));
|
||||
|
||||
let c = Camera::new(16. / 9., 1920, 3, 50);
|
||||
let mut c = Camera::new(400, 300);
|
||||
// let mut c = Camera::new(1920, 1080);
|
||||
c.set_fov(20.);
|
||||
c.set_anti_alias_rate(2);
|
||||
c.set_max_depth(90);
|
||||
c.set_look_from(Vec3::new(-2., 2., 1.));
|
||||
c.set_look_at(Vec3::new(0., 0., -1.));
|
||||
c.render(&world);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ use std::{
|
||||
ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign},
|
||||
};
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Vec3 {
|
||||
r: f32,
|
||||
g: f32,
|
||||
|
||||
Reference in New Issue
Block a user