use std::{fs::File, io::Read, path::Path}; use anyhow::Result; use crate::{ scene_data::{Object, Scene, Sphere}, vec3::Vec3, }; pub fn parse_input_file(path: impl AsRef) -> Result { 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) }