diff --git a/assignment-1b/Cargo.lock b/assignment-1b/Cargo.lock index ece12db..bc1bc4f 100644 --- a/assignment-1b/Cargo.lock +++ b/assignment-1b/Cargo.lock @@ -31,6 +31,7 @@ dependencies = [ "rand", "rayon", "tracing", + "tracing-subscriber", ] [[package]] @@ -235,6 +236,12 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + [[package]] name = "libc" version = "0.2.139" @@ -247,6 +254,15 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + [[package]] name = "matrixmultiply" version = "0.3.2" @@ -292,6 +308,16 @@ dependencies = [ "syn", ] +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + [[package]] name = "num" version = "0.4.0" @@ -402,6 +428,12 @@ version = "6.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + [[package]] name = "paste" version = "1.0.11" @@ -555,6 +587,15 @@ version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" +[[package]] +name = "sharded-slab" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +dependencies = [ + "lazy_static", +] + [[package]] name = "simba" version = "0.8.0" @@ -568,6 +609,12 @@ dependencies = [ "wide", ] +[[package]] +name = "smallvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" + [[package]] name = "strsim" version = "0.10.0" @@ -594,6 +641,16 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "thread_local" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +dependencies = [ + "cfg-if", + "once_cell", +] + [[package]] name = "tracing" version = "0.1.37" @@ -624,6 +681,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" dependencies = [ "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70" +dependencies = [ + "nu-ansi-term", + "sharded-slab", + "smallvec", + "thread_local", + "tracing-core", + "tracing-log", ] [[package]] @@ -638,6 +721,12 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + [[package]] name = "version_check" version = "0.9.4" diff --git a/assignment-1b/Cargo.toml b/assignment-1b/Cargo.toml index 1be1358..bd9ba71 100644 --- a/assignment-1b/Cargo.toml +++ b/assignment-1b/Cargo.toml @@ -29,3 +29,4 @@ ordered-float = "3.4.0" rand = "0.8.5" rayon = "1.6.1" tracing = "0.1.37" +tracing-subscriber = "0.3.16" diff --git a/assignment-1b/src/main.rs b/assignment-1b/src/main.rs index 87e22b2..8334beb 100644 --- a/assignment-1b/src/main.rs +++ b/assignment-1b/src/main.rs @@ -1,7 +1,10 @@ +#[macro_use] +extern crate tracing; + use std::fs::File; use std::path::PathBuf; -use anyhow::{Result}; +use anyhow::Result; use assignment_1b::image::Image; use assignment_1b::ray::Ray; use assignment_1b::scene::Scene; @@ -10,7 +13,7 @@ use clap::Parser; use rayon::prelude::{IntoParallelIterator, ParallelIterator}; -/// Simple raycaster. +/// Simple raytracer with Blinn-Phong illumination and shadowing. #[derive(Parser)] #[clap(author, version, about, long_about = None)] struct Opt { @@ -34,6 +37,15 @@ struct Opt { fn main() -> Result<()> { let opt = Opt::parse(); + + // Set up logging + tracing_subscriber::fmt() + .with_target(false) + .with_timer(tracing_subscriber::fmt::time::uptime()) + .with_level(true) + .init(); + + // Rename the output file if it's not provided let out_file = opt .output_path .unwrap_or_else(|| opt.input_path.with_extension("ppm")); @@ -41,33 +53,13 @@ fn main() -> Result<()> { let mut scene = Scene::from_input_file(&opt.input_path)?; let distance = opt.distance; + // Force-override parallel projection if opt.force_parallel { scene.parallel_projection = true; } - // Compute the viewing window - let view_window = scene.compute_viewing_window(distance); - // Translate image pixels to real-world 3d coords - let translate_pixel = { - let dx = view_window.upper_right - view_window.upper_left; - let pixel_base_x = dx / scene.image_width as f64; - - let dy = view_window.lower_left - view_window.upper_left; - let pixel_base_y = dy / scene.image_height as f64; - - move |px: usize, py: usize| { - let x_component = pixel_base_x * px as f64; - let y_component = pixel_base_y * py as f64; - - // Without adding this, we would be getting the top-left of the pixel's - // rectangle. We want the center, so add half of the pixel size as - // well. - let center_offset = (pixel_base_x + pixel_base_y) / 2.0; - - view_window.upper_left + x_component + y_component + center_offset - } - }; + let translate_pixel = scene.pixel_translation_function(distance); // Generate a parallel iterator for pixels // The iterator preserves order and uses row-major order @@ -106,7 +98,10 @@ fn main() -> Result<()> { Some(Ok((i, t, object))) } Ok(None) => None, - Err(e) => Some(Err(e)), + Err(err) => { + error!("Error: {err}"); + Some(Err(err)) + } } }) .collect::>>()?; diff --git a/assignment-1b/src/scene/data.rs b/assignment-1b/src/scene/data.rs index f054d65..45e5fdd 100644 --- a/assignment-1b/src/scene/data.rs +++ b/assignment-1b/src/scene/data.rs @@ -194,4 +194,32 @@ impl Scene { view_window } + + /// Create a pixel translation function based on the viewing window of the + /// current scene + pub fn pixel_translation_function( + &self, + distance: f64, + ) -> impl Fn(usize, usize) -> Vector3 { + let view_window = self.compute_viewing_window(distance); + + let dx = view_window.upper_right - view_window.upper_left; + let pixel_base_x = dx / self.image_width as f64; + + let dy = view_window.lower_left - view_window.upper_left; + let pixel_base_y = dy / self.image_height as f64; + + // The final function to be returned + move |px: usize, py: usize| { + let x_component = pixel_base_x * px as f64; + let y_component = pixel_base_y * py as f64; + + // Without adding this, we would be getting the top-left of the pixel's + // rectangle. We want the center, so add half of the pixel size as + // well. + let center_offset = (pixel_base_x + pixel_base_y) / 2.0; + + view_window.upper_left + x_component + y_component + center_offset + } + } } diff --git a/assignment-1b/src/scene/input_file.rs b/assignment-1b/src/scene/input_file.rs index 9942464..c6882d2 100644 --- a/assignment-1b/src/scene/input_file.rs +++ b/assignment-1b/src/scene/input_file.rs @@ -5,7 +5,7 @@ use nalgebra::Vector3; use crate::scene::{ cylinder::Cylinder, - data::{Light, LightKind, Material, Object, Attenuation}, + data::{Attenuation, Light, LightKind, Material, Object}, sphere::Sphere, Scene, }; @@ -15,6 +15,8 @@ use super::data::{DepthCueing, ObjectKind}; impl Scene { /// Parse the input file into a scene pub fn from_input_file(path: impl AsRef) -> Result { + // Scope the read so the file is dropped and closed immediately after the + // contents have been read to memory let contents = { let mut contents = String::new(); let mut file = File::open(path.as_ref())?;