diff --git a/assignment-1/examples/sample-1.txt b/assignment-1/examples/sample-1.txt new file mode 100644 index 000000000..25d5532 --- /dev/null +++ b/assignment-1/examples/sample-1.txt @@ -0,0 +1,8 @@ +imsize 256 256 +eye 0 0 0 +viewdir 0 0 -1 +hfov 90 +updir 0 1 0 +bkgcolor 0.1 0.1 0.1 +mtlcolor 0 0 1 +sphere 0 0 -5 2 diff --git a/assignment-1/examples/sample-2.txt b/assignment-1/examples/sample-2.txt new file mode 100644 index 000000000..ca22d17 --- /dev/null +++ b/assignment-1/examples/sample-2.txt @@ -0,0 +1,10 @@ +imsize 512 256 +eye 0 0 0 +viewdir 0 0 -1 +hfov 130 +updir 0 1 1 +bkgcolor 0.1 0.1 0.1 +mtlcolor 0 1 0 +sphere -0.5 -1 -8 3 +mtlcolor 1 0 0 +sphere 3 1 -3 1 diff --git a/assignment-1/src/input_file.rs b/assignment-1/src/input_file.rs index 4a4d8e8..6eb7fca 100644 --- a/assignment-1/src/input_file.rs +++ b/assignment-1/src/input_file.rs @@ -1,9 +1,69 @@ -use std::path::Path; +use std::{fs::File, io::Read, path::Path}; use anyhow::Result; -use crate::scene_data::Scene; +use crate::{ + scene_data::{Object, Scene, Sphere}, + vec3::Vec3, +}; pub fn parse_input_file(path: impl AsRef) -> Result { - todo!() + let contents = { + let mut contents = String::new(); + let mut file = File::open(path.as_ref())?; + file.read_to_string(&mut contents)?; + contents + }; + + let mut scene = Scene::default(); + let mut material_color = None; + + for line in contents.lines() { + let mut parts = line.split_whitespace(); + let keyword = match parts.next() { + Some(v) => v, + None => continue, + }; + + if keyword == "imsize" { + let parts = parts + .map(|s| s.parse::().map_err(|e| e.into())) + .collect::>>()?; + if let [width, height] = parts[..] { + scene.image_width = width; + scene.image_height = height; + } + } + // Do float parsing instead + else { + let parts = parts + .map(|s| s.parse::().map_err(|e| e.into())) + .collect::>>()?; + + let read_vec3 = || { + if parts.len() < 3 { + bail!("Vec3 requires 3 components."); + } + Ok(Vec3::new(parts[0], parts[1], parts[2])) + }; + + match keyword { + "eye" => scene.eye_pos = read_vec3()?, + "viewdir" => scene.view_dir = read_vec3()?, + "updir" => scene.up_dir = read_vec3()?, + + "hfov" => scene.hfov = parts[0], + "bkgcolor" => scene.bkg_color = read_vec3()?, + "mtlcolor" => material_color = Some(read_vec3()?), + + "sphere" => scene.objects.push(Object::Sphere(Sphere { + center: read_vec3()?, + radius: parts[3], + })), + _ => bail!("Unknown keyword {keyword}"), + } + } + } + + Ok(scene) } diff --git a/assignment-1/src/main.rs b/assignment-1/src/main.rs index 4d01571..a41aa25 100644 --- a/assignment-1/src/main.rs +++ b/assignment-1/src/main.rs @@ -1,3 +1,6 @@ +#[macro_use] +extern crate anyhow; + mod input_file; mod ray; mod scene_data; @@ -8,12 +11,12 @@ use std::path::PathBuf; use anyhow::Result; use clap::Parser; -use vec3::Vec3; -use view::Rect; use crate::input_file::parse_input_file; +use crate::vec3::Vec3; +use crate::view::Rect; -/// Noise image generator. +/// Simple raycaster. #[derive(Parser)] #[clap(author, version, about, long_about = None)] struct Opt { @@ -33,6 +36,7 @@ fn main() -> Result<()> { let opt = Opt::parse(); let scene = parse_input_file(&opt.input_path)?; + println!("Scene: {scene:?}"); // Compute viewing directions let u = Vec3::cross(scene.view_dir, scene.up_dir).unit(); diff --git a/assignment-1/src/scene_data.rs b/assignment-1/src/scene_data.rs index cf2b8e2..547856e 100644 --- a/assignment-1/src/scene_data.rs +++ b/assignment-1/src/scene_data.rs @@ -1,10 +1,12 @@ use crate::vec3::Vec3; +#[derive(Debug)] pub struct Sphere { pub center: Vec3, pub radius: f64, } +#[derive(Debug)] pub enum Object { Sphere(Sphere), Cylinder { @@ -15,6 +17,7 @@ pub enum Object { }, } +#[derive(Debug, Default)] pub struct Scene { pub eye_pos: Vec3, pub view_dir: Vec3, diff --git a/assignment-1/src/vec3.rs b/assignment-1/src/vec3.rs index 4c7aee9..bceef2b 100644 --- a/assignment-1/src/vec3.rs +++ b/assignment-1/src/vec3.rs @@ -2,7 +2,7 @@ use std::ops::{Add, Mul}; use num::Float; -#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[derive(Copy, Clone, Default, Debug, PartialEq, Eq)] pub struct Vec3 { pub x: T, pub y: T, @@ -25,6 +25,7 @@ impl Vec3 { ) } + /// Vector L2-norm pub fn norm(&self) -> T { (self.x.powi(2) + self.y.powi(2) + self.z.powi(2)).sqrt() } diff --git a/assignment-1/src/view.rs b/assignment-1/src/view.rs index da5e522..4e4dd04 100644 --- a/assignment-1/src/view.rs +++ b/assignment-1/src/view.rs @@ -1,5 +1,6 @@ use crate::vec3::Vec3; +#[derive(Debug)] pub struct Rect { pub upper_left: Vec3, pub upper_right: Vec3,