diff options
| author | Sakarias Johansson <sakarias.johansson@goodbyekansas.com> | 2023-04-16 14:32:42 +0200 |
|---|---|---|
| committer | Sakarias Johansson <sakariasjohansson@hotmail.com> | 2023-04-16 15:03:31 +0200 |
| commit | c7cbd0d288083ad7ae132ac6627cf93ec5b3aed5 (patch) | |
| tree | 421da75f8beae04ebfd42b1abb10810ab6eafa55 /racer-tracer/src | |
| parent | 8201c8e2a7ff85383ff7606513778253aae7e666 (diff) | |
| download | racer-tracer-c7cbd0d288083ad7ae132ac6627cf93ec5b3aed5.tar.gz racer-tracer-c7cbd0d288083ad7ae132ac6627cf93ec5b3aed5.tar.xz racer-tracer-c7cbd0d288083ad7ae132ac6627cf93ec5b3aed5.zip | |
✨ Add support for camera configuration
Also decided to not use glam and just do the math myself.
Just didn't want an entire library for such a small thing.
Probably goint to replace Vec3 at some point, just not now.
Diffstat (limited to 'racer-tracer/src')
| -rw-r--r-- | racer-tracer/src/camera.rs | 98 | ||||
| -rw-r--r-- | racer-tracer/src/config.rs | 87 | ||||
| -rw-r--r-- | racer-tracer/src/main.rs | 20 | ||||
| -rw-r--r-- | racer-tracer/src/vec3.rs | 48 |
4 files changed, 165 insertions, 88 deletions
diff --git a/racer-tracer/src/camera.rs b/racer-tracer/src/camera.rs index 1ac2396..438c18d 100644 --- a/racer-tracer/src/camera.rs +++ b/racer-tracer/src/camera.rs @@ -1,5 +1,4 @@ -use glam::{f32::Vec3 as FVec3, Quat}; - +use crate::config::CameraConfig; use crate::image::Image; use crate::ray::Ray; use crate::util::{degrees_to_radians, random_in_unit_disk}; @@ -19,6 +18,7 @@ pub struct Camera { pub scene_up: Vec3, pub lens_radius: f64, pub focus_distance: f64, + pub aspect_ratio: f64, } impl Camera { @@ -56,9 +56,36 @@ impl Camera { scene_up, lens_radius: aperture * 0.5, focus_distance, + aspect_ratio: image.aspect_ratio, } } + pub fn set_pos(&mut self, pos: Vec3) { + self.origin = pos; + self.update_corner(); + } + + pub fn set_look_at(&mut self, look_at: Vec3) { + self.forward = (self.origin - look_at).unit_vector(); + self.update_directions(); + } + + pub fn set_fov(&mut self, vfov: f64) { + let h = (degrees_to_radians(vfov) / 2.0).tan(); + self.viewport_height = 2.0 * h; + self.viewport_width = self.aspect_ratio * self.viewport_height; + self.update_viewport(); + } + + pub fn set_aperture(&mut self, aperture: f64) { + self.lens_radius = aperture * 0.5; + } + + pub fn set_focus_distance(&mut self, focus_distance: f64) { + self.focus_distance = focus_distance; + self.update_viewport(); + } + pub fn get_ray(&self, u: f64, v: f64) -> Ray { let ray_direction = self.lens_radius * random_in_unit_disk(); let offset = self.right * ray_direction.x() + self.up * ray_direction.y(); @@ -78,48 +105,53 @@ impl Camera { self.update_corner() } - fn update_corner(&mut self) { - self.upper_left_corner = self.origin + self.vertical / 2.0 - - self.horizontal / 2.0 - - self.focus_distance * self.forward; + pub fn rotate(&mut self, right_move: f64, up_move: f64) { + self.forward.rotate(up_move, &self.right); + self.forward.rotate(right_move, &self.scene_up); + self.update_directions(); + self.update_corner(); + } + + pub fn rotate_up(&mut self, degrees: f64) { + self.forward.rotate(degrees, &self.right); + self.update_directions(); + } + + pub fn rotate_right(&mut self, degrees: f64) { + self.forward.rotate(degrees, &self.scene_up); + self.update_directions(); } fn update_directions(&mut self) { self.forward.unit_vector(); self.right = self.scene_up.cross(&self.forward).unit_vector(); self.up = self.forward.cross(&self.right); - self.horizontal = self.focus_distance * self.viewport_width * self.right; - self.vertical = self.focus_distance * self.viewport_height * self.up; + self.update_viewport(); } - pub fn rotate(&mut self, up: f64, right: f64) { - self.forward = (Quat::from_axis_angle(self.right.into(), right as f32) - * Quat::from_axis_angle(self.scene_up.into(), up as f32) - * FVec3::from(self.forward)) - .into(); - - self.forward.unit_vector(); - self.update_directions(); - self.update_corner(); + fn update_viewport(&mut self) { + self.horizontal = self.focus_distance * self.viewport_width * self.right; + self.vertical = self.focus_distance * self.viewport_height * self.up; + self.update_corner() } - pub fn rotate_up(&mut self, go: f64) { - self.forward = (Quat::from_axis_angle(self.right.into(), go as f32) - * FVec3::from(self.forward)) - .into(); - - self.forward.unit_vector(); - self.update_directions(); - self.update_corner(); + fn update_corner(&mut self) { + self.upper_left_corner = self.origin + self.vertical / 2.0 + - self.horizontal / 2.0 + - self.focus_distance * self.forward; } +} - pub fn rotate_right(&mut self, go: f64) { - self.forward = (Quat::from_axis_angle(self.scene_up.into(), -go as f32) - * FVec3::from(self.forward)) - .into(); - - self.forward.unit_vector(); - self.update_directions(); - self.update_corner(); +impl From<(&Image, &CameraConfig)> for Camera { + fn from((image, c): (&Image, &CameraConfig)) -> Self { + Self::new( + c.pos, + c.look_at, + Vec3::new(0.0, 1.0, 0.0), + c.vfov, + image, + c.aperture, + c.focus_distance, + ) } } diff --git a/racer-tracer/src/config.rs b/racer-tracer/src/config.rs index 7d28ebe..58e9147 100644 --- a/racer-tracer/src/config.rs +++ b/racer-tracer/src/config.rs @@ -4,22 +4,7 @@ use config::File; use serde::Deserialize; use structopt::StructOpt; -use crate::error::TracerError; - -#[derive(Default, Clone, Debug, Deserialize)] -pub struct Screen { - pub height: usize, - pub width: usize, -} - -#[derive(Default, Clone, Debug, Deserialize)] -pub struct RenderConfigData { - pub samples: usize, - pub max_depth: usize, - pub num_threads_width: usize, - pub num_threads_height: usize, - pub scale: usize, -} +use crate::{error::TracerError, vec3::Vec3}; #[derive(StructOpt, Debug)] #[structopt(name = "racer-tracer")] @@ -76,6 +61,69 @@ impl TryFrom<Args> for Config { } } +#[derive(Default, Clone, Debug, Deserialize)] +pub struct Screen { + pub height: usize, + pub width: usize, +} + +#[derive(Default, Clone, Debug, Deserialize)] +pub struct RenderConfigData { + pub samples: usize, + pub max_depth: usize, + pub num_threads_width: usize, + pub num_threads_height: usize, + pub scale: usize, +} + +#[derive(Clone, Debug, Deserialize)] +pub struct CameraConfig { + #[serde(default = "CameraConfig::default_vfov")] + pub vfov: f64, + + #[serde(default = "CameraConfig::default_aperture")] + pub aperture: f64, + + #[serde(default = "CameraConfig::default_focus_distance")] + pub focus_distance: f64, + + #[serde(default = "CameraConfig::default_pos")] + pub pos: Vec3, + + #[serde(default)] + pub look_at: Vec3, +} + +impl CameraConfig { + fn default_vfov() -> f64 { + 20.0 + } + + fn default_aperture() -> f64 { + 0.1 + } + + fn default_focus_distance() -> f64 { + 10.0 + } + + fn default_pos() -> Vec3 { + Vec3::new(0.0, 2.0, 10.0) + } +} + +impl Default for CameraConfig { + fn default() -> Self { + Self { + vfov: CameraConfig::default_vfov(), + aperture: CameraConfig::default_aperture(), + focus_distance: CameraConfig::default_focus_distance(), + pos: CameraConfig::default_pos(), + look_at: Vec3::default(), + } + } +} + #[derive(StructOpt, Debug, Clone, Deserialize, Default)] pub enum SceneLoader { #[default] @@ -106,7 +154,7 @@ pub enum Renderer { CpuPreview, } -fn default_preview_renderer() -> Renderer { +fn default_preview() -> Renderer { Renderer::CpuPreview } @@ -148,8 +196,11 @@ pub struct Config { #[serde(default)] pub renderer: Renderer, - #[serde(default = "default_preview_renderer")] + #[serde(default = "default_preview")] pub preview_renderer: Renderer, + + #[serde(default)] + pub camera: CameraConfig, } impl Config { diff --git a/racer-tracer/src/main.rs b/racer-tracer/src/main.rs index afdc919..16fe6c4 100644 --- a/racer-tracer/src/main.rs +++ b/racer-tracer/src/main.rs @@ -35,10 +35,7 @@ use structopt::StructOpt; use synchronoise::SignalEvent; use terminal::Terminal; -use crate::{ - scene_controller::{interactive::InteractiveScene, SceneController, SceneData}, - vec3::Vec3, -}; +use crate::scene_controller::{interactive::InteractiveScene, SceneController, SceneData}; use crate::{ camera::Camera, @@ -51,20 +48,7 @@ use crate::{ fn run(config: Config, log: Logger, term: Terminal) -> Result<(), TracerError> { info!(log, "Starting racer-tracer {}", env!("CARGO_PKG_VERSION")); let image = image::Image::new(config.screen.width, config.screen.height); - let look_from = Vec3::new(13.0, 2.0, 3.0); - let look_at = Vec3::new(0.0, 0.0, 0.0); - // TODO: Make camera configurable. - // pos, look_at, fov, aperture, focus distance. - // Also ensure those can be changed during runtime. - let camera = Camera::new( - look_from, - look_at, - Vec3::new(0.0, 1.0, 0.0), - 20.0, - &image, - 0.1, - 10.0, - ); + let camera = Camera::from((&image, &config.camera)); let scene = Scene::try_new(&config.loader)?; let mut window_res: Result<(), TracerError> = Ok(()); let mut render_res: Result<(), TracerError> = Ok(()); diff --git a/racer-tracer/src/vec3.rs b/racer-tracer/src/vec3.rs index 6877eea..40c8453 100644 --- a/racer-tracer/src/vec3.rs +++ b/racer-tracer/src/vec3.rs @@ -1,6 +1,3 @@ -//TODO: Replace this with glam. -use glam::f32::Vec3 as FVec3; - use std::{fmt, ops}; use serde::Deserialize; @@ -121,6 +118,35 @@ impl Vec3 { let s = 1e-8; self.data[0].abs() < s && self.data[1].abs() < s && self.data[2].abs() < s } + + fn hamilton_product(a: [f64; 4], e: [f64; 4]) -> [f64; 4] { + [ + a[0] * e[0] - a[1] * e[1] - a[2] * e[2] - a[3] * e[3], + a[0] * e[1] + a[1] * e[0] + a[2] * e[3] - a[3] * e[2], + a[0] * e[2] - a[1] * e[3] + a[2] * e[0] + a[3] * e[1], + a[0] * e[3] + a[1] * e[2] - a[2] * e[1] + a[3] * e[0], + ] + } + + fn get_rotation(degrees: f64, axis: &Vec3) -> ([f64; 4], [f64; 4]) { + let hd = degrees * 0.5; + let rot = [ + hd.cos(), + hd.sin() * *axis.x(), + hd.sin() * *axis.y(), + hd.sin() * *axis.z(), + ]; + (rot, [rot[0], -rot[1], -rot[2], -rot[3]]) + } + + pub fn rotate(&mut self, degrees: f64, axis: &Vec3) { + let p = [0.0, self.data[0], self.data[1], self.data[2]]; + let (r, r_neg) = Vec3::get_rotation(degrees, axis); + let rpr_neg = Vec3::hamilton_product(Vec3::hamilton_product(r, p), r_neg); + self.data[0] = rpr_neg[1]; + self.data[1] = rpr_neg[2]; + self.data[2] = rpr_neg[3]; + } } pub fn dot(v1: &Vec3, v2: &Vec3) -> f64 { @@ -329,22 +355,6 @@ impl fmt::Display for Vec3 { } } -impl From<FVec3> for Vec3 { - fn from(v: FVec3) -> Self { - Vec3::new(v.x as f64, v.y as f64, v.z as f64) - } -} - -impl From<Vec3> for FVec3 { - fn from(v: Vec3) -> Self { - FVec3 { - x: v.data[0] as f32, - y: v.data[1] as f32, - z: v.data[2] as f32, - } - } -} - impl std::fmt::Debug for Vec3 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Vec3").field("data", &self.data).finish() |
