WIP refactor to make psy parsing all streaming.

Does not build right now.
This commit is contained in:
Nathan Vegdahl 2020-01-07 19:13:20 +09:00
parent 9d5bc63fa5
commit e3e5c1412f
6 changed files with 533 additions and 502 deletions

View File

@ -47,6 +47,11 @@ use nom::bytes::complete::take_until;
use kioku::Arena; use kioku::Arena;
use data_tree::{
reader::{DataTreeReader, ReaderError},
Event,
};
use crate::{ use crate::{
accel::BVH4Node, accel::BVH4Node,
bbox::BBox, bbox::BBox,
@ -191,63 +196,86 @@ fn main() {
println!("Parsing scene file...",); println!("Parsing scene file...",);
} }
t.tick(); t.tick();
let psy_contents = if args.is_present("use_stdin") { // let psy_contents = if args.is_present("use_stdin") {
// Read from stdin // // Read from stdin
let mut input = Vec::new(); // let mut input = Vec::new();
let tmp = std::io::stdin(); // let tmp = std::io::stdin();
let mut stdin = tmp.lock(); // let mut stdin = tmp.lock();
let mut buf = vec![0u8; 4096]; // let mut buf = vec![0u8; 4096];
loop { // loop {
let count = stdin // let count = stdin
.read(&mut buf) // .read(&mut buf)
.expect("Unexpected end of scene input."); // .expect("Unexpected end of scene input.");
let start = if input.len() < 11 { // let start = if input.len() < 11 {
0 // 0
} else { // } else {
input.len() - 11 // input.len() - 11
}; // };
let end = input.len() + count; // let end = input.len() + count;
input.extend(&buf[..count]); // input.extend(&buf[..count]);
let mut done = false; // let mut done = false;
let mut trunc_len = 0; // let mut trunc_len = 0;
if let nom::IResult::Ok((remaining, _)) = // if let nom::IResult::Ok((remaining, _)) =
take_until::<&str, &[u8], ()>("__PSY_EOF__")(&input[start..end]) // take_until::<&str, &[u8], ()>("__PSY_EOF__")(&input[start..end])
{ // {
done = true; // done = true;
trunc_len = input.len() - remaining.len(); // trunc_len = input.len() - remaining.len();
} // }
if done { // if done {
input.truncate(trunc_len); // input.truncate(trunc_len);
break; // break;
} // }
} // }
String::from_utf8(input).unwrap() // String::from_utf8(input).unwrap()
} else { // } else {
// Read from file // // Read from file
let mut input = String::new(); // let mut input = String::new();
let fp = args.value_of("input").unwrap(); // let fp = args.value_of("input").unwrap();
let mut f = io::BufReader::new(File::open(fp).unwrap()); // let mut f = io::BufReader::new(File::open(fp).unwrap());
let _ = f.read_to_string(&mut input); // let _ = f.read_to_string(&mut input);
input // input
}; // };
let dt = DataTree::from_str(&psy_contents).unwrap(); // let dt = DataTree::from_str(&psy_contents).unwrap();
if !args.is_present("serialized_output") { // if !args.is_present("serialized_output") {
println!("\tParsed scene file in {:.3}s", t.tick()); // 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 // Iterate through scenes and render them
if let DataTree::Internal { ref children, .. } = dt { loop {
for child in children { t.tick();
t.tick(); match events.next_event() {
if child.type_name() == "Scene" { 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") { if !args.is_present("serialized_output") {
println!("Building scene..."); println!("Building scene...");
} }
let arena = Arena::new().with_block_size((1 << 20) * 4); 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::<String>();
let mut scene = parse_scene(&arena, &mut events, &ident).unwrap_or_else(|e| {
e.print(&psy_contents); e.print(&psy_contents);
panic!("Parse error."); panic!("Parse error.");
}); });

View File

@ -1,9 +1,13 @@
#![allow(dead_code)] #![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 nom::{combinator::all_consuming, sequence::tuple, IResult};
use data_tree::{
reader::{DataTreeReader, ReaderError},
Event,
};
use kioku::Arena; use kioku::Arena;
use crate::{ use crate::{
@ -38,6 +42,7 @@ pub enum PsyParseError {
IncorrectLeafData(usize, &'static str), // Error message IncorrectLeafData(usize, &'static str), // Error message
WrongNodeCount(usize, &'static str, usize), // Error message, sections found WrongNodeCount(usize, &'static str, usize), // Error message, sections found
InstancedMissingData(usize, &'static str, String), // Error message, data name InstancedMissingData(usize, &'static str, String), // Error message, data name
ReaderError(ReaderError),
} }
impl PsyParseError { 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<ReaderError> for PsyParseError {
fn from(e: ReaderError) -> Self {
PsyParseError::ReaderError(e)
}
}
fn line_count_to_byte_offset(text: &str, offset: usize) -> usize { fn line_count_to_byte_offset(text: &str, offset: usize) -> usize {
text[..offset].matches('\n').count() + 1 text[..offset].matches('\n').count() + 1
} }
//----------------------------------------------------------------
/// Takes in a `DataTree` representing a Scene node and returns /// Takes in a `DataTree` representing a Scene node and returns
pub fn parse_scene<'a>(arena: &'a Arena, tree: &'a DataTree) -> Result<Scene<'a>, PsyParseError> { pub fn parse_scene<'a>(
// Verify we have the right number of each section arena: &'a Arena,
if tree.iter_children_with_type("Output").count() != 1 { events: &mut DataTreeReader<impl BufRead>,
let count = tree.iter_children_with_type("Output").count(); ident: Option<&str>,
return Err(PsyParseError::WrongNodeCount( ) -> Result<Scene<'a>, PsyParseError> {
tree.byte_offset(), // Get output info.
"Scene should have precisely one Output \ let output_info = if let Event::InnerOpen {
section.", type_name: "Output",
count, ..
)); } = events.next_event()?
} {
if tree.iter_children_with_type("RenderSettings").count() != 1 { parse_output_info(events)?
let count = tree.iter_children_with_type("RenderSettings").count(); } else {
return Err(PsyParseError::WrongNodeCount( todo!(); // Return error.
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,
));
}
// Parse output info // Get render settings.
let output_info = parse_output_info(tree.iter_children_with_type("Output").nth(0).unwrap())?; let render_settings = if let Event::InnerOpen {
type_name: "RenderSettings",
..
} = events.next_event()?
{
parse_render_settings(events)?
} else {
todo!(); // Return error.
};
// Parse render settings // Get camera.
let render_settings = parse_render_settings( let camera = if let Event::InnerOpen {
tree.iter_children_with_type("RenderSettings") type_name: "Camera",
.nth(0) ..
.unwrap(), } = events.next_event()?
)?; {
parse_camera(arena, events)?
} else {
todo!(); // Return error.
};
// Parse camera // Get shaders.
let camera = parse_camera( let shaders = if let Event::InnerOpen {
arena, type_name: "Shaders",
tree.iter_children_with_type("Camera").nth(0).unwrap(), ..
)?; } = events.next_event()?
{
parse_shaders(arena, events)?
} else {
todo!(); // Return error.
};
// Parse world // Get world.
let world = parse_world(arena, tree.iter_children_with_type("World").nth(0).unwrap())?; let world = if let Event::InnerOpen {
type_name: "World", ..
} = events.next_event()?
{
parse_world(arena, events)?
} else {
todo!(); // Return error.
};
// Parse shaders // Get the root assembly.
let shaders = parse_shaders(tree.iter_children_with_type("Shaders").nth(0).unwrap())?; let root_assembly = if let Event::InnerOpen {
type_name: "Assembly",
ident,
..
} = events.next_event()?
{
parse_assembly(arena, events, &(ident.into::<String>()))?
} else {
todo!(); // Return error.
};
// Parse root scene assembly // Make sure we're closed out properly.
let assembly = parse_assembly( if let Event::InnerClose { .. } = events.next_event()? {
arena, } else {
tree.iter_children_with_type("Assembly").nth(0).unwrap(), todo!(); // Return error.
)?; }
// Put scene together // Put scene together
let scene_name = if let DataTree::Internal { ident, .. } = tree { let scene_name = if let Some(name) = ident {
if let Some(name) = ident { Some(name.into())
Some(name.clone())
} else {
None
}
} else { } else {
None None
}; };
let scene = Scene { let scene = Scene {
camera: camera, camera: camera,
world: world, world: world,
shaders: shaders, shaders: shaders,
root_assembly: assembly, root_assembly: root_assembly,
}; };
// // Put renderer together // // Put renderer together
@ -215,396 +227,357 @@ pub fn parse_scene<'a>(arena: &'a Arena, tree: &'a DataTree) -> Result<Scene<'a>
return Ok(scene); return Ok(scene);
} }
fn parse_output_info(tree: &DataTree) -> Result<String, PsyParseError> { fn parse_output_info(events: &mut DataTreeReader<impl BufRead>) -> Result<String, PsyParseError> {
if let DataTree::Internal { ref children, .. } = *tree { let mut found_path = false;
let mut found_path = false; let mut path = String::new();
let mut path = String::new(); loop {
match events.next_event()? {
for child in children { Event::Leaf {
match child { type_name: "Path",
DataTree::Leaf { contents,
type_name, byte_offset,
contents, } => {
byte_offset, // Trim and validate
} if type_name == "Path" => { let tc = contents.trim();
// Trim and validate if tc.chars().count() < 2 {
let tc = contents.trim(); return Err(PsyParseError::IncorrectLeafData(
if tc.chars().count() < 2 { *byte_offset,
return Err(PsyParseError::IncorrectLeafData( "File path format is incorrect.",
*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();
} }
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 { if found_path {
return Ok(path); return Ok(path);
} else {
return Err(PsyParseError::MissingNode(
tree.byte_offset(),
"Output section must contain a Path.",
));
}
} else { } else {
return Err(PsyParseError::ExpectedInternalNode( // return Err(PsyParseError::MissingNode(
tree.byte_offset(), // tree.byte_offset(),
"Output section should be an internal \ // "Output section must contain a Path.",
node, containing at least a Path.", // ));
)); todo!(); // Return error.
};
}
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<Camera<'a>, 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.",
));
} }
} }
fn parse_world<'a>(arena: &'a Arena, tree: &'a DataTree) -> Result<World<'a>, PsyParseError> { fn parse_render_settings(
if tree.is_internal() { events: &mut DataTreeReader<impl BufRead>,
let background_color; ) -> Result<((u32, u32), u32, u32), PsyParseError> {
let mut lights: Vec<&dyn WorldLightSource> = Vec::new(); let mut found_res = false;
let mut found_spp = false;
// Parse background shader let mut res = (0, 0);
let bgs = { let mut spp = 0;
if tree.iter_children_with_type("BackgroundShader").count() != 1 { let mut seed = 0;
return Err(PsyParseError::WrongNodeCount( loop {
tree.byte_offset(), match events.next_event()? {
"World should have precisely one BackgroundShader section.", // Resolution
tree.iter_children_with_type("BackgroundShader").count(), Event::Leaf {
)); type_name: "Resolution",
} contents,
tree.iter_children_with_type("BackgroundShader") byte_offset,
.nth(0) } => {
.unwrap() if let IResult::Ok((_, (w, h))) = all_consuming(tuple((ws_u32, ws_u32)))(&contents)
};
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)
{ {
if let Ok(color) = parse_color(&contents) { found_res = true;
background_color = color; res = (w, h);
} else {
return Err(PsyParseError::IncorrectLeafData(
*byte_offset,
"Color should be specified \
with three decimal numbers \
in the form '[R G B]'.",
));
}
} else { } else {
return Err(PsyParseError::MissingNode( // Found Resolution, but its contents is not in the right format
bgs.byte_offset(), return Err(PsyParseError::IncorrectLeafData(
"BackgroundShader's Type is Color, \ *byte_offset,
but no Color is specified.", "Resolution should be specified with two \
integers in the form '[width height]'.",
)); ));
} }
} }
_ => { // SamplesPerPixel
return Err(PsyParseError::UnknownVariant( DataTree::Leaf {
bgs.byte_offset(), type_name: "SamplesPerPixel",
"The specified BackgroundShader Type \ contents,
isn't a recognized type.", byte_offset,
)) } => {
} if let IResult::Ok((_, n)) = all_consuming(ws_u32)(&contents) {
} found_spp = true;
spp = n;
// Parse light sources } else {
for child in tree.iter_children() { // Found SamplesPerPixel, but its contents is not in the right format
match child { return Err(PsyParseError::IncorrectLeafData(
DataTree::Internal { type_name, .. } if type_name == "DistantDiskLight" => { *byte_offset,
lights.push(arena.alloc(parse_distant_disk_light(arena, child)?)); "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 if found_res && found_spp {
return Ok(World { return Ok((res, spp, seed));
background_color: background_color,
lights: arena.copy_slice(&lights),
});
} else { } else {
return Err(PsyParseError::ExpectedInternalNode( // return Err(PsyParseError::MissingNode(
tree.byte_offset(), // tree.byte_offset(),
"World section should be an internal \ // "RenderSettings must have both Resolution and \
node, containing at least a \ // SamplesPerPixel specified.",
BackgroundShader.", // ));
)); todo!(); // Return error.
} }
} }
fn parse_shaders<'a>( fn parse_camera<'a>(
tree: &'a DataTree, arena: &'a Arena,
) -> Result<HashMap<String, Box<dyn SurfaceShader>>, PsyParseError> { events: &mut DataTreeReader<impl BufRead>,
if tree.is_internal() { ) -> Result<Camera<'a>, PsyParseError> {
let mut shaders = HashMap::new(); 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() { // Parse
match shader_item { loop {
DataTree::Internal { match events.next_event()? {
type_name, // Fov
ident, Event::Leaf {
children, type_name: "Fov",
byte_offset, contents,
} if type_name == &"SurfaceShader" => { byte_offset,
if let Some(name) = ident { } => {
shaders.insert(name.to_string(), parse_surface_shader(shader_item)?); if let IResult::Ok((_, fov)) = all_consuming(ws_f32)(&contents) {
} else { fovs.push(fov * (f32::consts::PI / 180.0));
// TODO: error. } 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<impl BufRead>,
) -> Result<World<'a>, 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::<String>()
} 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.
} }
} }
_ => { // Close it out.
// TODO: an error. if let Event::InnerClose { .. } = events.next_event() {
} else {
todo!(); // Return error.
} }
} }
}
// Return the list of shaders. // Parse light sources
return Ok(shaders); Event::InnerOpen {
} else { type_name: "DistantDiskLight",
return Err(PsyParseError::ExpectedInternalNode( ..
tree.byte_offset(), } => {
"Shaders section should be an internal \ lights.push(arena.alloc(parse_distant_disk_light(arena, events)?));
node.", }
)); }
} }
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<impl BufRead>,
) -> Result<HashMap<String, Box<dyn SurfaceShader>>, 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<Matrix4x4, PsyParseError> { pub fn parse_matrix(contents: &str) -> Result<Matrix4x4, PsyParseError> {
@ -621,7 +594,7 @@ pub fn parse_matrix(contents: &str) -> Result<Matrix4x4, PsyParseError> {
} }
} }
return Err(PsyParseError::UnknownError(0)); todo!(); // Return an error.
} }
pub fn make_transform_format_error(byte_offset: usize) -> PsyParseError { 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<Color, PsyParseError> { pub fn parse_color(contents: &str) -> Result<Color, PsyParseError> {
let items: Vec<_> = contents.split(',').map(|s| s.trim()).collect(); let items: Vec<_> = contents.split(',').map(|s| s.trim()).collect();
if items.len() != 2 { if items.len() != 2 {
return Err(PsyParseError::UnknownError(0)); todo!(); // Return an error.
} }
match items[0] { match items[0] {
@ -643,7 +616,7 @@ pub fn parse_color(contents: &str) -> Result<Color, PsyParseError> {
if let IResult::Ok((_, color)) = tuple((ws_f32, ws_f32, ws_f32))(items[1]) { if let IResult::Ok((_, color)) = tuple((ws_f32, ws_f32, ws_f32))(items[1]) {
return Ok(Color::new_xyz(rec709_e_to_xyz(color))); return Ok(Color::new_xyz(rec709_e_to_xyz(color)));
} else { } else {
return Err(PsyParseError::UnknownError(0)); todo!(); // Return an error.
} }
} }
@ -651,7 +624,7 @@ pub fn parse_color(contents: &str) -> Result<Color, PsyParseError> {
if let IResult::Ok((_, (temperature, factor))) = tuple((ws_f32, ws_f32))(items[1]) { if let IResult::Ok((_, (temperature, factor))) = tuple((ws_f32, ws_f32))(items[1]) {
return Ok(Color::new_blackbody(temperature, factor)); return Ok(Color::new_blackbody(temperature, factor));
} else { } else {
return Err(PsyParseError::UnknownError(0)); todo!(); // Return an error.
} }
} }
@ -659,10 +632,12 @@ pub fn parse_color(contents: &str) -> Result<Color, PsyParseError> {
if let IResult::Ok((_, (temperature, factor))) = tuple((ws_f32, ws_f32))(items[1]) { if let IResult::Ok((_, (temperature, factor))) = tuple((ws_f32, ws_f32))(items[1]) {
return Ok(Color::new_temperature(temperature, factor)); return Ok(Color::new_temperature(temperature, factor));
} else { } else {
return Err(PsyParseError::UnknownError(0)); todo!(); // Return an error.
} }
} }
_ => return Err(PsyParseError::UnknownError(0)), _ => {
todo!(); // Return an error.
}
} }
} }

View File

@ -4,6 +4,11 @@ use std::result::Result;
use kioku::Arena; use kioku::Arena;
use data_tree::{
reader::{DataTreeReader, ReaderError},
Event,
};
use crate::scene::{Assembly, Object, ObjectData}; use crate::scene::{Assembly, Object, ObjectData};
use super::{ use super::{
@ -15,7 +20,8 @@ use super::{
pub fn parse_assembly<'a>( pub fn parse_assembly<'a>(
arena: &'a Arena, arena: &'a Arena,
tree: &'a DataTree, events: &mut DataTreeReader,
ident: Option<&str>,
) -> Result<Assembly<'a>, PsyParseError> { ) -> Result<Assembly<'a>, PsyParseError> {
if !tree.is_internal() { if !tree.is_internal() {
return Err(PsyParseError::UnknownError(tree.byte_offset())); return Err(PsyParseError::UnknownError(tree.byte_offset()));

View File

@ -6,6 +6,11 @@ use nom::{combinator::all_consuming, sequence::tuple, IResult};
use kioku::Arena; use kioku::Arena;
use data_tree::{
reader::{DataTreeReader, ReaderError},
Event,
};
use crate::{ use crate::{
light::{DistantDiskLight, RectangleLight, SphereLight}, light::{DistantDiskLight, RectangleLight, SphereLight},
math::Vector, math::Vector,
@ -19,7 +24,8 @@ use super::{
pub fn parse_distant_disk_light<'a>( pub fn parse_distant_disk_light<'a>(
arena: &'a Arena, arena: &'a Arena,
tree: &'a DataTree, events: &mut DataTreeReader,
ident: Option<&str>,
) -> Result<DistantDiskLight<'a>, PsyParseError> { ) -> Result<DistantDiskLight<'a>, PsyParseError> {
if let DataTree::Internal { ref children, .. } = *tree { if let DataTree::Internal { ref children, .. } = *tree {
let mut radii = Vec::new(); let mut radii = Vec::new();
@ -85,7 +91,8 @@ pub fn parse_distant_disk_light<'a>(
pub fn parse_sphere_light<'a>( pub fn parse_sphere_light<'a>(
arena: &'a Arena, arena: &'a Arena,
tree: &'a DataTree, events: &mut DataTreeReader,
ident: Option<&str>,
) -> Result<SphereLight<'a>, PsyParseError> { ) -> Result<SphereLight<'a>, PsyParseError> {
if let DataTree::Internal { ref children, .. } = *tree { if let DataTree::Internal { ref children, .. } = *tree {
let mut radii = Vec::new(); let mut radii = Vec::new();
@ -134,7 +141,8 @@ pub fn parse_sphere_light<'a>(
pub fn parse_rectangle_light<'a>( pub fn parse_rectangle_light<'a>(
arena: &'a Arena, arena: &'a Arena,
tree: &'a DataTree, events: &mut DataTreeReader,
ident: Option<&str>,
) -> Result<RectangleLight<'a>, PsyParseError> { ) -> Result<RectangleLight<'a>, PsyParseError> {
if let DataTree::Internal { ref children, .. } = *tree { if let DataTree::Internal { ref children, .. } = *tree {
let mut dimensions = Vec::new(); let mut dimensions = Vec::new();

View File

@ -6,6 +6,11 @@ use nom::{sequence::tuple, IResult};
use kioku::Arena; use kioku::Arena;
use data_tree::{
reader::{DataTreeReader, ReaderError},
Event,
};
use crate::{ use crate::{
math::{Normal, Point}, math::{Normal, Point},
surface::triangle_mesh::TriangleMesh, surface::triangle_mesh::TriangleMesh,
@ -26,7 +31,8 @@ use super::{
pub fn parse_mesh_surface<'a>( pub fn parse_mesh_surface<'a>(
arena: &'a Arena, arena: &'a Arena,
tree: &'a DataTree, events: &mut DataTreeReader,
ident: Option<&str>,
) -> Result<TriangleMesh<'a>, PsyParseError> { ) -> Result<TriangleMesh<'a>, PsyParseError> {
let mut verts = Vec::new(); // Vec of vecs, one for each time sample 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 normals = Vec::new(); // Vec of vecs, on for each time sample

View File

@ -4,6 +4,11 @@ use std::result::Result;
use nom::{combinator::all_consuming, IResult}; use nom::{combinator::all_consuming, IResult};
use data_tree::{
reader::{DataTreeReader, ReaderError},
Event,
};
use crate::shading::{SimpleSurfaceShader, SurfaceShader}; use crate::shading::{SimpleSurfaceShader, SurfaceShader};
use super::{ use super::{
@ -19,7 +24,10 @@ use super::{
// accel: BVH, // accel: BVH,
// } // }
pub fn parse_surface_shader(tree: &DataTree) -> Result<Box<dyn SurfaceShader>, PsyParseError> { pub fn parse_surface_shader(
events: &mut DataTreeReader,
ident: Option<&str>,
) -> Result<Box<dyn SurfaceShader>, PsyParseError> {
let type_name = if let Some((_, text, _)) = tree.iter_leaf_children_with_type("Type").nth(0) { let type_name = if let Some((_, text, _)) = tree.iter_leaf_children_with_type("Type").nth(0) {
text.trim() text.trim()
} else { } else {