diff --git a/src/main.rs b/src/main.rs index 2091f8a..f39abae 100644 --- a/src/main.rs +++ b/src/main.rs @@ -47,6 +47,11 @@ use nom::bytes::complete::take_until; use kioku::Arena; +use data_tree::{ + reader::{DataTreeReader, ReaderError}, + Event, +}; + use crate::{ accel::BVH4Node, bbox::BBox, @@ -191,63 +196,86 @@ fn main() { println!("Parsing scene file...",); } t.tick(); - let psy_contents = if args.is_present("use_stdin") { - // Read from stdin - let mut input = Vec::new(); - let tmp = std::io::stdin(); - let mut stdin = tmp.lock(); - let mut buf = vec![0u8; 4096]; - loop { - let count = stdin - .read(&mut buf) - .expect("Unexpected end of scene input."); - let start = if input.len() < 11 { - 0 - } else { - input.len() - 11 - }; - let end = input.len() + count; - input.extend(&buf[..count]); + // let psy_contents = if args.is_present("use_stdin") { + // // Read from stdin + // let mut input = Vec::new(); + // let tmp = std::io::stdin(); + // let mut stdin = tmp.lock(); + // let mut buf = vec![0u8; 4096]; + // loop { + // let count = stdin + // .read(&mut buf) + // .expect("Unexpected end of scene input."); + // let start = if input.len() < 11 { + // 0 + // } else { + // input.len() - 11 + // }; + // let end = input.len() + count; + // input.extend(&buf[..count]); - let mut done = false; - let mut trunc_len = 0; - if let nom::IResult::Ok((remaining, _)) = - take_until::<&str, &[u8], ()>("__PSY_EOF__")(&input[start..end]) - { - done = true; - trunc_len = input.len() - remaining.len(); - } - if done { - input.truncate(trunc_len); - break; - } - } - String::from_utf8(input).unwrap() - } else { - // Read from file - let mut input = String::new(); - let fp = args.value_of("input").unwrap(); - let mut f = io::BufReader::new(File::open(fp).unwrap()); - let _ = f.read_to_string(&mut input); - input - }; + // let mut done = false; + // let mut trunc_len = 0; + // if let nom::IResult::Ok((remaining, _)) = + // take_until::<&str, &[u8], ()>("__PSY_EOF__")(&input[start..end]) + // { + // done = true; + // trunc_len = input.len() - remaining.len(); + // } + // if done { + // input.truncate(trunc_len); + // break; + // } + // } + // String::from_utf8(input).unwrap() + // } else { + // // Read from file + // let mut input = String::new(); + // let fp = args.value_of("input").unwrap(); + // let mut f = io::BufReader::new(File::open(fp).unwrap()); + // let _ = f.read_to_string(&mut input); + // input + // }; - let dt = DataTree::from_str(&psy_contents).unwrap(); - if !args.is_present("serialized_output") { - println!("\tParsed scene file in {:.3}s", t.tick()); - } + // let dt = DataTree::from_str(&psy_contents).unwrap(); + // if !args.is_present("serialized_output") { + // println!("\tParsed scene file in {:.3}s", t.tick()); + // } + + let mut psy_file = io::BufReader::new(File::open(fp).unwrap()); + let mut events = DataTreeReader::new(&mut psy_file); // Iterate through scenes and render them - if let DataTree::Internal { ref children, .. } = dt { - for child in children { - t.tick(); - if child.type_name() == "Scene" { + loop { + t.tick(); + match events.next_event() { + Ok(Event::ValidEnd) => { + break; + } + + Ok(_) => { + println!("Error: invalid scene in psy file."); + break; + } + + Err(e) => { + println!("Error: {:?}", e); + break; + } + + // Parse a scene and render it. + Ok(Event::InnerOpen { + type_name: "Scene", + ident, + .. + }) => { if !args.is_present("serialized_output") { println!("Building scene..."); } let arena = Arena::new().with_block_size((1 << 20) * 4); - let mut scene = parse_scene(&arena, child).unwrap_or_else(|e| { + let ident = ident.into::(); + let mut scene = parse_scene(&arena, &mut events, &ident).unwrap_or_else(|e| { e.print(&psy_contents); panic!("Parse error."); }); diff --git a/src/parse/psy.rs b/src/parse/psy.rs index e681a0b..6edde25 100644 --- a/src/parse/psy.rs +++ b/src/parse/psy.rs @@ -1,9 +1,13 @@ #![allow(dead_code)] -use std::{collections::HashMap, f32, result::Result}; +use std::{collections::HashMap, f32, io::BufRead, result::Result}; use nom::{combinator::all_consuming, sequence::tuple, IResult}; +use data_tree::{ + reader::{DataTreeReader, ReaderError}, + Event, +}; use kioku::Arena; use crate::{ @@ -38,6 +42,7 @@ pub enum PsyParseError { IncorrectLeafData(usize, &'static str), // Error message WrongNodeCount(usize, &'static str, usize), // Error message, sections found InstancedMissingData(usize, &'static str, String), // Error message, data name + ReaderError(ReaderError), } impl PsyParseError { @@ -95,109 +100,116 @@ impl PsyParseError { } } +impl std::error::Error for PsyParseError {} + +impl std::fmt::Display for PsyParseError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { + write!(f, "{:?}", self) + } +} + +impl From for PsyParseError { + fn from(e: ReaderError) -> Self { + PsyParseError::ReaderError(e) + } +} + fn line_count_to_byte_offset(text: &str, offset: usize) -> usize { text[..offset].matches('\n').count() + 1 } +//---------------------------------------------------------------- + /// Takes in a `DataTree` representing a Scene node and returns -pub fn parse_scene<'a>(arena: &'a Arena, tree: &'a DataTree) -> Result, PsyParseError> { - // Verify we have the right number of each section - if tree.iter_children_with_type("Output").count() != 1 { - let count = tree.iter_children_with_type("Output").count(); - return Err(PsyParseError::WrongNodeCount( - tree.byte_offset(), - "Scene should have precisely one Output \ - section.", - count, - )); - } - if tree.iter_children_with_type("RenderSettings").count() != 1 { - let count = tree.iter_children_with_type("RenderSettings").count(); - return Err(PsyParseError::WrongNodeCount( - tree.byte_offset(), - "Scene should have precisely one \ - RenderSettings section.", - count, - )); - } - if tree.iter_children_with_type("Camera").count() != 1 { - let count = tree.iter_children_with_type("Camera").count(); - return Err(PsyParseError::WrongNodeCount( - tree.byte_offset(), - "Scene should have precisely one Camera \ - section.", - count, - )); - } - if tree.iter_children_with_type("World").count() != 1 { - let count = tree.iter_children_with_type("World").count(); - return Err(PsyParseError::WrongNodeCount( - tree.byte_offset(), - "Scene should have precisely one World section.", - count, - )); - } - if tree.iter_children_with_type("Shaders").count() != 1 { - let count = tree.iter_children_with_type("Shaders").count(); - return Err(PsyParseError::WrongNodeCount( - tree.byte_offset(), - "Scene should have precisely one Shaders section.", - count, - )); - } - if tree.iter_children_with_type("Assembly").count() != 1 { - let count = tree.iter_children_with_type("Assembly").count(); - return Err(PsyParseError::WrongNodeCount( - tree.byte_offset(), - "Scene should have precisely one Root Assembly \ - section.", - count, - )); - } +pub fn parse_scene<'a>( + arena: &'a Arena, + events: &mut DataTreeReader, + ident: Option<&str>, +) -> Result, PsyParseError> { + // Get output info. + let output_info = if let Event::InnerOpen { + type_name: "Output", + .. + } = events.next_event()? + { + parse_output_info(events)? + } else { + todo!(); // Return error. + }; - // Parse output info - let output_info = parse_output_info(tree.iter_children_with_type("Output").nth(0).unwrap())?; + // Get render settings. + let render_settings = if let Event::InnerOpen { + type_name: "RenderSettings", + .. + } = events.next_event()? + { + parse_render_settings(events)? + } else { + todo!(); // Return error. + }; - // Parse render settings - let render_settings = parse_render_settings( - tree.iter_children_with_type("RenderSettings") - .nth(0) - .unwrap(), - )?; + // Get camera. + let camera = if let Event::InnerOpen { + type_name: "Camera", + .. + } = events.next_event()? + { + parse_camera(arena, events)? + } else { + todo!(); // Return error. + }; - // Parse camera - let camera = parse_camera( - arena, - tree.iter_children_with_type("Camera").nth(0).unwrap(), - )?; + // Get shaders. + let shaders = if let Event::InnerOpen { + type_name: "Shaders", + .. + } = events.next_event()? + { + parse_shaders(arena, events)? + } else { + todo!(); // Return error. + }; - // Parse world - let world = parse_world(arena, tree.iter_children_with_type("World").nth(0).unwrap())?; + // Get world. + let world = if let Event::InnerOpen { + type_name: "World", .. + } = events.next_event()? + { + parse_world(arena, events)? + } else { + todo!(); // Return error. + }; - // Parse shaders - let shaders = parse_shaders(tree.iter_children_with_type("Shaders").nth(0).unwrap())?; + // Get the root assembly. + let root_assembly = if let Event::InnerOpen { + type_name: "Assembly", + ident, + .. + } = events.next_event()? + { + parse_assembly(arena, events, &(ident.into::()))? + } else { + todo!(); // Return error. + }; - // Parse root scene assembly - let assembly = parse_assembly( - arena, - tree.iter_children_with_type("Assembly").nth(0).unwrap(), - )?; + // Make sure we're closed out properly. + if let Event::InnerClose { .. } = events.next_event()? { + } else { + todo!(); // Return error. + } // Put scene together - let scene_name = if let DataTree::Internal { ident, .. } = tree { - if let Some(name) = ident { - Some(name.clone()) - } else { - None - } + let scene_name = if let Some(name) = ident { + Some(name.into()) } else { None }; + let scene = Scene { camera: camera, world: world, shaders: shaders, - root_assembly: assembly, + root_assembly: root_assembly, }; // // Put renderer together @@ -215,396 +227,357 @@ pub fn parse_scene<'a>(arena: &'a Arena, tree: &'a DataTree) -> Result return Ok(scene); } -fn parse_output_info(tree: &DataTree) -> Result { - if let DataTree::Internal { ref children, .. } = *tree { - let mut found_path = false; - let mut path = String::new(); - - for child in children { - match child { - DataTree::Leaf { - type_name, - contents, - byte_offset, - } if type_name == "Path" => { - // Trim and validate - let tc = contents.trim(); - if tc.chars().count() < 2 { - return Err(PsyParseError::IncorrectLeafData( - *byte_offset, - "File path format is \ - incorrect.", - )); - } - if tc.chars().nth(0).unwrap() != '"' || !tc.ends_with('"') { - return Err(PsyParseError::IncorrectLeafData( - *byte_offset, - "File paths must be \ - surrounded by quotes.", - )); - } - let len = tc.len(); - let tc = &tc[1..len - 1]; - - // Parse - // TODO: proper string escaping - found_path = true; - path = tc.to_string(); +fn parse_output_info(events: &mut DataTreeReader) -> Result { + let mut found_path = false; + let mut path = String::new(); + loop { + match events.next_event()? { + Event::Leaf { + type_name: "Path", + contents, + byte_offset, + } => { + // Trim and validate + let tc = contents.trim(); + if tc.chars().count() < 2 { + return Err(PsyParseError::IncorrectLeafData( + *byte_offset, + "File path format is incorrect.", + )); } + if tc.chars().nth(0).unwrap() != '"' || !tc.ends_with('"') { + return Err(PsyParseError::IncorrectLeafData( + *byte_offset, + "File paths must be surrounded by quotes.", + )); + } + let len = tc.len(); + let tc = &tc[1..len - 1]; - _ => {} + // Parse + // TODO: proper string escaping + found_path = true; + path = tc.to_string(); + } + + Event::InnerClose { .. } => { + break; + } + + _ => { + todo!(); // Return error. } } + } - if found_path { - return Ok(path); - } else { - return Err(PsyParseError::MissingNode( - tree.byte_offset(), - "Output section must contain a Path.", - )); - } + if found_path { + return Ok(path); } else { - return Err(PsyParseError::ExpectedInternalNode( - tree.byte_offset(), - "Output section should be an internal \ - node, containing at least a Path.", - )); - }; -} - -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; - let mut res = (0, 0); - let mut spp = 0; - let mut seed = 0; - - for child in children { - match child { - // Resolution - DataTree::Leaf { - type_name, - contents, - byte_offset, - } if type_name == "Resolution" => { - if let IResult::Ok((_, (w, h))) = - all_consuming(tuple((ws_u32, ws_u32)))(&contents) - { - found_res = true; - res = (w, h); - } else { - // Found Resolution, but its contents is not in the right format - return Err(PsyParseError::IncorrectLeafData( - *byte_offset, - "Resolution should be specified with two \ - integers in the form '[width height]'.", - )); - } - } - - // SamplesPerPixel - DataTree::Leaf { - type_name, - contents, - byte_offset, - } if type_name == "SamplesPerPixel" => { - if let IResult::Ok((_, n)) = all_consuming(ws_u32)(&contents) { - found_spp = true; - spp = n; - } else { - // Found SamplesPerPixel, but its contents is not in the right format - return Err(PsyParseError::IncorrectLeafData( - *byte_offset, - "SamplesPerPixel should be \ - an integer specified in \ - the form '[samples]'.", - )); - } - } - - // Seed - DataTree::Leaf { - type_name, - contents, - byte_offset, - } if type_name == "Seed" => { - if let IResult::Ok((_, n)) = all_consuming(ws_u32)(&contents) { - seed = n; - } else { - // Found Seed, but its contents is not in the right format - return Err(PsyParseError::IncorrectLeafData( - *byte_offset, - "Seed should be an integer \ - specified in the form \ - '[samples]'.", - )); - } - } - - _ => {} - } - } - - if found_res && found_spp { - return Ok((res, spp, seed)); - } else { - return Err(PsyParseError::MissingNode( - tree.byte_offset(), - "RenderSettings must have both Resolution and \ - SamplesPerPixel specified.", - )); - } - } else { - return Err(PsyParseError::ExpectedInternalNode( - tree.byte_offset(), - "RenderSettings section should be an \ - internal node, containing at least \ - Resolution and SamplesPerPixel.", - )); - }; -} - -fn parse_camera<'a>(arena: &'a Arena, tree: &'a DataTree) -> Result, PsyParseError> { - if let DataTree::Internal { ref children, .. } = *tree { - let mut mats = Vec::new(); - let mut fovs = Vec::new(); - let mut focus_distances = Vec::new(); - let mut aperture_radii = Vec::new(); - - // Parse - for child in children.iter() { - match child { - // Fov - DataTree::Leaf { - type_name, - contents, - byte_offset, - } if type_name == "Fov" => { - if let IResult::Ok((_, fov)) = all_consuming(ws_f32)(&contents) { - fovs.push(fov * (f32::consts::PI / 180.0)); - } else { - // Found Fov, but its contents is not in the right format - return Err(PsyParseError::IncorrectLeafData( - *byte_offset, - "Fov should be a decimal \ - number specified in the \ - form '[fov]'.", - )); - } - } - - // FocalDistance - DataTree::Leaf { - type_name, - contents, - byte_offset, - } if type_name == "FocalDistance" => { - if let IResult::Ok((_, fd)) = all_consuming(ws_f32)(&contents) { - focus_distances.push(fd); - } else { - // Found FocalDistance, but its contents is not in the right format - return Err(PsyParseError::IncorrectLeafData( - *byte_offset, - "FocalDistance should be a \ - decimal number specified \ - in the form '[fov]'.", - )); - } - } - - // ApertureRadius - DataTree::Leaf { - type_name, - contents, - byte_offset, - } if type_name == "ApertureRadius" => { - if let IResult::Ok((_, ar)) = all_consuming(ws_f32)(&contents) { - aperture_radii.push(ar); - } else { - // Found ApertureRadius, but its contents is not in the right format - return Err(PsyParseError::IncorrectLeafData( - *byte_offset, - "ApertureRadius should be a \ - decimal number specified \ - in the form '[fov]'.", - )); - } - } - - // Transform - DataTree::Leaf { - type_name, - contents, - byte_offset, - } if type_name == "Transform" => { - if let Ok(mat) = parse_matrix(&contents) { - mats.push(mat); - } else { - // Found Transform, but its contents is not in the right format - return Err(make_transform_format_error(*byte_offset)); - } - } - - _ => {} - } - } - - return Ok(Camera::new( - arena, - &mats, - &fovs, - &aperture_radii, - &focus_distances, - )); - } else { - return Err(PsyParseError::ExpectedInternalNode( - tree.byte_offset(), - "Camera section should be an internal \ - node, containing at least Fov and \ - Transform.", - )); + // return Err(PsyParseError::MissingNode( + // tree.byte_offset(), + // "Output section must contain a Path.", + // )); + todo!(); // Return error. } } -fn parse_world<'a>(arena: &'a Arena, tree: &'a DataTree) -> Result, PsyParseError> { - if tree.is_internal() { - let background_color; - let mut lights: Vec<&dyn WorldLightSource> = Vec::new(); - - // Parse background shader - let bgs = { - if tree.iter_children_with_type("BackgroundShader").count() != 1 { - return Err(PsyParseError::WrongNodeCount( - tree.byte_offset(), - "World should have precisely one BackgroundShader section.", - tree.iter_children_with_type("BackgroundShader").count(), - )); - } - tree.iter_children_with_type("BackgroundShader") - .nth(0) - .unwrap() - }; - let bgs_type = { - if bgs.iter_children_with_type("Type").count() != 1 { - return Err(PsyParseError::WrongNodeCount( - bgs.byte_offset(), - "BackgroundShader should have \ - precisely one Type specified.", - bgs.iter_children_with_type("Type").count(), - )); - } - if let DataTree::Leaf { contents, .. } = - bgs.iter_children_with_type("Type").nth(0).unwrap() - { - contents.trim() - } else { - return Err(PsyParseError::ExpectedLeafNode( - bgs.byte_offset(), - "BackgroundShader's Type should be a \ - leaf node.", - )); - } - }; - match bgs_type { - "Color" => { - if let Some(DataTree::Leaf { - contents, - byte_offset, - .. - }) = bgs.iter_children_with_type("Color").nth(0) +fn parse_render_settings( + events: &mut DataTreeReader, +) -> Result<((u32, u32), u32, u32), PsyParseError> { + let mut found_res = false; + let mut found_spp = false; + let mut res = (0, 0); + let mut spp = 0; + let mut seed = 0; + loop { + match events.next_event()? { + // Resolution + Event::Leaf { + type_name: "Resolution", + contents, + byte_offset, + } => { + if let IResult::Ok((_, (w, h))) = all_consuming(tuple((ws_u32, ws_u32)))(&contents) { - if let Ok(color) = parse_color(&contents) { - background_color = color; - } else { - return Err(PsyParseError::IncorrectLeafData( - *byte_offset, - "Color should be specified \ - with three decimal numbers \ - in the form '[R G B]'.", - )); - } + found_res = true; + res = (w, h); } else { - return Err(PsyParseError::MissingNode( - bgs.byte_offset(), - "BackgroundShader's Type is Color, \ - but no Color is specified.", + // Found Resolution, but its contents is not in the right format + return Err(PsyParseError::IncorrectLeafData( + *byte_offset, + "Resolution should be specified with two \ + integers in the form '[width height]'.", )); } } - _ => { - return Err(PsyParseError::UnknownVariant( - bgs.byte_offset(), - "The specified BackgroundShader Type \ - isn't a recognized type.", - )) - } - } - - // Parse light sources - for child in tree.iter_children() { - match child { - DataTree::Internal { type_name, .. } if type_name == "DistantDiskLight" => { - lights.push(arena.alloc(parse_distant_disk_light(arena, child)?)); + // SamplesPerPixel + DataTree::Leaf { + type_name: "SamplesPerPixel", + contents, + byte_offset, + } => { + if let IResult::Ok((_, n)) = all_consuming(ws_u32)(&contents) { + found_spp = true; + spp = n; + } else { + // Found SamplesPerPixel, but its contents is not in the right format + return Err(PsyParseError::IncorrectLeafData( + *byte_offset, + "SamplesPerPixel should be \ + an integer specified in \ + the form '[samples]'.", + )); } + } - _ => {} + // Seed + DataTree::Leaf { + type_name: "Seed", + contents, + byte_offset, + } => { + if let IResult::Ok((_, n)) = all_consuming(ws_u32)(&contents) { + seed = n; + } else { + // Found Seed, but its contents is not in the right format + return Err(PsyParseError::IncorrectLeafData( + *byte_offset, + "Seed should be an integer \ + specified in the form \ + '[samples]'.", + )); + } + } + + Event::InnerClose { .. } => { + break; + } + + _ => { + todo!(); // Return error. } } + } - // Build and return the world - return Ok(World { - background_color: background_color, - lights: arena.copy_slice(&lights), - }); + if found_res && found_spp { + return Ok((res, spp, seed)); } else { - return Err(PsyParseError::ExpectedInternalNode( - tree.byte_offset(), - "World section should be an internal \ - node, containing at least a \ - BackgroundShader.", - )); + // return Err(PsyParseError::MissingNode( + // tree.byte_offset(), + // "RenderSettings must have both Resolution and \ + // SamplesPerPixel specified.", + // )); + todo!(); // Return error. } } -fn parse_shaders<'a>( - tree: &'a DataTree, -) -> Result>, PsyParseError> { - if tree.is_internal() { - let mut shaders = HashMap::new(); +fn parse_camera<'a>( + arena: &'a Arena, + events: &mut DataTreeReader, +) -> Result, PsyParseError> { + let mut mats = Vec::new(); + let mut fovs = Vec::new(); + let mut focus_distances = Vec::new(); + let mut aperture_radii = Vec::new(); - for shader_item in tree.iter_children() { - match shader_item { - DataTree::Internal { - type_name, - ident, - children, - byte_offset, - } if type_name == &"SurfaceShader" => { - if let Some(name) = ident { - shaders.insert(name.to_string(), parse_surface_shader(shader_item)?); - } else { - // TODO: error. + // Parse + loop { + match events.next_event()? { + // Fov + Event::Leaf { + type_name: "Fov", + contents, + byte_offset, + } => { + if let IResult::Ok((_, fov)) = all_consuming(ws_f32)(&contents) { + fovs.push(fov * (f32::consts::PI / 180.0)); + } else { + // Found Fov, but its contents is not in the right format + return Err(PsyParseError::IncorrectLeafData( + *byte_offset, + "Fov should be a decimal \ + number specified in the \ + form '[fov]'.", + )); + } + } + + // FocalDistance + Event::Leaf { + type_name: "FocalDistance", + contents, + byte_offset, + } => { + if let IResult::Ok((_, fd)) = all_consuming(ws_f32)(&contents) { + focus_distances.push(fd); + } else { + // Found FocalDistance, but its contents is not in the right format + return Err(PsyParseError::IncorrectLeafData( + *byte_offset, + "FocalDistance should be a \ + decimal number specified \ + in the form '[fov]'.", + )); + } + } + + // ApertureRadius + Event::Leaf { + type_name: "ApertureRadius", + contents, + byte_offset, + } => { + if let IResult::Ok((_, ar)) = all_consuming(ws_f32)(&contents) { + aperture_radii.push(ar); + } else { + // Found ApertureRadius, but its contents is not in the right format + return Err(PsyParseError::IncorrectLeafData( + *byte_offset, + "ApertureRadius should be a \ + decimal number specified \ + in the form '[fov]'.", + )); + } + } + + // Transform + Event::Leaf { + type_name: "Transform", + contents, + byte_offset, + } => { + if let Ok(mat) = parse_matrix(&contents) { + mats.push(mat); + } else { + // Found Transform, but its contents is not in the right format + return Err(make_transform_format_error(*byte_offset)); + } + } + + Event::InnerClose { .. } => { + break; + } + + _ => { + todo!(); // Return error. + } + } + } + + return Ok(Camera::new( + arena, + &mats, + &fovs, + &aperture_radii, + &focus_distances, + )); +} + +fn parse_world<'a>( + arena: &'a Arena, + events: &mut DataTreeReader, +) -> Result, PsyParseError> { + let background_color = None; + let mut lights: Vec<&dyn WorldLightSource> = Vec::new(); + + loop { + match events.next_event()? { + // Parse background shader + Event::InnerOpen { + type_name: "BackgroundShader", + } => { + let bgs_type = if let Event::Leaf { + type_name: "Type", + contents, + .. + } = events.next_event() + { + contents.into::() + } else { + todo!(); // Return error. + }; + + match bgs_type { + "Color" => { + if let Event::Leaf { + type_name: "Color", + contents, + .. + } = events.next_event() + { + background_color = Some(parse_color(contents)?); + } else { + todo!( + "BackgroundShader's Type is Color, \ + but no Color is specified." + ); // Return error. + }; + } + + _ => { + todo!( + "The specified BackgroundShader Type \ + isn't a recognized type.", + ); // Return an error. } } - _ => { - // TODO: an error. + // Close it out. + if let Event::InnerClose { .. } = events.next_event() { + } else { + todo!(); // Return error. } } - } - // Return the list of shaders. - return Ok(shaders); - } else { - return Err(PsyParseError::ExpectedInternalNode( - tree.byte_offset(), - "Shaders section should be an internal \ - node.", - )); + // Parse light sources + Event::InnerOpen { + type_name: "DistantDiskLight", + .. + } => { + lights.push(arena.alloc(parse_distant_disk_light(arena, events)?)); + } + } } + + if background_color == None { + todo!(); // Return error. + } + + // Build and return the world + return Ok(World { + background_color: background_color.unwrap(), + lights: arena.copy_slice(&lights), + }); +} + +fn parse_shaders<'a>( + events: &mut DataTreeReader, +) -> Result>, PsyParseError> { + let mut shaders = HashMap::new(); + loop { + match events.next_event() { + DataTree::Internal { + type_name: "SurfaceShader", + ident, + byte_offset, + } => { + if let Some(name) = ident { + let name = name.to_string(); + shaders.insert(name, parse_surface_shader(events)?); + } else { + todo!("Shader has no name."); // Return error. + } + } + + _ => { + todo!(); // Return error. + } + } + } + + // Return the list of shaders. + return Ok(shaders); } pub fn parse_matrix(contents: &str) -> Result { @@ -621,7 +594,7 @@ pub fn parse_matrix(contents: &str) -> Result { } } - return Err(PsyParseError::UnknownError(0)); + todo!(); // Return an error. } pub fn make_transform_format_error(byte_offset: usize) -> PsyParseError { @@ -635,7 +608,7 @@ pub fn make_transform_format_error(byte_offset: usize) -> PsyParseError { pub fn parse_color(contents: &str) -> Result { let items: Vec<_> = contents.split(',').map(|s| s.trim()).collect(); if items.len() != 2 { - return Err(PsyParseError::UnknownError(0)); + todo!(); // Return an error. } match items[0] { @@ -643,7 +616,7 @@ pub fn parse_color(contents: &str) -> Result { if let IResult::Ok((_, color)) = tuple((ws_f32, ws_f32, ws_f32))(items[1]) { return Ok(Color::new_xyz(rec709_e_to_xyz(color))); } else { - return Err(PsyParseError::UnknownError(0)); + todo!(); // Return an error. } } @@ -651,7 +624,7 @@ pub fn parse_color(contents: &str) -> Result { if let IResult::Ok((_, (temperature, factor))) = tuple((ws_f32, ws_f32))(items[1]) { return Ok(Color::new_blackbody(temperature, factor)); } else { - return Err(PsyParseError::UnknownError(0)); + todo!(); // Return an error. } } @@ -659,10 +632,12 @@ pub fn parse_color(contents: &str) -> Result { if let IResult::Ok((_, (temperature, factor))) = tuple((ws_f32, ws_f32))(items[1]) { return Ok(Color::new_temperature(temperature, factor)); } else { - return Err(PsyParseError::UnknownError(0)); + todo!(); // Return an error. } } - _ => return Err(PsyParseError::UnknownError(0)), + _ => { + todo!(); // Return an error. + } } } diff --git a/src/parse/psy_assembly.rs b/src/parse/psy_assembly.rs index dc3ad0c..1e37d89 100644 --- a/src/parse/psy_assembly.rs +++ b/src/parse/psy_assembly.rs @@ -4,6 +4,11 @@ use std::result::Result; use kioku::Arena; +use data_tree::{ + reader::{DataTreeReader, ReaderError}, + Event, +}; + use crate::scene::{Assembly, Object, ObjectData}; use super::{ @@ -15,7 +20,8 @@ use super::{ pub fn parse_assembly<'a>( arena: &'a Arena, - tree: &'a DataTree, + events: &mut DataTreeReader, + ident: Option<&str>, ) -> Result, PsyParseError> { if !tree.is_internal() { return Err(PsyParseError::UnknownError(tree.byte_offset())); diff --git a/src/parse/psy_light.rs b/src/parse/psy_light.rs index df59820..86c8254 100644 --- a/src/parse/psy_light.rs +++ b/src/parse/psy_light.rs @@ -6,6 +6,11 @@ use nom::{combinator::all_consuming, sequence::tuple, IResult}; use kioku::Arena; +use data_tree::{ + reader::{DataTreeReader, ReaderError}, + Event, +}; + use crate::{ light::{DistantDiskLight, RectangleLight, SphereLight}, math::Vector, @@ -19,7 +24,8 @@ use super::{ pub fn parse_distant_disk_light<'a>( arena: &'a Arena, - tree: &'a DataTree, + events: &mut DataTreeReader, + ident: Option<&str>, ) -> Result, PsyParseError> { if let DataTree::Internal { ref children, .. } = *tree { let mut radii = Vec::new(); @@ -85,7 +91,8 @@ pub fn parse_distant_disk_light<'a>( pub fn parse_sphere_light<'a>( arena: &'a Arena, - tree: &'a DataTree, + events: &mut DataTreeReader, + ident: Option<&str>, ) -> Result, PsyParseError> { if let DataTree::Internal { ref children, .. } = *tree { let mut radii = Vec::new(); @@ -134,7 +141,8 @@ pub fn parse_sphere_light<'a>( pub fn parse_rectangle_light<'a>( arena: &'a Arena, - tree: &'a DataTree, + events: &mut DataTreeReader, + ident: Option<&str>, ) -> Result, PsyParseError> { if let DataTree::Internal { ref children, .. } = *tree { let mut dimensions = Vec::new(); diff --git a/src/parse/psy_mesh_surface.rs b/src/parse/psy_mesh_surface.rs index c435ca1..69f82ab 100644 --- a/src/parse/psy_mesh_surface.rs +++ b/src/parse/psy_mesh_surface.rs @@ -6,6 +6,11 @@ use nom::{sequence::tuple, IResult}; use kioku::Arena; +use data_tree::{ + reader::{DataTreeReader, ReaderError}, + Event, +}; + use crate::{ math::{Normal, Point}, surface::triangle_mesh::TriangleMesh, @@ -26,7 +31,8 @@ use super::{ pub fn parse_mesh_surface<'a>( arena: &'a Arena, - tree: &'a DataTree, + events: &mut DataTreeReader, + ident: Option<&str>, ) -> Result, PsyParseError> { let mut verts = Vec::new(); // Vec of vecs, one for each time sample let mut normals = Vec::new(); // Vec of vecs, on for each time sample diff --git a/src/parse/psy_surface_shader.rs b/src/parse/psy_surface_shader.rs index a934d9f..8f7b38f 100644 --- a/src/parse/psy_surface_shader.rs +++ b/src/parse/psy_surface_shader.rs @@ -4,6 +4,11 @@ use std::result::Result; use nom::{combinator::all_consuming, IResult}; +use data_tree::{ + reader::{DataTreeReader, ReaderError}, + Event, +}; + use crate::shading::{SimpleSurfaceShader, SurfaceShader}; use super::{ @@ -19,7 +24,10 @@ use super::{ // accel: BVH, // } -pub fn parse_surface_shader(tree: &DataTree) -> Result, PsyParseError> { +pub fn parse_surface_shader( + events: &mut DataTreeReader, + ident: Option<&str>, +) -> Result, PsyParseError> { let type_name = if let Some((_, text, _)) = tree.iter_leaf_children_with_type("Type").nth(0) { text.trim() } else {