WIP refactor to make psy parsing all streaming.
Does not build right now.
This commit is contained in:
parent
9d5bc63fa5
commit
e3e5c1412f
124
src/main.rs
124
src/main.rs
|
@ -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.");
|
||||||
});
|
});
|
||||||
|
|
871
src/parse/psy.rs
871
src/parse/psy.rs
|
@ -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.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()));
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user