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 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::<String>();
let mut scene = parse_scene(&arena, &mut events, &ident).unwrap_or_else(|e| {
e.print(&psy_contents);
panic!("Parse error.");
});

View File

@ -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<ReaderError> 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<Scene<'a>, 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<impl BufRead>,
ident: Option<&str>,
) -> Result<Scene<'a>, 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::<String>()))?
} 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<Scene<'a>
return Ok(scene);
}
fn parse_output_info(tree: &DataTree) -> Result<String, PsyParseError> {
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<impl BufRead>) -> Result<String, PsyParseError> {
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<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.",
));
// 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<World<'a>, 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<impl BufRead>,
) -> 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<HashMap<String, Box<dyn SurfaceShader>>, PsyParseError> {
if tree.is_internal() {
let mut shaders = HashMap::new();
fn parse_camera<'a>(
arena: &'a Arena,
events: &mut DataTreeReader<impl BufRead>,
) -> Result<Camera<'a>, 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<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.
}
}
_ => {
// 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<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> {
@ -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 {
@ -635,7 +608,7 @@ pub fn make_transform_format_error(byte_offset: usize) -> PsyParseError {
pub fn parse_color(contents: &str) -> Result<Color, PsyParseError> {
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<Color, PsyParseError> {
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<Color, PsyParseError> {
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<Color, PsyParseError> {
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.
}
}
}

View File

@ -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<Assembly<'a>, PsyParseError> {
if !tree.is_internal() {
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 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<DistantDiskLight<'a>, 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<SphereLight<'a>, 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<RectangleLight<'a>, PsyParseError> {
if let DataTree::Internal { ref children, .. } = *tree {
let mut dimensions = Vec::new();

View File

@ -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<TriangleMesh<'a>, 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

View File

@ -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<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) {
text.trim()
} else {