From 4f564d14747cd43a9fe8a3a7180ad30a17232b78 Mon Sep 17 00:00:00 2001 From: Nathan Vegdahl Date: Fri, 10 Jan 2020 22:31:39 +0900 Subject: [PATCH] All parsing is now streaming! But lots left to do. In particular, parsing error messages are now either terrible or non-existent. But it compiles and works for correct inputs! --- example_scenes/cornell_box.psy | 24 +-- example_scenes/cube.psy | 20 +-- src/color.rs | 2 +- src/main.rs | 50 +++--- src/parse/data_tree.rs | 5 +- src/parse/mod.rs | 4 +- src/parse/psy.rs | 136 ++++++++------- src/parse/psy_assembly.rs | 189 +++++++++++--------- src/parse/psy_light.rs | 266 ++++++++++++++--------------- src/parse/psy_mesh_surface.rs | 140 +++++++++------ src/parse/psy_surface_shader.rs | 199 +++++++++++++-------- sub_crates/data_tree/src/lib.rs | 52 +++++- sub_crates/data_tree/src/reader.rs | 37 ++++ 13 files changed, 677 insertions(+), 447 deletions(-) diff --git a/example_scenes/cornell_box.psy b/example_scenes/cornell_box.psy index 1b71f09..eb357da 100644 --- a/example_scenes/cornell_box.psy +++ b/example_scenes/cornell_box.psy @@ -7,18 +7,6 @@ Scene $Scene_fr1 { SamplesPerPixel [16] Seed [1] } - Camera { - Fov [39.449188] - FocalDistance [10.62] - ApertureRadius [0.0] - Transform [1.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 -2.779998 -8.000000 2.730010 1.0] - } - World { - BackgroundShader { - Type [Color] - Color [rec709, 0.0 0.0 0.0] - } - } Shaders { SurfaceShader $Green { Type [Lambert] @@ -33,6 +21,18 @@ Scene $Scene_fr1 { Color [rec709, 0.7295 0.7355 0.729] } } + World { + BackgroundShader { + Type [Color] + Color [rec709, 0.0 0.0 0.0] + } + } + Camera { + Fov [39.449188] + FocalDistance [10.62] + ApertureRadius [0.0] + Transform [1.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 -2.779998 -8.000000 2.730010 1.0] + } Assembly { Object $__Area { Instance { diff --git a/example_scenes/cube.psy b/example_scenes/cube.psy index 6154709..35f3ff0 100644 --- a/example_scenes/cube.psy +++ b/example_scenes/cube.psy @@ -7,11 +7,11 @@ Scene $Scene_fr1 { SamplesPerPixel [16] Seed [1] } - Camera { - Fov [49.134342] - FocalDistance [9.56] - ApertureRadius [0.25] - Transform [0.685881 0.727634 -0.010817 0.0 -0.317370 0.312469 0.895343 0.0 -0.654862 0.610666 -0.445245 0.0 7.481132 -6.507640 5.343665 1.0] + Shaders { + SurfaceShader $Material { + Type [Lambert] + Color [rec709, 0.8 0.8 0.8] + } } World { BackgroundShader { @@ -19,11 +19,11 @@ Scene $Scene_fr1 { Color [rec709, 0.050876 0.050876 0.050876] } } - Shaders { - SurfaceShader $Material { - Type [Lambert] - Color [rec709, 0.8 0.8 0.8] - } + Camera { + Fov [49.134342] + FocalDistance [9.56] + ApertureRadius [0.25] + Transform [0.685881 0.727634 -0.010817 0.0 -0.317370 0.312469 0.895343 0.0 -0.654862 0.610666 -0.445245 0.0 7.481132 -6.507640 5.343665 1.0] } Assembly { Object $__Plane_ { diff --git a/src/color.rs b/src/color.rs index 178e47c..ff2cefb 100644 --- a/src/color.rs +++ b/src/color.rs @@ -44,7 +44,7 @@ fn wavelengths(hero_wavelength: f32) -> Vec4 { //---------------------------------------------------------------- -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, PartialEq)] pub enum Color { XYZ(f32, f32, f32), Blackbody { diff --git a/src/main.rs b/src/main.rs index f39abae..2f1b2ba 100644 --- a/src/main.rs +++ b/src/main.rs @@ -47,15 +47,12 @@ use nom::bytes::complete::take_until; use kioku::Arena; -use data_tree::{ - reader::{DataTreeReader, ReaderError}, - Event, -}; +use data_tree::{reader::DataTreeReader, Event}; use crate::{ accel::BVH4Node, bbox::BBox, - parse::{parse_scene, DataTree}, + parse::parse_scene, // renderer::LightPath, surface::SurfaceIntersection, timer::Timer, @@ -242,27 +239,14 @@ fn main() { // println!("\tParsed scene file in {:.3}s", t.tick()); // } - let mut psy_file = io::BufReader::new(File::open(fp).unwrap()); + let file_path = args.value_of("input").unwrap(); + let mut psy_file = io::BufReader::new(File::open(file_path).unwrap()); let mut events = DataTreeReader::new(&mut psy_file); // Iterate through scenes and render them 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", @@ -274,11 +258,13 @@ fn main() { } let arena = Arena::new().with_block_size((1 << 20) * 4); - let ident = ident.into::(); - let mut scene = parse_scene(&arena, &mut events, &ident).unwrap_or_else(|e| { - e.print(&psy_contents); - panic!("Parse error."); - }); + let ident = ident.map(|v| v.to_string()); + let scene = + parse_scene(&arena, &mut events, ident.as_deref()).unwrap_or_else(|e| { + println!("Parse error: {}", e); + // e.print(&psy_contents); + panic!("Parse error."); + }); if let Some(spp) = args.value_of("spp") { if !args.is_present("serialized_output") { @@ -384,6 +370,20 @@ fn main() { // println!("\tTotal blocks: {}", arena_stats.2); // } } + + Ok(Event::ValidEnd) => { + break; + } + + Err(e) => { + println!("Error: {:?}", e); + break; + } + + Ok(_) => { + println!("Error: invalid scene in psy file."); + break; + } } } diff --git a/src/parse/data_tree.rs b/src/parse/data_tree.rs index e63f84d..937c747 100644 --- a/src/parse/data_tree.rs +++ b/src/parse/data_tree.rs @@ -2,10 +2,7 @@ use std::{io::Cursor, iter::Iterator, result::Result, slice}; -use data_tree::{ - reader::{DataTreeReader, ReaderError}, - Event, -}; +use data_tree::{reader::DataTreeReader, Event}; #[derive(Debug, Eq, PartialEq)] pub enum DataTree { diff --git a/src/parse/mod.rs b/src/parse/mod.rs index a76ad59..ea4f1d8 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -1,9 +1,9 @@ pub mod basics; -mod data_tree; +// mod data_tree; mod psy; mod psy_assembly; mod psy_light; mod psy_mesh_surface; mod psy_surface_shader; -pub use self::{data_tree::DataTree, psy::parse_scene}; +pub use self::psy::parse_scene; diff --git a/src/parse/psy.rs b/src/parse/psy.rs index 6edde25..6655495 100644 --- a/src/parse/psy.rs +++ b/src/parse/psy.rs @@ -26,7 +26,6 @@ use super::{ psy_assembly::parse_assembly, psy_light::parse_distant_disk_light, psy_surface_shader::parse_surface_shader, - DataTree, }; #[derive(Debug)] @@ -34,13 +33,13 @@ pub enum PsyParseError { // The first usize for all errors is their byte offset // into the psy content where they occured. UnknownError(usize), - UnknownVariant(usize, &'static str), // Error message - ExpectedInternalNode(usize, &'static str), // Error message - ExpectedLeafNode(usize, &'static str), // Error message - ExpectedIdent(usize, &'static str), // Error message - MissingNode(usize, &'static str), // Error message - IncorrectLeafData(usize, &'static str), // Error message - WrongNodeCount(usize, &'static str, usize), // Error message, sections found + UnknownVariant(usize, &'static str), // Error message + ExpectedInternalNode(usize, &'static str), // Error message + ExpectedLeafNode(usize, &'static str), // Error message + ExpectedIdent(usize, &'static str), // Error message + MissingNode(usize, &'static str), // Error message + IncorrectLeafData(usize, &'static str), // Error message + WrongNodeCount(usize, &'static str), // Error message InstancedMissingData(usize, &'static str, String), // Error message, data name ReaderError(ReaderError), } @@ -87,15 +86,17 @@ impl PsyParseError { println!("Line {}: {}", line, error); } - PsyParseError::WrongNodeCount(offset, error, count) => { + PsyParseError::WrongNodeCount(offset, error) => { let line = line_count_to_byte_offset(psy_content, offset); - println!("Line {}: {} Found: {}", line, error, count); + println!("Line {}: {}", line, error); } PsyParseError::InstancedMissingData(offset, error, ref data_name) => { let line = line_count_to_byte_offset(psy_content, offset); println!("Line {}: {} Data name: '{}'", line, error, data_name); } + + _ => todo!(), } } } @@ -124,10 +125,10 @@ fn line_count_to_byte_offset(text: &str, offset: usize) -> usize { pub fn parse_scene<'a>( arena: &'a Arena, events: &mut DataTreeReader, - ident: Option<&str>, + _ident: Option<&str>, ) -> Result, PsyParseError> { // Get output info. - let output_info = if let Event::InnerOpen { + let _output_info = if let Event::InnerOpen { type_name: "Output", .. } = events.next_event()? @@ -138,7 +139,7 @@ pub fn parse_scene<'a>( }; // Get render settings. - let render_settings = if let Event::InnerOpen { + let _render_settings = if let Event::InnerOpen { type_name: "RenderSettings", .. } = events.next_event()? @@ -148,17 +149,6 @@ pub fn parse_scene<'a>( todo!(); // Return error. }; - // Get camera. - let camera = if let Event::InnerOpen { - type_name: "Camera", - .. - } = events.next_event()? - { - parse_camera(arena, events)? - } else { - todo!(); // Return error. - }; - // Get shaders. let shaders = if let Event::InnerOpen { type_name: "Shaders", @@ -180,14 +170,24 @@ pub fn parse_scene<'a>( todo!(); // Return error. }; - // Get the root assembly. - let root_assembly = if let Event::InnerOpen { - type_name: "Assembly", - ident, + // Get camera. + let camera = if let Event::InnerOpen { + type_name: "Camera", .. } = events.next_event()? { - parse_assembly(arena, events, &(ident.into::()))? + parse_camera(arena, events)? + } else { + todo!(); // Return error. + }; + + // Get the root assembly. + let root_assembly = if let Event::InnerOpen { + type_name: "Assembly", + .. + } = events.next_event()? + { + parse_assembly(arena, events)? } else { todo!(); // Return error. }; @@ -199,12 +199,11 @@ pub fn parse_scene<'a>( } // Put scene together - let scene_name = if let Some(name) = ident { - Some(name.into()) - } else { - None - }; - + // let scene_name = if let Some(name) = ident { + // Some(name.into()) + // } else { + // None + // }; let scene = Scene { camera: camera, world: world, @@ -241,13 +240,13 @@ fn parse_output_info(events: &mut DataTreeReader) -> Result( } else { // Found Fov, but its contents is not in the right format return Err(PsyParseError::IncorrectLeafData( - *byte_offset, + byte_offset, "Fov should be a decimal \ number specified in the \ form '[fov]'.", @@ -414,7 +413,7 @@ fn parse_camera<'a>( } else { // Found FocalDistance, but its contents is not in the right format return Err(PsyParseError::IncorrectLeafData( - *byte_offset, + byte_offset, "FocalDistance should be a \ decimal number specified \ in the form '[fov]'.", @@ -433,7 +432,7 @@ fn parse_camera<'a>( } else { // Found ApertureRadius, but its contents is not in the right format return Err(PsyParseError::IncorrectLeafData( - *byte_offset, + byte_offset, "ApertureRadius should be a \ decimal number specified \ in the form '[fov]'.", @@ -451,7 +450,7 @@ fn parse_camera<'a>( mats.push(mat); } else { // Found Transform, but its contents is not in the right format - return Err(make_transform_format_error(*byte_offset)); + return Err(make_transform_format_error(byte_offset)); } } @@ -478,7 +477,7 @@ fn parse_world<'a>( arena: &'a Arena, events: &mut DataTreeReader, ) -> Result, PsyParseError> { - let background_color = None; + let mut background_color = None; let mut lights: Vec<&dyn WorldLightSource> = Vec::new(); loop { @@ -486,25 +485,26 @@ fn parse_world<'a>( // Parse background shader Event::InnerOpen { type_name: "BackgroundShader", + .. } => { let bgs_type = if let Event::Leaf { type_name: "Type", contents, .. - } = events.next_event() + } = events.next_event()? { - contents.into::() + contents.to_string() } else { todo!(); // Return error. }; - match bgs_type { + match bgs_type.as_ref() { "Color" => { if let Event::Leaf { type_name: "Color", contents, .. - } = events.next_event() + } = events.next_event()? { background_color = Some(parse_color(contents)?); } else { @@ -524,7 +524,7 @@ fn parse_world<'a>( } // Close it out. - if let Event::InnerClose { .. } = events.next_event() { + if let Event::InnerClose { .. } = events.next_event()? { } else { todo!(); // Return error. } @@ -533,9 +533,23 @@ fn parse_world<'a>( // Parse light sources Event::InnerOpen { type_name: "DistantDiskLight", + ident, .. } => { - lights.push(arena.alloc(parse_distant_disk_light(arena, events)?)); + let ident = ident.map(|v| v.to_string()); + lights.push(arena.alloc(parse_distant_disk_light( + arena, + events, + ident.as_deref(), + )?)); + } + + Event::InnerClose { .. } => { + break; + } + + _ => { + todo!(); // Return error. } } } @@ -552,24 +566,32 @@ fn parse_world<'a>( } fn parse_shaders<'a>( + arena: &'a Arena, events: &mut DataTreeReader, ) -> Result>, PsyParseError> { let mut shaders = HashMap::new(); loop { - match events.next_event() { - DataTree::Internal { + match events.next_event()? { + Event::InnerOpen { type_name: "SurfaceShader", ident, - byte_offset, + .. } => { if let Some(name) = ident { let name = name.to_string(); - shaders.insert(name, parse_surface_shader(events)?); + shaders.insert( + name.clone(), + parse_surface_shader(arena, events, Some(&name))?, + ); } else { todo!("Shader has no name."); // Return error. } } + Event::InnerClose { .. } => { + break; + } + _ => { todo!(); // Return error. } diff --git a/src/parse/psy_assembly.rs b/src/parse/psy_assembly.rs index 1e37d89..b5ca346 100644 --- a/src/parse/psy_assembly.rs +++ b/src/parse/psy_assembly.rs @@ -1,13 +1,10 @@ #![allow(dead_code)] -use std::result::Result; +use std::{io::BufRead, result::Result}; use kioku::Arena; -use data_tree::{ - reader::{DataTreeReader, ReaderError}, - Event, -}; +use data_tree::{reader::DataTreeReader, Event}; use crate::scene::{Assembly, Object, ObjectData}; @@ -15,101 +12,137 @@ use super::{ psy::{parse_matrix, PsyParseError}, psy_light::{parse_rectangle_light, parse_sphere_light}, psy_mesh_surface::parse_mesh_surface, - DataTree, }; pub fn parse_assembly<'a>( arena: &'a Arena, - events: &mut DataTreeReader, - ident: Option<&str>, + events: &mut DataTreeReader, ) -> Result, PsyParseError> { - if !tree.is_internal() { - return Err(PsyParseError::UnknownError(tree.byte_offset())); - } - let mut assembly = Assembly::new(); - for object in tree.iter_children() { - if object.type_name() == "Object" { - // Get object identifier. - let object_ident = if let Some(ident) = object.ident() { - ident - } else { - return Err(PsyParseError::ExpectedIdent( - object.byte_offset(), - "\'Object\' types must have an identifier, but the identifier is missing.", - )); - }; - - // Collect instances. - let mut instance_xform_idxs = Vec::new(); - for instance in object.iter_children_with_type("Instance") { - if !instance.is_internal() { - // TODO: error. - } - - let xforms_start_idx = assembly.xforms.len(); - for (_, contents, _) in instance.iter_leaf_children_with_type("Transform") { - assembly.xforms.push(parse_matrix(contents)?); - } - instance_xform_idxs.push(xforms_start_idx..assembly.xforms.len()); - } - - // Get object data. - let object_data = { - let obj_data_tree = { - if object - .iter_children() - .filter(|d| d.type_name() != "Instance") - .count() - != 1 - { - // TODO: error. - } - object - .iter_children() - .filter(|d| d.type_name() != "Instance") - .nth(0) - .unwrap() + loop { + match events.next_event()? { + Event::InnerOpen { + type_name: "Object", + ident, + byte_offset, + } => { + // Get object identifier. + let object_ident = if let Some(id) = ident { + id.to_string() + } else { + return Err(PsyParseError::ExpectedIdent( + byte_offset, + "\'Object\' types must have an identifier, but the identifier is missing.", + )); }; - match obj_data_tree.type_name() { - // Sub-Assembly - "Assembly" => { - ObjectData::Assembly(Box::new(parse_assembly(arena, obj_data_tree)?)) + // Collect instances. + let mut instance_xform_idxs = Vec::new(); + while let Event::InnerOpen { + type_name: "Instance", + .. + } = events.peek_event()? + { + events.next_event(); + let xforms_start_idx = assembly.xforms.len(); + loop { + match events.next_event()? { + Event::Leaf { + type_name: "Transform", + contents, + .. + } => { + assembly.xforms.push(parse_matrix(contents)?); + } + + Event::InnerClose { .. } => { + break; + } + + _ => { + todo!("Instances can only contain Transforms."); + // Return an error. + } + } } - "MeshSurface" => { - ObjectData::Surface(Box::new(parse_mesh_surface(arena, obj_data_tree)?)) - } + instance_xform_idxs.push(xforms_start_idx..assembly.xforms.len()); + } - "SphereLight" => { - ObjectData::Light(Box::new(parse_sphere_light(arena, obj_data_tree)?)) - } + // Get object data. + let object_data = match events.next_event()? { + Event::InnerOpen { + type_name: "Assembly", + .. + } => ObjectData::Assembly(Box::new(parse_assembly(arena, events)?)), - "RectangleLight" => { - ObjectData::Light(Box::new(parse_rectangle_light(arena, obj_data_tree)?)) + Event::InnerOpen { + type_name: "MeshSurface", + .. + } => ObjectData::Surface(Box::new(parse_mesh_surface(arena, events)?)), + + Event::InnerOpen { + type_name: "SphereLight", + .. + } => ObjectData::Light(Box::new(parse_sphere_light(arena, events)?)), + + Event::InnerOpen { + type_name: "RectangleLight", + .. + } => ObjectData::Light(Box::new(parse_rectangle_light(arena, events)?)), + + Event::InnerClose { byte_offset } => { + return Err(PsyParseError::MissingNode( + byte_offset, + "Object contains no object data.", + )); } _ => { return Err(PsyParseError::UnknownVariant( - tree.byte_offset(), + byte_offset, "Unknown data type for Object.", )); } - } - }; + }; - assembly.objects.insert( - object_ident.to_string(), - Object { - data: object_data, - instance_xform_idxs: instance_xform_idxs, - }, - ); - } else { - // TODO: error. + // Close object node. + if let Event::InnerClose { .. } = events.next_event()? { + // Success, do nothing. + } else { + todo!(); // Return error. + } + + assembly.objects.insert( + object_ident, + Object { + data: object_data, + instance_xform_idxs: instance_xform_idxs, + }, + ); + } + + Event::InnerClose { .. } => { + break; + } + + _ => { + todo!(); // Return an error. + } } } + // if !tree.is_internal() { + // return Err(PsyParseError::UnknownError(tree.byte_offset())); + // } + + // for object in tree.iter_children() { + // if object.type_name() == "Object" { + + // } else { + // // TODO: error. + // } + // } + return Ok(assembly); } diff --git a/src/parse/psy_light.rs b/src/parse/psy_light.rs index 86c8254..3b37329 100644 --- a/src/parse/psy_light.rs +++ b/src/parse/psy_light.rs @@ -1,15 +1,12 @@ #![allow(dead_code)] -use std::result::Result; +use std::{io::BufRead, result::Result}; use nom::{combinator::all_consuming, sequence::tuple, IResult}; use kioku::Arena; -use data_tree::{ - reader::{DataTreeReader, ReaderError}, - Event, -}; +use data_tree::{reader::DataTreeReader, Event}; use crate::{ light::{DistantDiskLight, RectangleLight, SphereLight}, @@ -19,174 +16,175 @@ use crate::{ use super::{ basics::ws_f32, psy::{parse_color, PsyParseError}, - DataTree, }; pub fn parse_distant_disk_light<'a>( arena: &'a Arena, - events: &mut DataTreeReader, - ident: Option<&str>, + events: &mut DataTreeReader, + _ident: Option<&str>, ) -> Result, PsyParseError> { - if let DataTree::Internal { ref children, .. } = *tree { - let mut radii = Vec::new(); - let mut directions = Vec::new(); - let mut colors = Vec::new(); + let mut radii = Vec::new(); + let mut directions = Vec::new(); + let mut colors = Vec::new(); - // Parse - for child in children.iter() { - match child { - // Radius - DataTree::Leaf { - type_name, - contents, - byte_offset, - } if type_name == "Radius" => { - if let IResult::Ok((_, radius)) = all_consuming(ws_f32)(&contents) { - radii.push(radius); - } else { - // Found radius, but its contents is not in the right format - return Err(PsyParseError::UnknownError(*byte_offset)); - } + // Parse + loop { + match events.next_event()? { + Event::Leaf { + type_name: "Radius", + contents, + byte_offset, + } => { + if let IResult::Ok((_, radius)) = all_consuming(ws_f32)(&contents) { + radii.push(radius); + } else { + // Found radius, but its contents is not in the right format + return Err(PsyParseError::UnknownError(byte_offset)); } + } - // Direction - DataTree::Leaf { - type_name, - contents, - byte_offset, - } if type_name == "Direction" => { - if let IResult::Ok((_, direction)) = - all_consuming(tuple((ws_f32, ws_f32, ws_f32)))(&contents) - { - directions.push(Vector::new(direction.0, direction.1, direction.2)); - } else { - // Found direction, but its contents is not in the right format - return Err(PsyParseError::UnknownError(*byte_offset)); - } + // Direction + Event::Leaf { + type_name: "Direction", + contents, + byte_offset, + } => { + if let IResult::Ok((_, direction)) = + all_consuming(tuple((ws_f32, ws_f32, ws_f32)))(&contents) + { + directions.push(Vector::new(direction.0, direction.1, direction.2)); + } else { + // Found direction, but its contents is not in the right format + return Err(PsyParseError::UnknownError(byte_offset)); } + } - // Color - DataTree::Leaf { - type_name, - contents, - byte_offset, - } if type_name == "Color" => { - if let Ok(color) = parse_color(&contents) { - colors.push(color); - } else { - // Found color, but its contents is not in the right format - return Err(PsyParseError::UnknownError(*byte_offset)); - } + // Color + Event::Leaf { + type_name: "Color", + contents, + byte_offset, + } => { + if let Ok(color) = parse_color(&contents) { + colors.push(color); + } else { + // Found color, but its contents is not in the right format + return Err(PsyParseError::UnknownError(byte_offset)); } + } - _ => {} + Event::InnerClose { .. } => { + break; + } + + _ => { + todo!(); // Return error. } } - - return Ok(DistantDiskLight::new(arena, &radii, &directions, &colors)); - } else { - return Err(PsyParseError::UnknownError(tree.byte_offset())); } + + return Ok(DistantDiskLight::new(arena, &radii, &directions, &colors)); } pub fn parse_sphere_light<'a>( arena: &'a Arena, - events: &mut DataTreeReader, - ident: Option<&str>, + events: &mut DataTreeReader, ) -> Result, PsyParseError> { - if let DataTree::Internal { ref children, .. } = *tree { - let mut radii = Vec::new(); - let mut colors = Vec::new(); + let mut radii = Vec::new(); + let mut colors = Vec::new(); - // Parse - for child in children.iter() { - match child { - // Radius - DataTree::Leaf { - type_name, - contents, - byte_offset, - } if type_name == "Radius" => { - if let IResult::Ok((_, radius)) = all_consuming(ws_f32)(&contents) { - radii.push(radius); - } else { - // Found radius, but its contents is not in the right format - return Err(PsyParseError::UnknownError(*byte_offset)); - } + // Parse + loop { + match events.next_event()? { + // Radius + Event::Leaf { + type_name: "Radius", + contents, + byte_offset, + } => { + if let IResult::Ok((_, radius)) = all_consuming(ws_f32)(&contents) { + radii.push(radius); + } else { + // Found radius, but its contents is not in the right format + return Err(PsyParseError::UnknownError(byte_offset)); } + } - // Color - DataTree::Leaf { - type_name, - contents, - byte_offset, - } if type_name == "Color" => { - if let Ok(color) = parse_color(&contents) { - colors.push(color); - } else { - // Found color, but its contents is not in the right format - return Err(PsyParseError::UnknownError(*byte_offset)); - } + // Color + Event::Leaf { + type_name: "Color", + contents, + byte_offset, + } => { + if let Ok(color) = parse_color(&contents) { + colors.push(color); + } else { + // Found color, but its contents is not in the right format + return Err(PsyParseError::UnknownError(byte_offset)); } + } - _ => {} + Event::InnerClose { .. } => { + break; + } + + _ => { + todo!(); // Return error. } } - - return Ok(SphereLight::new(arena, &radii, &colors)); - } else { - return Err(PsyParseError::UnknownError(tree.byte_offset())); } + + return Ok(SphereLight::new(arena, &radii, &colors)); } pub fn parse_rectangle_light<'a>( arena: &'a Arena, - events: &mut DataTreeReader, - ident: Option<&str>, + events: &mut DataTreeReader, ) -> Result, PsyParseError> { - if let DataTree::Internal { ref children, .. } = *tree { - let mut dimensions = Vec::new(); - let mut colors = Vec::new(); + let mut dimensions = Vec::new(); + let mut colors = Vec::new(); - // Parse - for child in children.iter() { - match child { - // Dimensions - DataTree::Leaf { - type_name, - contents, - byte_offset, - } if type_name == "Dimensions" => { - if let IResult::Ok((_, radius)) = - all_consuming(tuple((ws_f32, ws_f32)))(&contents) - { - dimensions.push(radius); - } else { - // Found dimensions, but its contents is not in the right format - return Err(PsyParseError::UnknownError(*byte_offset)); - } + // Parse + loop { + match events.next_event()? { + // Dimensions + Event::Leaf { + type_name: "Dimensions", + contents, + byte_offset, + } => { + if let IResult::Ok((_, radius)) = all_consuming(tuple((ws_f32, ws_f32)))(&contents) + { + dimensions.push(radius); + } else { + // Found dimensions, but its contents is not in the right format + return Err(PsyParseError::UnknownError(byte_offset)); } + } - // Color - DataTree::Leaf { - type_name, - contents, - byte_offset, - } if type_name == "Color" => { - if let Ok(color) = parse_color(&contents) { - colors.push(color); - } else { - // Found color, but its contents is not in the right format - return Err(PsyParseError::UnknownError(*byte_offset)); - } + // Color + Event::Leaf { + type_name: "Color", + contents, + byte_offset, + } => { + if let Ok(color) = parse_color(&contents) { + colors.push(color); + } else { + // Found color, but its contents is not in the right format + return Err(PsyParseError::UnknownError(byte_offset)); } + } - _ => {} + Event::InnerClose { .. } => { + break; + } + + _ => { + todo!(); // Return error. } } - - return Ok(RectangleLight::new(arena, &dimensions, &colors)); - } else { - return Err(PsyParseError::UnknownError(tree.byte_offset())); } + + return Ok(RectangleLight::new(arena, &dimensions, &colors)); } diff --git a/src/parse/psy_mesh_surface.rs b/src/parse/psy_mesh_surface.rs index 69f82ab..8283f00 100644 --- a/src/parse/psy_mesh_surface.rs +++ b/src/parse/psy_mesh_surface.rs @@ -1,15 +1,12 @@ #![allow(dead_code)] -use std::result::Result; +use std::{io::BufRead, result::Result}; use nom::{sequence::tuple, IResult}; use kioku::Arena; -use data_tree::{ - reader::{DataTreeReader, ReaderError}, - Event, -}; +use data_tree::{reader::DataTreeReader, Event}; use crate::{ math::{Normal, Point}, @@ -19,7 +16,6 @@ use crate::{ use super::{ basics::{ws_f32, ws_usize}, psy::PsyParseError, - DataTree, }; // pub struct TriangleMesh { @@ -31,48 +27,108 @@ use super::{ pub fn parse_mesh_surface<'a>( arena: &'a Arena, - events: &mut DataTreeReader, - ident: Option<&str>, + events: &mut DataTreeReader, ) -> 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 let mut face_vert_counts = Vec::new(); let mut face_vert_indices = Vec::new(); - // TODO: make sure there are the right number of various children, - // and other validation. + loop { + match events.next_event()? { + Event::Leaf { + type_name: "SurfaceShaderBind", + .. + } => { + // TODO + } - // Get verts - for (_, mut text, _) in tree.iter_leaf_children_with_type("Vertices") { - // Collect verts for this time sample - let mut tverts = Vec::new(); - while let IResult::Ok((remaining, vert)) = tuple((ws_f32, ws_f32, ws_f32))(text) { - text = remaining; + Event::Leaf { + type_name: "Vertices", + contents, + .. + } => { + // Collect verts for this time sample + let mut text = contents; + let mut tverts = Vec::new(); + while let IResult::Ok((remaining, vert)) = tuple((ws_f32, ws_f32, ws_f32))(text) { + text = remaining; - tverts.push(Point::new(vert.0, vert.1, vert.2)); + tverts.push(Point::new(vert.0, vert.1, vert.2)); + } + verts.push(tverts); + } + + Event::Leaf { + type_name: "Normals", + contents, + .. + } => { + // Collect normals for this time sample + let mut text = contents; + let mut tnormals = Vec::new(); + while let IResult::Ok((remaining, nor)) = tuple((ws_f32, ws_f32, ws_f32))(text) { + text = remaining; + + tnormals.push(Normal::new(nor.0, nor.1, nor.2).normalized()); + } + normals.push(tnormals); + } + + Event::Leaf { + type_name: "FaceVertCounts", + contents, + byte_offset, + } => { + if !face_vert_counts.is_empty() { + return Err(PsyParseError::WrongNodeCount( + byte_offset, + "Meshes can only have one FaceVertCounts section.", + )); + } + let mut text = contents; + while let IResult::Ok((remaining, count)) = ws_usize(text) { + text = remaining; + face_vert_counts.push(count); + } + } + + Event::Leaf { + type_name: "FaceVertIndices", + contents, + byte_offset, + } => { + if !face_vert_indices.is_empty() { + return Err(PsyParseError::WrongNodeCount( + byte_offset, + "Meshes can only have one FaceVertIndices section.", + )); + } + let mut text = contents; + while let IResult::Ok((remaining, index)) = ws_usize(text) { + text = remaining; + face_vert_indices.push(index); + } + } + + Event::InnerClose { .. } => { + break; + } + + _ => { + todo!(); // Return error. + } } - verts.push(tverts); } - // Make sure all time samples have same vert count + // Validation: make sure all time samples have same vert count. let vert_count = verts[0].len(); for vs in &verts { assert_eq!(vert_count, vs.len()); } - // Get normals, if they exist - for (_, mut text, _) in tree.iter_leaf_children_with_type("Normals") { - // Collect normals for this time sample - let mut tnormals = Vec::new(); - while let IResult::Ok((remaining, nor)) = tuple((ws_f32, ws_f32, ws_f32))(text) { - text = remaining; - - tnormals.push(Normal::new(nor.0, nor.1, nor.2).normalized()); - } - normals.push(tnormals); - } - - // Make sure normal's time samples and vert count match the vertices + // Validation: make sure normal's time samples and vert count match + // the vertices. if !normals.is_empty() { assert_eq!(normals.len(), verts.len()); for ns in &normals { @@ -80,22 +136,10 @@ pub fn parse_mesh_surface<'a>( } } - // Get face vert counts - if let Some((_, mut text, _)) = tree.iter_leaf_children_with_type("FaceVertCounts").nth(0) { - while let IResult::Ok((remaining, count)) = ws_usize(text) { - text = remaining; - - face_vert_counts.push(count); - } - } - - // Get face vert indices - if let Some((_, mut text, _)) = tree.iter_leaf_children_with_type("FaceVertIndices").nth(0) { - while let IResult::Ok((remaining, index)) = ws_usize(text) { - text = remaining; - - face_vert_indices.push(index); - } + // Validation: make sure we have any mesh data. + if verts.is_empty() || face_vert_counts.is_empty() || face_vert_indices.is_empty() { + todo!("Meshes must have at least one non-empty of each of the following sections: Vertices, FaceVertCounts, FaceVertIndices."); + // Return an error. } // Build triangle mesh diff --git a/src/parse/psy_surface_shader.rs b/src/parse/psy_surface_shader.rs index 8f7b38f..cef7cbd 100644 --- a/src/parse/psy_surface_shader.rs +++ b/src/parse/psy_surface_shader.rs @@ -1,20 +1,18 @@ #![allow(dead_code)] -use std::result::Result; +use std::{io::BufRead, result::Result}; use nom::{combinator::all_consuming, IResult}; -use data_tree::{ - reader::{DataTreeReader, ReaderError}, - Event, -}; +use kioku::Arena; + +use data_tree::{reader::DataTreeReader, Event}; use crate::shading::{SimpleSurfaceShader, SurfaceShader}; use super::{ basics::ws_f32, psy::{parse_color, PsyParseError}, - DataTree, }; // pub struct TriangleMesh { @@ -25,22 +23,22 @@ use super::{ // } pub fn parse_surface_shader( - events: &mut DataTreeReader, - ident: Option<&str>, + _arena: &Arena, + 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 { - return Err(PsyParseError::MissingNode( - tree.byte_offset(), - "Expected a Type field in SurfaceShader.", - )); - }; - - let shader = match type_name { - "Lambert" => { - let color = if let Some((_, contents, byte_offset)) = - tree.iter_leaf_children_with_type("Color").nth(0) + // Get shader type. + let shader = match events.next_event()? { + Event::Leaf { + type_name: "Type", + contents: "Lambert", + .. + } => { + let color = if let Event::Leaf { + type_name: "Color", + contents, + byte_offset, + } = events.next_event()? { if let Ok(color) = parse_color(contents) { color @@ -50,74 +48,108 @@ pub fn parse_surface_shader( } } else { return Err(PsyParseError::MissingNode( - tree.byte_offset(), + events.byte_offset(), "Expected a Color field in Lambert SurfaceShader.", )); }; + // Close shader node. + if let Event::InnerClose { .. } = events.next_event()? { + // Success, do nothing. + } else { + todo!(); // Return error. + } + Box::new(SimpleSurfaceShader::Lambert { color: color }) } - "GGX" => { - // Color - let color = if let Some((_, contents, byte_offset)) = - tree.iter_leaf_children_with_type("Color").nth(0) - { - if let Ok(color) = parse_color(contents) { - color - } else { - // Found color, but its contents is not in the right format - return Err(PsyParseError::UnknownError(byte_offset)); - } - } else { - return Err(PsyParseError::MissingNode( - tree.byte_offset(), - "Expected a Color field in GTR SurfaceShader.", - )); - }; + Event::Leaf { + type_name: "Type", + contents: "GGX", + .. + } => { + let mut color = None; + let mut roughness = None; + let mut fresnel = None; - // Roughness - let roughness = if let Some((_, contents, byte_offset)) = - tree.iter_leaf_children_with_type("Roughness").nth(0) - { - if let IResult::Ok((_, roughness)) = all_consuming(ws_f32)(contents) { - roughness - } else { - return Err(PsyParseError::UnknownError(byte_offset)); - } - } else { - return Err(PsyParseError::MissingNode( - tree.byte_offset(), - "Expected a Roughness field in GTR SurfaceShader.", - )); - }; + loop { + match events.next_event()? { + // Color + Event::Leaf { + type_name: "Color", + contents, + byte_offset, + } => { + if let Ok(col) = parse_color(contents) { + color = Some(col); + } else { + // Found color, but its contents is not in the right + // format. + return Err(PsyParseError::UnknownError(byte_offset)); + } + } - // Fresnel - let fresnel = if let Some((_, contents, byte_offset)) = - tree.iter_leaf_children_with_type("Fresnel").nth(0) - { - if let IResult::Ok((_, fresnel)) = all_consuming(ws_f32)(contents) { - fresnel - } else { - return Err(PsyParseError::UnknownError(byte_offset)); + // Roughness + Event::Leaf { + type_name: "Roughness", + contents, + byte_offset, + } => { + if let IResult::Ok((_, rgh)) = all_consuming(ws_f32)(contents) { + roughness = Some(rgh); + } else { + return Err(PsyParseError::UnknownError(byte_offset)); + } + } + + // Fresnel + Event::Leaf { + type_name: "Fresnel", + contents, + byte_offset, + } => { + if let IResult::Ok((_, frs)) = all_consuming(ws_f32)(contents) { + fresnel = Some(frs); + } else { + return Err(PsyParseError::UnknownError(byte_offset)); + } + } + + Event::InnerClose { .. } => { + break; + } + + _ => { + todo!(); // Return an error. + } } - } else { + } + + // Validation: make sure all fields are present. + if color == None || roughness == None || fresnel == None { return Err(PsyParseError::MissingNode( - tree.byte_offset(), - "Expected a Fresnel field in GTR SurfaceShader.", + events.byte_offset(), + "GGX shader requires one of each field: Color, Roughness, Fresnel.", )); - }; + } Box::new(SimpleSurfaceShader::GGX { - color: color, - roughness: roughness, - fresnel: fresnel, + color: color.unwrap(), + roughness: roughness.unwrap(), + fresnel: fresnel.unwrap(), }) } - "Emit" => { - let color = if let Some((_, contents, byte_offset)) = - tree.iter_leaf_children_with_type("Color").nth(0) + Event::Leaf { + type_name: "Type", + contents: "Emit", + .. + } => { + let color = if let Event::Leaf { + type_name: "Color", + contents, + byte_offset, + } = events.next_event()? { if let Ok(color) = parse_color(contents) { color @@ -127,15 +159,34 @@ pub fn parse_surface_shader( } } else { return Err(PsyParseError::MissingNode( - tree.byte_offset(), + events.byte_offset(), "Expected a Color field in Emit SurfaceShader.", )); }; + // Close shader node. + if let Event::InnerClose { .. } = events.next_event()? { + // Success, do nothing. + } else { + todo!(); // Return error. + } + Box::new(SimpleSurfaceShader::Emit { color: color }) } - _ => unimplemented!(), + Event::Leaf { + type_name: "Type", + byte_offset, + .. + } => { + return Err(PsyParseError::MissingNode( + byte_offset, + "Unknown SurfaceShader type.", + )); + } + _ => { + todo!(); // Return error. + } }; Ok(shader) diff --git a/sub_crates/data_tree/src/lib.rs b/sub_crates/data_tree/src/lib.rs index 7cd6dc5..09e45f9 100644 --- a/sub_crates/data_tree/src/lib.rs +++ b/sub_crates/data_tree/src/lib.rs @@ -127,8 +127,6 @@ impl Parser { self.buf_consumed_idx += bytes_consumed; self.total_bytes_processed += bytes_consumed; - // Hack the borrow checker, which doesn't understand - // loops apparently, and return. Ok(event.add_to_byte_offset(self.total_bytes_processed - self.buf_consumed_idx)) } EventParse::ReachedEnd => { @@ -157,6 +155,56 @@ impl Parser { )), } } + + pub fn peek_event<'a>(&'a mut self) -> Result, Error> { + // Remove any consumed data. + if self.buf_consumed_idx > 0 { + self.buffer.replace_range(..self.buf_consumed_idx, ""); + self.buf_consumed_idx = 0; + } + + // Try to parse an event from the valid prefix. + match try_parse_event(&self.buffer) { + EventParse::Ok(event, _bytes_consumed) => { + if let Event::InnerClose { byte_offset, .. } = event { + if self.inner_opens == 0 { + return Err(Error::UnexpectedClose( + byte_offset + self.total_bytes_processed, + )); + } + } + Ok(event.add_to_byte_offset(self.total_bytes_processed)) + } + EventParse::ReachedEnd => { + // If we consumed all data, then if all nodes are properly + // closed we're done. Otherwise we need more input. + if self.inner_opens == 0 { + Ok(Event::ValidEnd) + } else { + Ok(Event::NeedMoreInput) + } + } + EventParse::IncompleteData => Ok(Event::NeedMoreInput), + + // Hard errors. + EventParse::ExpectedTypeNameOrInnerClose(byte_offset) => Err( + Error::ExpectedTypeNameOrClose(byte_offset + self.total_bytes_processed), + ), + EventParse::ExpectedOpenOrIdent(byte_offset) => Err(Error::ExpectedOpenOrIdent( + byte_offset + self.total_bytes_processed, + )), + EventParse::ExpectedInnerOpen(byte_offset) => Err(Error::ExpectedOpen( + byte_offset + self.total_bytes_processed, + )), + EventParse::UnexpectedIdent(byte_offset) => Err(Error::UnexpectedIdent( + byte_offset + self.total_bytes_processed, + )), + } + } + + pub fn byte_offset(&self) -> usize { + self.total_bytes_processed + self.buf_consumed_idx + } } //-------------------------------------------------------------------------- diff --git a/sub_crates/data_tree/src/reader.rs b/sub_crates/data_tree/src/reader.rs index 9d6246e..3942391 100644 --- a/sub_crates/data_tree/src/reader.rs +++ b/sub_crates/data_tree/src/reader.rs @@ -81,4 +81,41 @@ impl DataTreeReader { } } } + + pub fn peek_event<'a>(&'a mut self) -> Result, ReaderError> { + loop { + let valid_end = match self.parser.peek_event()? { + Event::ValidEnd => true, + Event::NeedMoreInput => false, + e => { + return Ok(unsafe { + // Transmute because the borrow checker is + // over-conservative about this. It thinks + // the liftime isn't valid, but since we aren't + // mutating self after returning (and in fact + // can't because of the borrow) there's no way for + // the references in this to become invalid. + std::mem::transmute::(e) + }); + } + }; + + if !self.eof { + self.buf.clear(); + let read = self.reader.read_line(&mut self.buf)?; + self.parser.push_data(&self.buf); + if read == 0 { + self.eof = true; + } + } else if !valid_end { + return Err(ReaderError::UnexpectedEOF); + } else { + return Ok(Event::ValidEnd); + } + } + } + + pub fn byte_offset(&self) -> usize { + self.parser.byte_offset() + } }