diff --git a/src/bvh.rs b/src/bvh.rs index 84d51ad..1719f96 100644 --- a/src/bvh.rs +++ b/src/bvh.rs @@ -178,6 +178,10 @@ impl BVH { pub fn traverse(&self, rays: &mut [Ray], objects: &[T], mut obj_ray_test: F) where F: FnMut(&T, &mut [Ray]) { + if self.nodes.len() == 0 { + return; + } + let mut i_stack = [0; 65]; let mut ray_i_stack = [rays.len(); 65]; let mut stack_ptr = 1; diff --git a/src/main.rs b/src/main.rs index a7ca3a3..78a76f5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -36,7 +36,7 @@ use scene::Scene; use assembly::{AssemblyBuilder, Object}; use renderer::Renderer; use surface::triangle_mesh::TriangleMesh; -use parse::DataTree; +use parse::{parse_scene, DataTree}; // ---------------------------------------------------------------- @@ -81,76 +81,86 @@ fn main() { return; } - // ======================= - // Print tree from psy file if passed as an argument. - // TODO: remove this, because it's for debugging - if let Some(fp) = args.flag_input { + // Parse data tree of scene file + let mut s = String::new(); + let dt = if let Some(fp) = args.flag_input { let mut f = io::BufReader::new(File::open(fp).unwrap()); - let mut s = String::new(); let _ = f.read_to_string(&mut s); - let dt = DataTree::from_str(&s); - println!("{:#?}", dt); - return; - } - // ======================= + + DataTree::from_str(&s).unwrap() + } else { + panic!() + }; + + + // Generate a scene of triangles + // let mesh = TriangleMesh::from_triangles(2, { + // let mut triangles = Vec::new(); + // let xres = 32; + // let yres = 32; + // let xinc = 512.0 / (xres as f32); + // let yinc = 512.0 / (yres as f32); + // for x in 0..xres { + // for y in 0..yres { + // let i = y * xres + x; + // let cx = halton::sample(0, i) * 512.0; + // let cy = halton::sample(1, i) * 512.0; + // let cz = halton::sample(2, i) * 512.0; + // let cx = x as f32 * xinc; + // let cy = y as f32 * yinc; + // let cz = 1.0; + // triangles.push((Point::new(cx, cy, cz + 1.0), + // Point::new(cx + xinc, cy, cz + 1.1), + // Point::new(cx, cy + yinc, cz + 1.2))); + // triangles.push((Point::new(cx + 25.0, cy, cz + 1.0), + // Point::new(cx + 25.0 + xinc, cy, cz + 1.1), + // Point::new(cx + 25.0, cy + yinc, cz + 1.2))); + // } + // } + // triangles + // }); + // + // let cam = Camera::new(vec![Matrix4x4::from_location(Point::new(256.0, 256.0, -1024.0))], + // vec![0.785], + // vec![20.0], + // vec![1026.0]); + // + // let mut assembly_b = AssemblyBuilder::new(); + // assembly_b.add_object("yar", Object::Surface(Box::new(mesh))); + // assembly_b.add_object_instance("yar", + // Some(&[Matrix4x4::from_location(Point::new(25.0, 0.0, 0.0))])); + // let assembly = assembly_b.build(); + // + // let scene = Scene { + // name: None, + // background_color: (0.0, 0.0, 0.0), + // camera: cam, + // root: assembly, + // }; + // + // let r = Renderer { + // output_file: args.arg_imgpath.clone(), + // resolution: (512, 512), + // spp: samples_per_pixel as usize, + // scene: scene, + // }; + // + println!("Scene built."); let samples_per_pixel = args.flag_spp.unwrap_or_else(|| 16); println!("Sample count: {}", samples_per_pixel); println!("Ray size: {} bytes", mem::size_of::()); - // Generate a scene of triangles - let mesh = TriangleMesh::from_triangles(2, { - let mut triangles = Vec::new(); - let xres = 32; - let yres = 32; - let xinc = 512.0 / (xres as f32); - let yinc = 512.0 / (yres as f32); - for x in 0..xres { - for y in 0..yres { - let i = y * xres + x; - let cx = halton::sample(0, i) * 512.0; - let cy = halton::sample(1, i) * 512.0; - let cz = halton::sample(2, i) * 512.0; - // let cx = x as f32 * xinc; - // let cy = y as f32 * yinc; - // let cz = 1.0; - triangles.push((Point::new(cx, cy, cz + 1.0), - Point::new(cx + xinc, cy, cz + 1.1), - Point::new(cx, cy + yinc, cz + 1.2))); - triangles.push((Point::new(cx + 25.0, cy, cz + 1.0), - Point::new(cx + 25.0 + xinc, cy, cz + 1.1), - Point::new(cx + 25.0, cy + yinc, cz + 1.2))); + // Iterate through scenes and render them + if let DataTree::Internal{ref children, ..} = dt { + for child in children { + if child.type_name() == "Scene" { + println!("Parsing scene..."); + let r = parse_scene(child).unwrap(); + println!("Rendering scene..."); + r.render(); } } - triangles - }); - println!("Scene built."); - - let cam = Camera::new(vec![Matrix4x4::from_location(Point::new(256.0, 256.0, -1024.0))], - vec![0.785], - vec![20.0], - vec![1026.0]); - - let mut assembly_b = AssemblyBuilder::new(); - assembly_b.add_object("yar", Object::Surface(Box::new(mesh))); - assembly_b.add_object_instance("yar", - Some(&[Matrix4x4::from_location(Point::new(25.0, 0.0, 0.0))])); - let assembly = assembly_b.build(); - - let scene = Scene { - name: None, - background_color: (0.0, 0.0, 0.0), - camera: cam, - root: assembly, - }; - - let r = Renderer { - output_file: args.arg_imgpath.clone(), - resolution: (512, 512), - spp: samples_per_pixel as usize, - scene: scene, - }; - - r.render(); + } } diff --git a/src/parse/mod.rs b/src/parse/mod.rs index 1725dda..60c386a 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -4,3 +4,4 @@ mod psy_assembly; pub mod basics; pub use self::data_tree::DataTree; +pub use self::psy::parse_scene; diff --git a/src/parse/psy.rs b/src/parse/psy.rs index 94be11d..c75c395 100644 --- a/src/parse/psy.rs +++ b/src/parse/psy.rs @@ -14,27 +14,36 @@ use camera::Camera; use renderer::Renderer; use scene::Scene; - +#[derive(Copy, Clone, Debug)] +pub enum PsyParseError { + UnknownError, + SectionWrongCount(&'static str, usize), +} /// Takes in a DataTree representing a Scene node and returns /// a renderer. -pub fn parse_frame(tree: &DataTree) -> Result { +pub fn parse_scene(tree: &DataTree) -> Result { // Verify we have the right number of each section if tree.count_children_with_type_name("Output") != 1 { - return Err(()); + let count = tree.count_children_with_type_name("Output"); + return Err(PsyParseError::SectionWrongCount("Output", count)); } if tree.count_children_with_type_name("RenderSettings") != 1 { - return Err(()); + let count = tree.count_children_with_type_name("RenderSettings"); + return Err(PsyParseError::SectionWrongCount("RenderSettings", count)); } if tree.count_children_with_type_name("Camera") != 1 { - return Err(()); + let count = tree.count_children_with_type_name("Camera"); + return Err(PsyParseError::SectionWrongCount("Camera", count)); } if tree.count_children_with_type_name("World") != 1 { - return Err(()); + let count = tree.count_children_with_type_name("World"); + return Err(PsyParseError::SectionWrongCount("World", count)); } if tree.count_children_with_type_name("Assembly") != 1 { - return Err(()); + let count = tree.count_children_with_type_name("Assembly"); + return Err(PsyParseError::SectionWrongCount("Root Assembly", count)); } // Parse output info @@ -73,23 +82,22 @@ pub fn parse_frame(tree: &DataTree) -> Result { root: assembly, }; - // // Put renderer together - // let renderer = Renderer { - // output_file: output_info.0.clone(), - // resolution: (render_settings.0.0 as usize, render_settings.0.1 as usize), - // spp: render_settings.1, - // scene: scene, - // } - // - // return Ok(renderer); + // Put renderer together + let renderer = Renderer { + output_file: output_info.clone(), + resolution: ((render_settings.0).0 as usize, + (render_settings.0).1 as usize), + spp: render_settings.1 as usize, + scene: scene, + }; - return Err(()); + return Ok(renderer); } -fn parse_output_info(tree: &DataTree) -> Result<(String), ()> { +fn parse_output_info(tree: &DataTree) -> Result { if let &DataTree::Internal{ref children, ..} = tree { let mut found_path = false; let mut path = String::new(); @@ -109,17 +117,17 @@ fn parse_output_info(tree: &DataTree) -> Result<(String), ()> { if found_path { return Ok((path)); } else { - return Err(()); + return Err(PsyParseError::UnknownError); } } else { - return Err(()); + return Err(PsyParseError::UnknownError); }; } -fn parse_render_settings(tree: &DataTree) -> Result<((u32, u32), u32, u32), ()> { +fn parse_render_settings(tree: &DataTree) -> Result<((u32, u32), u32, u32), PsyParseError> { if let &DataTree::Internal{ref children, ..} = tree { let mut found_res = false; let mut found_spp = false; @@ -137,7 +145,7 @@ fn parse_render_settings(tree: &DataTree) -> Result<((u32, u32), u32, u32), ()> res = (w, h); } else { // Found Resolution, but its contents is not in the right format - return Err(()); + return Err(PsyParseError::UnknownError); } } @@ -148,7 +156,7 @@ fn parse_render_settings(tree: &DataTree) -> Result<((u32, u32), u32, u32), ()> spp = n; } else { // Found SamplesPerPixel, but its contents is not in the right format - return Err(()); + return Err(PsyParseError::UnknownError); } } @@ -158,7 +166,7 @@ fn parse_render_settings(tree: &DataTree) -> Result<((u32, u32), u32, u32), ()> seed = n; } else { // Found Seed, but its contents is not in the right format - return Err(()); + return Err(PsyParseError::UnknownError); } } @@ -169,17 +177,17 @@ fn parse_render_settings(tree: &DataTree) -> Result<((u32, u32), u32, u32), ()> if found_res && found_spp { return Ok((res, spp, seed)); } else { - return Err(()); + return Err(PsyParseError::UnknownError); } } else { - return Err(()); + return Err(PsyParseError::UnknownError); }; } -fn parse_camera(tree: &DataTree) -> Result { +fn parse_camera(tree: &DataTree) -> Result { if let &DataTree::Internal{ref children, ..} = tree { let mut mats = Vec::new(); let mut fovs = Vec::new(); @@ -195,7 +203,7 @@ fn parse_camera(tree: &DataTree) -> Result { fovs.push(fov * (3.1415926536 / 180.0)); } else { // Found Fov, but its contents is not in the right format - return Err(()); + return Err(PsyParseError::UnknownError); } } @@ -205,7 +213,7 @@ fn parse_camera(tree: &DataTree) -> Result { focus_distances.push(fd); } else { // Found FocalDistance, but its contents is not in the right format - return Err(()); + return Err(PsyParseError::UnknownError); } } @@ -215,7 +223,7 @@ fn parse_camera(tree: &DataTree) -> Result { aperture_radii.push(ar); } else { // Found ApertureRadius, but its contents is not in the right format - return Err(()); + return Err(PsyParseError::UnknownError); } } @@ -225,7 +233,7 @@ fn parse_camera(tree: &DataTree) -> Result { mats.push(mat); } else { // Found Transform, but its contents is not in the right format - return Err(()); + return Err(PsyParseError::UnknownError); } } @@ -235,14 +243,14 @@ fn parse_camera(tree: &DataTree) -> Result { return Ok(Camera::new(mats, fovs, aperture_radii, focus_distances)); } else { - return Err(()); + return Err(PsyParseError::UnknownError); } } -fn parse_world(tree: &DataTree) -> Result<(f32, f32, f32), ()> { +fn parse_world(tree: &DataTree) -> Result<(f32, f32, f32), PsyParseError> { if tree.is_internal() { let mut found_background_color = false; let mut background_color = (0.0, 0.0, 0.0); @@ -250,19 +258,19 @@ fn parse_world(tree: &DataTree) -> Result<(f32, f32, f32), ()> { // Parse background shader let bgs = { if tree.count_children_with_type_name("BackgroundShader") != 1 { - return Err(()); + return Err(PsyParseError::UnknownError); } tree.get_first_child_with_type_name("BackgroundShader").unwrap() }; let bgs_type = { if bgs.count_children_with_type_name("Type") != 1 { - return Err(()); + return Err(PsyParseError::UnknownError); } - if let &DataTree::Leaf{contents, ..} = tree.get_first_child_with_type_name("Type") - .unwrap() { + if let &DataTree::Leaf{contents, ..} = bgs.get_first_child_with_type_name("Type") + .unwrap() { contents.trim() } else { - return Err(()); + return Err(PsyParseError::UnknownError); } }; match bgs_type { @@ -276,26 +284,26 @@ fn parse_world(tree: &DataTree) -> Result<(f32, f32, f32), ()> { found_background_color = true; background_color = color; } else { - return Err(()); + return Err(PsyParseError::UnknownError); } } else { - return Err(()); + return Err(PsyParseError::UnknownError); } } - _ => return Err(()), + _ => return Err(PsyParseError::UnknownError), } return Ok(background_color); } else { - return Err(()); + return Err(PsyParseError::UnknownError); } } -fn parse_matrix(contents: &str) -> Result { +fn parse_matrix(contents: &str) -> Result { if let IResult::Done(_, ns) = closure!(terminated!(tuple!(ws_f32, ws_f32, ws_f32, @@ -330,6 +338,6 @@ fn parse_matrix(contents: &str) -> Result { ns.14, ns.15)); } else { - return Err(()); + return Err(PsyParseError::UnknownError); } } diff --git a/src/parse/psy_assembly.rs b/src/parse/psy_assembly.rs index 0ad21ba..08732bf 100644 --- a/src/parse/psy_assembly.rs +++ b/src/parse/psy_assembly.rs @@ -7,12 +7,100 @@ use nom::IResult; use super::DataTree; use super::basics::{ws_u32, ws_f32}; +use super::psy::PsyParseError; use math::Matrix4x4; use camera::Camera; use renderer::Renderer; -use assembly::Assembly; +use assembly::{Assembly, AssemblyBuilder}; -pub fn parse_assembly(tree: &DataTree) -> Result { - unimplemented!() +pub fn parse_assembly(tree: &DataTree) -> Result { + let mut builder = AssemblyBuilder::new(); + + if let &DataTree::Internal{ref children, ..} = tree { + for child in children { + match child.type_name() { + // Sub-Assembly + "Assembly" => { + if let &DataTree::Internal {ident: Some(ident), ..} = child { + builder.add_assembly(ident, try!(parse_assembly(&child))); + } else { + // TODO: error condition of some kind, because no ident + } + } + + _ => { + // TODO: some kind of error, because not a known type name + } + + // // Bilinear Patch + // "BilinearPatch" => { + // assembly->add_object(child.name, parse_bilinear_patch(child)); + // } + // + // // Bicubic Patch + // else if (child.type == "BicubicPatch") { + // assembly->add_object(child.name, parse_bicubic_patch(child)); + // } + // + // // Subdivision surface + // else if (child.type == "SubdivisionSurface") { + // assembly->add_object(child.name, parse_subdivision_surface(child)); + // } + // + // // Sphere + // else if (child.type == "Sphere") { + // assembly->add_object(child.name, parse_sphere(child)); + // } + // + // // Surface shader + // else if (child.type == "SurfaceShader") { + // assembly->add_surface_shader(child.name, parse_surface_shader(child)); + // } + // + // // Sphere Light + // else if (child.type == "SphereLight") { + // assembly->add_object(child.name, parse_sphere_light(child)); + // } + // + // // Rectangle Light + // else if (child.type == "RectangleLight") { + // assembly->add_object(child.name, parse_rectangle_light(child)); + // } + // + // // Instance + // else if (child.type == "Instance") { + // // Parse + // std::string name = ""; + // std::vector xforms; + // const SurfaceShader *shader = nullptr; + // for (const auto& child2: child.children) { + // if (child2.type == "Transform") { + // xforms.emplace_back(parse_matrix(child2.leaf_contents)); + // } else if (child2.type == "Data") { + // name = child2.leaf_contents; + // } else if (child2.type == "SurfaceShaderBind") { + // shader = assembly->get_surface_shader(child2.leaf_contents); + // if (shader == nullptr) { + // std::cout << "ERROR: attempted to bind surface shader that doesn't exist." << std::endl; + // } + // } + // } + // + // // Add instance + // if (assembly->object_map.count(name) != 0) { + // assembly->create_object_instance(name, xforms, shader); + // } else if (assembly->assembly_map.count(name) != 0) { + // assembly->create_assembly_instance(name, xforms, shader); + // } else { + // std::cout << "ERROR: attempted to add instace for data that doesn't exist." << std::endl; + // } + // } + } + } + } else { + return Err(PsyParseError::UnknownError); + } + + return Ok(builder.build()); }