summaryrefslogtreecommitdiff
path: root/racer-tracer/src
diff options
context:
space:
mode:
Diffstat (limited to 'racer-tracer/src')
-rw-r--r--racer-tracer/src/camera.rs98
-rw-r--r--racer-tracer/src/config.rs87
-rw-r--r--racer-tracer/src/main.rs20
-rw-r--r--racer-tracer/src/vec3.rs48
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()