csci5607/assignment-1/src/input_file.rs

84 lines
2.1 KiB
Rust

use std::{fs::File, io::Read, path::Path};
use anyhow::Result;
use crate::{
image::Color,
scene_data::{Object, Scene, Sphere},
vec3::Vec3,
};
/// Parse the input file into a scene
pub fn parse_input_file(path: impl AsRef<Path>) -> Result<Scene> {
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::<usize>().map_err(|e| e.into()))
.collect::<Result<Vec<_>>>()?;
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::<f64>().map_err(|e| e.into()))
.collect::<Result<Vec<_>>>()?;
let read_vec3 = || {
if parts.len() < 3 {
bail!("Vec3 requires 3 components.");
}
Ok(Vec3::new(parts[0], parts[1], parts[2]))
};
let read_color = || {
if parts.len() < 3 {
bail!("Color requires 3 components.");
}
Ok(Color::from_01_float(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_color()?,
"mtlcolor" => {
let idx = scene.material_colors.len();
material_color = Some(idx);
scene.material_colors.push(read_color()?);
}
"sphere" => scene.objects.push(Object::Sphere(Sphere {
center: read_vec3()?,
radius: parts[3],
material: material_color.unwrap(),
})),
_ => bail!("Unknown keyword {keyword}"),
}
}
}
Ok(scene)
}