All parsing is now streaming! But lots left to do.

In particular, parsing error messages are now either terrible or
non-existent.  But it compiles and works for correct inputs!
This commit is contained in:
Nathan Vegdahl 2020-01-10 22:31:39 +09:00
parent 5196e8e2c2
commit 4f564d1474
13 changed files with 677 additions and 447 deletions

View File

@ -7,18 +7,6 @@ Scene $Scene_fr1 {
SamplesPerPixel [16]
Seed [1]
}
Camera {
Fov [39.449188]
FocalDistance [10.62]
ApertureRadius [0.0]
Transform [1.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 -2.779998 -8.000000 2.730010 1.0]
}
World {
BackgroundShader {
Type [Color]
Color [rec709, 0.0 0.0 0.0]
}
}
Shaders {
SurfaceShader $Green {
Type [Lambert]
@ -33,6 +21,18 @@ Scene $Scene_fr1 {
Color [rec709, 0.7295 0.7355 0.729]
}
}
World {
BackgroundShader {
Type [Color]
Color [rec709, 0.0 0.0 0.0]
}
}
Camera {
Fov [39.449188]
FocalDistance [10.62]
ApertureRadius [0.0]
Transform [1.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 -2.779998 -8.000000 2.730010 1.0]
}
Assembly {
Object $__Area {
Instance {

View File

@ -7,11 +7,11 @@ Scene $Scene_fr1 {
SamplesPerPixel [16]
Seed [1]
}
Camera {
Fov [49.134342]
FocalDistance [9.56]
ApertureRadius [0.25]
Transform [0.685881 0.727634 -0.010817 0.0 -0.317370 0.312469 0.895343 0.0 -0.654862 0.610666 -0.445245 0.0 7.481132 -6.507640 5.343665 1.0]
Shaders {
SurfaceShader $Material {
Type [Lambert]
Color [rec709, 0.8 0.8 0.8]
}
}
World {
BackgroundShader {
@ -19,11 +19,11 @@ Scene $Scene_fr1 {
Color [rec709, 0.050876 0.050876 0.050876]
}
}
Shaders {
SurfaceShader $Material {
Type [Lambert]
Color [rec709, 0.8 0.8 0.8]
}
Camera {
Fov [49.134342]
FocalDistance [9.56]
ApertureRadius [0.25]
Transform [0.685881 0.727634 -0.010817 0.0 -0.317370 0.312469 0.895343 0.0 -0.654862 0.610666 -0.445245 0.0 7.481132 -6.507640 5.343665 1.0]
}
Assembly {
Object $__Plane_ {

View File

@ -44,7 +44,7 @@ fn wavelengths(hero_wavelength: f32) -> Vec4 {
//----------------------------------------------------------------
#[derive(Debug, Copy, Clone)]
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Color {
XYZ(f32, f32, f32),
Blackbody {

View File

@ -47,15 +47,12 @@ use nom::bytes::complete::take_until;
use kioku::Arena;
use data_tree::{
reader::{DataTreeReader, ReaderError},
Event,
};
use data_tree::{reader::DataTreeReader, Event};
use crate::{
accel::BVH4Node,
bbox::BBox,
parse::{parse_scene, DataTree},
parse::parse_scene,
// renderer::LightPath,
surface::SurfaceIntersection,
timer::Timer,
@ -242,27 +239,14 @@ fn main() {
// println!("\tParsed scene file in {:.3}s", t.tick());
// }
let mut psy_file = io::BufReader::new(File::open(fp).unwrap());
let file_path = args.value_of("input").unwrap();
let mut psy_file = io::BufReader::new(File::open(file_path).unwrap());
let mut events = DataTreeReader::new(&mut psy_file);
// Iterate through scenes and render them
loop {
t.tick();
match events.next_event() {
Ok(Event::ValidEnd) => {
break;
}
Ok(_) => {
println!("Error: invalid scene in psy file.");
break;
}
Err(e) => {
println!("Error: {:?}", e);
break;
}
// Parse a scene and render it.
Ok(Event::InnerOpen {
type_name: "Scene",
@ -274,11 +258,13 @@ fn main() {
}
let arena = Arena::new().with_block_size((1 << 20) * 4);
let ident = ident.into::<String>();
let mut scene = parse_scene(&arena, &mut events, &ident).unwrap_or_else(|e| {
e.print(&psy_contents);
panic!("Parse error.");
});
let ident = ident.map(|v| v.to_string());
let scene =
parse_scene(&arena, &mut events, ident.as_deref()).unwrap_or_else(|e| {
println!("Parse error: {}", e);
// e.print(&psy_contents);
panic!("Parse error.");
});
if let Some(spp) = args.value_of("spp") {
if !args.is_present("serialized_output") {
@ -384,6 +370,20 @@ fn main() {
// println!("\tTotal blocks: {}", arena_stats.2);
// }
}
Ok(Event::ValidEnd) => {
break;
}
Err(e) => {
println!("Error: {:?}", e);
break;
}
Ok(_) => {
println!("Error: invalid scene in psy file.");
break;
}
}
}

View File

@ -2,10 +2,7 @@
use std::{io::Cursor, iter::Iterator, result::Result, slice};
use data_tree::{
reader::{DataTreeReader, ReaderError},
Event,
};
use data_tree::{reader::DataTreeReader, Event};
#[derive(Debug, Eq, PartialEq)]
pub enum DataTree {

View File

@ -1,9 +1,9 @@
pub mod basics;
mod data_tree;
// mod data_tree;
mod psy;
mod psy_assembly;
mod psy_light;
mod psy_mesh_surface;
mod psy_surface_shader;
pub use self::{data_tree::DataTree, psy::parse_scene};
pub use self::psy::parse_scene;

View File

@ -26,7 +26,6 @@ use super::{
psy_assembly::parse_assembly,
psy_light::parse_distant_disk_light,
psy_surface_shader::parse_surface_shader,
DataTree,
};
#[derive(Debug)]
@ -34,13 +33,13 @@ pub enum PsyParseError {
// The first usize for all errors is their byte offset
// into the psy content where they occured.
UnknownError(usize),
UnknownVariant(usize, &'static str), // Error message
ExpectedInternalNode(usize, &'static str), // Error message
ExpectedLeafNode(usize, &'static str), // Error message
ExpectedIdent(usize, &'static str), // Error message
MissingNode(usize, &'static str), // Error message
IncorrectLeafData(usize, &'static str), // Error message
WrongNodeCount(usize, &'static str, usize), // Error message, sections found
UnknownVariant(usize, &'static str), // Error message
ExpectedInternalNode(usize, &'static str), // Error message
ExpectedLeafNode(usize, &'static str), // Error message
ExpectedIdent(usize, &'static str), // Error message
MissingNode(usize, &'static str), // Error message
IncorrectLeafData(usize, &'static str), // Error message
WrongNodeCount(usize, &'static str), // Error message
InstancedMissingData(usize, &'static str, String), // Error message, data name
ReaderError(ReaderError),
}
@ -87,15 +86,17 @@ impl PsyParseError {
println!("Line {}: {}", line, error);
}
PsyParseError::WrongNodeCount(offset, error, count) => {
PsyParseError::WrongNodeCount(offset, error) => {
let line = line_count_to_byte_offset(psy_content, offset);
println!("Line {}: {} Found: {}", line, error, count);
println!("Line {}: {}", line, error);
}
PsyParseError::InstancedMissingData(offset, error, ref data_name) => {
let line = line_count_to_byte_offset(psy_content, offset);
println!("Line {}: {} Data name: '{}'", line, error, data_name);
}
_ => todo!(),
}
}
}
@ -124,10 +125,10 @@ fn line_count_to_byte_offset(text: &str, offset: usize) -> usize {
pub fn parse_scene<'a>(
arena: &'a Arena,
events: &mut DataTreeReader<impl BufRead>,
ident: Option<&str>,
_ident: Option<&str>,
) -> Result<Scene<'a>, PsyParseError> {
// Get output info.
let output_info = if let Event::InnerOpen {
let _output_info = if let Event::InnerOpen {
type_name: "Output",
..
} = events.next_event()?
@ -138,7 +139,7 @@ pub fn parse_scene<'a>(
};
// Get render settings.
let render_settings = if let Event::InnerOpen {
let _render_settings = if let Event::InnerOpen {
type_name: "RenderSettings",
..
} = events.next_event()?
@ -148,17 +149,6 @@ pub fn parse_scene<'a>(
todo!(); // Return error.
};
// Get camera.
let camera = if let Event::InnerOpen {
type_name: "Camera",
..
} = events.next_event()?
{
parse_camera(arena, events)?
} else {
todo!(); // Return error.
};
// Get shaders.
let shaders = if let Event::InnerOpen {
type_name: "Shaders",
@ -180,14 +170,24 @@ pub fn parse_scene<'a>(
todo!(); // Return error.
};
// Get the root assembly.
let root_assembly = if let Event::InnerOpen {
type_name: "Assembly",
ident,
// Get camera.
let camera = if let Event::InnerOpen {
type_name: "Camera",
..
} = events.next_event()?
{
parse_assembly(arena, events, &(ident.into::<String>()))?
parse_camera(arena, events)?
} else {
todo!(); // Return error.
};
// Get the root assembly.
let root_assembly = if let Event::InnerOpen {
type_name: "Assembly",
..
} = events.next_event()?
{
parse_assembly(arena, events)?
} else {
todo!(); // Return error.
};
@ -199,12 +199,11 @@ pub fn parse_scene<'a>(
}
// Put scene together
let scene_name = if let Some(name) = ident {
Some(name.into())
} else {
None
};
// let scene_name = if let Some(name) = ident {
// Some(name.into())
// } else {
// None
// };
let scene = Scene {
camera: camera,
world: world,
@ -241,13 +240,13 @@ fn parse_output_info(events: &mut DataTreeReader<impl BufRead>) -> Result<String
let tc = contents.trim();
if tc.chars().count() < 2 {
return Err(PsyParseError::IncorrectLeafData(
*byte_offset,
byte_offset,
"File path format is incorrect.",
));
}
if tc.chars().nth(0).unwrap() != '"' || !tc.ends_with('"') {
return Err(PsyParseError::IncorrectLeafData(
*byte_offset,
byte_offset,
"File paths must be surrounded by quotes.",
));
}
@ -304,7 +303,7 @@ fn parse_render_settings(
} else {
// Found Resolution, but its contents is not in the right format
return Err(PsyParseError::IncorrectLeafData(
*byte_offset,
byte_offset,
"Resolution should be specified with two \
integers in the form '[width height]'.",
));
@ -312,7 +311,7 @@ fn parse_render_settings(
}
// SamplesPerPixel
DataTree::Leaf {
Event::Leaf {
type_name: "SamplesPerPixel",
contents,
byte_offset,
@ -323,7 +322,7 @@ fn parse_render_settings(
} else {
// Found SamplesPerPixel, but its contents is not in the right format
return Err(PsyParseError::IncorrectLeafData(
*byte_offset,
byte_offset,
"SamplesPerPixel should be \
an integer specified in \
the form '[samples]'.",
@ -332,7 +331,7 @@ fn parse_render_settings(
}
// Seed
DataTree::Leaf {
Event::Leaf {
type_name: "Seed",
contents,
byte_offset,
@ -342,7 +341,7 @@ fn parse_render_settings(
} else {
// Found Seed, but its contents is not in the right format
return Err(PsyParseError::IncorrectLeafData(
*byte_offset,
byte_offset,
"Seed should be an integer \
specified in the form \
'[samples]'.",
@ -395,7 +394,7 @@ fn parse_camera<'a>(
} else {
// Found Fov, but its contents is not in the right format
return Err(PsyParseError::IncorrectLeafData(
*byte_offset,
byte_offset,
"Fov should be a decimal \
number specified in the \
form '[fov]'.",
@ -414,7 +413,7 @@ fn parse_camera<'a>(
} else {
// Found FocalDistance, but its contents is not in the right format
return Err(PsyParseError::IncorrectLeafData(
*byte_offset,
byte_offset,
"FocalDistance should be a \
decimal number specified \
in the form '[fov]'.",
@ -433,7 +432,7 @@ fn parse_camera<'a>(
} else {
// Found ApertureRadius, but its contents is not in the right format
return Err(PsyParseError::IncorrectLeafData(
*byte_offset,
byte_offset,
"ApertureRadius should be a \
decimal number specified \
in the form '[fov]'.",
@ -451,7 +450,7 @@ fn parse_camera<'a>(
mats.push(mat);
} else {
// Found Transform, but its contents is not in the right format
return Err(make_transform_format_error(*byte_offset));
return Err(make_transform_format_error(byte_offset));
}
}
@ -478,7 +477,7 @@ fn parse_world<'a>(
arena: &'a Arena,
events: &mut DataTreeReader<impl BufRead>,
) -> Result<World<'a>, PsyParseError> {
let background_color = None;
let mut background_color = None;
let mut lights: Vec<&dyn WorldLightSource> = Vec::new();
loop {
@ -486,25 +485,26 @@ fn parse_world<'a>(
// Parse background shader
Event::InnerOpen {
type_name: "BackgroundShader",
..
} => {
let bgs_type = if let Event::Leaf {
type_name: "Type",
contents,
..
} = events.next_event()
} = events.next_event()?
{
contents.into::<String>()
contents.to_string()
} else {
todo!(); // Return error.
};
match bgs_type {
match bgs_type.as_ref() {
"Color" => {
if let Event::Leaf {
type_name: "Color",
contents,
..
} = events.next_event()
} = events.next_event()?
{
background_color = Some(parse_color(contents)?);
} else {
@ -524,7 +524,7 @@ fn parse_world<'a>(
}
// Close it out.
if let Event::InnerClose { .. } = events.next_event() {
if let Event::InnerClose { .. } = events.next_event()? {
} else {
todo!(); // Return error.
}
@ -533,9 +533,23 @@ fn parse_world<'a>(
// Parse light sources
Event::InnerOpen {
type_name: "DistantDiskLight",
ident,
..
} => {
lights.push(arena.alloc(parse_distant_disk_light(arena, events)?));
let ident = ident.map(|v| v.to_string());
lights.push(arena.alloc(parse_distant_disk_light(
arena,
events,
ident.as_deref(),
)?));
}
Event::InnerClose { .. } => {
break;
}
_ => {
todo!(); // Return error.
}
}
}
@ -552,24 +566,32 @@ fn parse_world<'a>(
}
fn parse_shaders<'a>(
arena: &'a Arena,
events: &mut DataTreeReader<impl BufRead>,
) -> Result<HashMap<String, Box<dyn SurfaceShader>>, PsyParseError> {
let mut shaders = HashMap::new();
loop {
match events.next_event() {
DataTree::Internal {
match events.next_event()? {
Event::InnerOpen {
type_name: "SurfaceShader",
ident,
byte_offset,
..
} => {
if let Some(name) = ident {
let name = name.to_string();
shaders.insert(name, parse_surface_shader(events)?);
shaders.insert(
name.clone(),
parse_surface_shader(arena, events, Some(&name))?,
);
} else {
todo!("Shader has no name."); // Return error.
}
}
Event::InnerClose { .. } => {
break;
}
_ => {
todo!(); // Return error.
}

View File

@ -1,13 +1,10 @@
#![allow(dead_code)]
use std::result::Result;
use std::{io::BufRead, result::Result};
use kioku::Arena;
use data_tree::{
reader::{DataTreeReader, ReaderError},
Event,
};
use data_tree::{reader::DataTreeReader, Event};
use crate::scene::{Assembly, Object, ObjectData};
@ -15,101 +12,137 @@ use super::{
psy::{parse_matrix, PsyParseError},
psy_light::{parse_rectangle_light, parse_sphere_light},
psy_mesh_surface::parse_mesh_surface,
DataTree,
};
pub fn parse_assembly<'a>(
arena: &'a Arena,
events: &mut DataTreeReader,
ident: Option<&str>,
events: &mut DataTreeReader<impl BufRead>,
) -> Result<Assembly<'a>, PsyParseError> {
if !tree.is_internal() {
return Err(PsyParseError::UnknownError(tree.byte_offset()));
}
let mut assembly = Assembly::new();
for object in tree.iter_children() {
if object.type_name() == "Object" {
// Get object identifier.
let object_ident = if let Some(ident) = object.ident() {
ident
} else {
return Err(PsyParseError::ExpectedIdent(
object.byte_offset(),
"\'Object\' types must have an identifier, but the identifier is missing.",
));
};
// Collect instances.
let mut instance_xform_idxs = Vec::new();
for instance in object.iter_children_with_type("Instance") {
if !instance.is_internal() {
// TODO: error.
}
let xforms_start_idx = assembly.xforms.len();
for (_, contents, _) in instance.iter_leaf_children_with_type("Transform") {
assembly.xforms.push(parse_matrix(contents)?);
}
instance_xform_idxs.push(xforms_start_idx..assembly.xforms.len());
}
// Get object data.
let object_data = {
let obj_data_tree = {
if object
.iter_children()
.filter(|d| d.type_name() != "Instance")
.count()
!= 1
{
// TODO: error.
}
object
.iter_children()
.filter(|d| d.type_name() != "Instance")
.nth(0)
.unwrap()
loop {
match events.next_event()? {
Event::InnerOpen {
type_name: "Object",
ident,
byte_offset,
} => {
// Get object identifier.
let object_ident = if let Some(id) = ident {
id.to_string()
} else {
return Err(PsyParseError::ExpectedIdent(
byte_offset,
"\'Object\' types must have an identifier, but the identifier is missing.",
));
};
match obj_data_tree.type_name() {
// Sub-Assembly
"Assembly" => {
ObjectData::Assembly(Box::new(parse_assembly(arena, obj_data_tree)?))
// Collect instances.
let mut instance_xform_idxs = Vec::new();
while let Event::InnerOpen {
type_name: "Instance",
..
} = events.peek_event()?
{
events.next_event();
let xforms_start_idx = assembly.xforms.len();
loop {
match events.next_event()? {
Event::Leaf {
type_name: "Transform",
contents,
..
} => {
assembly.xforms.push(parse_matrix(contents)?);
}
Event::InnerClose { .. } => {
break;
}
_ => {
todo!("Instances can only contain Transforms.");
// Return an error.
}
}
}
"MeshSurface" => {
ObjectData::Surface(Box::new(parse_mesh_surface(arena, obj_data_tree)?))
}
instance_xform_idxs.push(xforms_start_idx..assembly.xforms.len());
}
"SphereLight" => {
ObjectData::Light(Box::new(parse_sphere_light(arena, obj_data_tree)?))
}
// Get object data.
let object_data = match events.next_event()? {
Event::InnerOpen {
type_name: "Assembly",
..
} => ObjectData::Assembly(Box::new(parse_assembly(arena, events)?)),
"RectangleLight" => {
ObjectData::Light(Box::new(parse_rectangle_light(arena, obj_data_tree)?))
Event::InnerOpen {
type_name: "MeshSurface",
..
} => ObjectData::Surface(Box::new(parse_mesh_surface(arena, events)?)),
Event::InnerOpen {
type_name: "SphereLight",
..
} => ObjectData::Light(Box::new(parse_sphere_light(arena, events)?)),
Event::InnerOpen {
type_name: "RectangleLight",
..
} => ObjectData::Light(Box::new(parse_rectangle_light(arena, events)?)),
Event::InnerClose { byte_offset } => {
return Err(PsyParseError::MissingNode(
byte_offset,
"Object contains no object data.",
));
}
_ => {
return Err(PsyParseError::UnknownVariant(
tree.byte_offset(),
byte_offset,
"Unknown data type for Object.",
));
}
}
};
};
assembly.objects.insert(
object_ident.to_string(),
Object {
data: object_data,
instance_xform_idxs: instance_xform_idxs,
},
);
} else {
// TODO: error.
// Close object node.
if let Event::InnerClose { .. } = events.next_event()? {
// Success, do nothing.
} else {
todo!(); // Return error.
}
assembly.objects.insert(
object_ident,
Object {
data: object_data,
instance_xform_idxs: instance_xform_idxs,
},
);
}
Event::InnerClose { .. } => {
break;
}
_ => {
todo!(); // Return an error.
}
}
}
// if !tree.is_internal() {
// return Err(PsyParseError::UnknownError(tree.byte_offset()));
// }
// for object in tree.iter_children() {
// if object.type_name() == "Object" {
// } else {
// // TODO: error.
// }
// }
return Ok(assembly);
}

View File

@ -1,15 +1,12 @@
#![allow(dead_code)]
use std::result::Result;
use std::{io::BufRead, result::Result};
use nom::{combinator::all_consuming, sequence::tuple, IResult};
use kioku::Arena;
use data_tree::{
reader::{DataTreeReader, ReaderError},
Event,
};
use data_tree::{reader::DataTreeReader, Event};
use crate::{
light::{DistantDiskLight, RectangleLight, SphereLight},
@ -19,174 +16,175 @@ use crate::{
use super::{
basics::ws_f32,
psy::{parse_color, PsyParseError},
DataTree,
};
pub fn parse_distant_disk_light<'a>(
arena: &'a Arena,
events: &mut DataTreeReader,
ident: Option<&str>,
events: &mut DataTreeReader<impl BufRead>,
_ident: Option<&str>,
) -> Result<DistantDiskLight<'a>, PsyParseError> {
if let DataTree::Internal { ref children, .. } = *tree {
let mut radii = Vec::new();
let mut directions = Vec::new();
let mut colors = Vec::new();
let mut radii = Vec::new();
let mut directions = Vec::new();
let mut colors = Vec::new();
// Parse
for child in children.iter() {
match child {
// Radius
DataTree::Leaf {
type_name,
contents,
byte_offset,
} if type_name == "Radius" => {
if let IResult::Ok((_, radius)) = all_consuming(ws_f32)(&contents) {
radii.push(radius);
} else {
// Found radius, but its contents is not in the right format
return Err(PsyParseError::UnknownError(*byte_offset));
}
// Parse
loop {
match events.next_event()? {
Event::Leaf {
type_name: "Radius",
contents,
byte_offset,
} => {
if let IResult::Ok((_, radius)) = all_consuming(ws_f32)(&contents) {
radii.push(radius);
} else {
// Found radius, but its contents is not in the right format
return Err(PsyParseError::UnknownError(byte_offset));
}
}
// Direction
DataTree::Leaf {
type_name,
contents,
byte_offset,
} if type_name == "Direction" => {
if let IResult::Ok((_, direction)) =
all_consuming(tuple((ws_f32, ws_f32, ws_f32)))(&contents)
{
directions.push(Vector::new(direction.0, direction.1, direction.2));
} else {
// Found direction, but its contents is not in the right format
return Err(PsyParseError::UnknownError(*byte_offset));
}
// Direction
Event::Leaf {
type_name: "Direction",
contents,
byte_offset,
} => {
if let IResult::Ok((_, direction)) =
all_consuming(tuple((ws_f32, ws_f32, ws_f32)))(&contents)
{
directions.push(Vector::new(direction.0, direction.1, direction.2));
} else {
// Found direction, but its contents is not in the right format
return Err(PsyParseError::UnknownError(byte_offset));
}
}
// Color
DataTree::Leaf {
type_name,
contents,
byte_offset,
} if type_name == "Color" => {
if let Ok(color) = parse_color(&contents) {
colors.push(color);
} else {
// Found color, but its contents is not in the right format
return Err(PsyParseError::UnknownError(*byte_offset));
}
// Color
Event::Leaf {
type_name: "Color",
contents,
byte_offset,
} => {
if let Ok(color) = parse_color(&contents) {
colors.push(color);
} else {
// Found color, but its contents is not in the right format
return Err(PsyParseError::UnknownError(byte_offset));
}
}
_ => {}
Event::InnerClose { .. } => {
break;
}
_ => {
todo!(); // Return error.
}
}
return Ok(DistantDiskLight::new(arena, &radii, &directions, &colors));
} else {
return Err(PsyParseError::UnknownError(tree.byte_offset()));
}
return Ok(DistantDiskLight::new(arena, &radii, &directions, &colors));
}
pub fn parse_sphere_light<'a>(
arena: &'a Arena,
events: &mut DataTreeReader,
ident: Option<&str>,
events: &mut DataTreeReader<impl BufRead>,
) -> Result<SphereLight<'a>, PsyParseError> {
if let DataTree::Internal { ref children, .. } = *tree {
let mut radii = Vec::new();
let mut colors = Vec::new();
let mut radii = Vec::new();
let mut colors = Vec::new();
// Parse
for child in children.iter() {
match child {
// Radius
DataTree::Leaf {
type_name,
contents,
byte_offset,
} if type_name == "Radius" => {
if let IResult::Ok((_, radius)) = all_consuming(ws_f32)(&contents) {
radii.push(radius);
} else {
// Found radius, but its contents is not in the right format
return Err(PsyParseError::UnknownError(*byte_offset));
}
// Parse
loop {
match events.next_event()? {
// Radius
Event::Leaf {
type_name: "Radius",
contents,
byte_offset,
} => {
if let IResult::Ok((_, radius)) = all_consuming(ws_f32)(&contents) {
radii.push(radius);
} else {
// Found radius, but its contents is not in the right format
return Err(PsyParseError::UnknownError(byte_offset));
}
}
// Color
DataTree::Leaf {
type_name,
contents,
byte_offset,
} if type_name == "Color" => {
if let Ok(color) = parse_color(&contents) {
colors.push(color);
} else {
// Found color, but its contents is not in the right format
return Err(PsyParseError::UnknownError(*byte_offset));
}
// Color
Event::Leaf {
type_name: "Color",
contents,
byte_offset,
} => {
if let Ok(color) = parse_color(&contents) {
colors.push(color);
} else {
// Found color, but its contents is not in the right format
return Err(PsyParseError::UnknownError(byte_offset));
}
}
_ => {}
Event::InnerClose { .. } => {
break;
}
_ => {
todo!(); // Return error.
}
}
return Ok(SphereLight::new(arena, &radii, &colors));
} else {
return Err(PsyParseError::UnknownError(tree.byte_offset()));
}
return Ok(SphereLight::new(arena, &radii, &colors));
}
pub fn parse_rectangle_light<'a>(
arena: &'a Arena,
events: &mut DataTreeReader,
ident: Option<&str>,
events: &mut DataTreeReader<impl BufRead>,
) -> Result<RectangleLight<'a>, PsyParseError> {
if let DataTree::Internal { ref children, .. } = *tree {
let mut dimensions = Vec::new();
let mut colors = Vec::new();
let mut dimensions = Vec::new();
let mut colors = Vec::new();
// Parse
for child in children.iter() {
match child {
// Dimensions
DataTree::Leaf {
type_name,
contents,
byte_offset,
} if type_name == "Dimensions" => {
if let IResult::Ok((_, radius)) =
all_consuming(tuple((ws_f32, ws_f32)))(&contents)
{
dimensions.push(radius);
} else {
// Found dimensions, but its contents is not in the right format
return Err(PsyParseError::UnknownError(*byte_offset));
}
// Parse
loop {
match events.next_event()? {
// Dimensions
Event::Leaf {
type_name: "Dimensions",
contents,
byte_offset,
} => {
if let IResult::Ok((_, radius)) = all_consuming(tuple((ws_f32, ws_f32)))(&contents)
{
dimensions.push(radius);
} else {
// Found dimensions, but its contents is not in the right format
return Err(PsyParseError::UnknownError(byte_offset));
}
}
// Color
DataTree::Leaf {
type_name,
contents,
byte_offset,
} if type_name == "Color" => {
if let Ok(color) = parse_color(&contents) {
colors.push(color);
} else {
// Found color, but its contents is not in the right format
return Err(PsyParseError::UnknownError(*byte_offset));
}
// Color
Event::Leaf {
type_name: "Color",
contents,
byte_offset,
} => {
if let Ok(color) = parse_color(&contents) {
colors.push(color);
} else {
// Found color, but its contents is not in the right format
return Err(PsyParseError::UnknownError(byte_offset));
}
}
_ => {}
Event::InnerClose { .. } => {
break;
}
_ => {
todo!(); // Return error.
}
}
return Ok(RectangleLight::new(arena, &dimensions, &colors));
} else {
return Err(PsyParseError::UnknownError(tree.byte_offset()));
}
return Ok(RectangleLight::new(arena, &dimensions, &colors));
}

View File

@ -1,15 +1,12 @@
#![allow(dead_code)]
use std::result::Result;
use std::{io::BufRead, result::Result};
use nom::{sequence::tuple, IResult};
use kioku::Arena;
use data_tree::{
reader::{DataTreeReader, ReaderError},
Event,
};
use data_tree::{reader::DataTreeReader, Event};
use crate::{
math::{Normal, Point},
@ -19,7 +16,6 @@ use crate::{
use super::{
basics::{ws_f32, ws_usize},
psy::PsyParseError,
DataTree,
};
// pub struct TriangleMesh {
@ -31,48 +27,108 @@ use super::{
pub fn parse_mesh_surface<'a>(
arena: &'a Arena,
events: &mut DataTreeReader,
ident: Option<&str>,
events: &mut DataTreeReader<impl BufRead>,
) -> 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
let mut face_vert_counts = Vec::new();
let mut face_vert_indices = Vec::new();
// TODO: make sure there are the right number of various children,
// and other validation.
loop {
match events.next_event()? {
Event::Leaf {
type_name: "SurfaceShaderBind",
..
} => {
// TODO
}
// Get verts
for (_, mut text, _) in tree.iter_leaf_children_with_type("Vertices") {
// Collect verts for this time sample
let mut tverts = Vec::new();
while let IResult::Ok((remaining, vert)) = tuple((ws_f32, ws_f32, ws_f32))(text) {
text = remaining;
Event::Leaf {
type_name: "Vertices",
contents,
..
} => {
// Collect verts for this time sample
let mut text = contents;
let mut tverts = Vec::new();
while let IResult::Ok((remaining, vert)) = tuple((ws_f32, ws_f32, ws_f32))(text) {
text = remaining;
tverts.push(Point::new(vert.0, vert.1, vert.2));
tverts.push(Point::new(vert.0, vert.1, vert.2));
}
verts.push(tverts);
}
Event::Leaf {
type_name: "Normals",
contents,
..
} => {
// Collect normals for this time sample
let mut text = contents;
let mut tnormals = Vec::new();
while let IResult::Ok((remaining, nor)) = tuple((ws_f32, ws_f32, ws_f32))(text) {
text = remaining;
tnormals.push(Normal::new(nor.0, nor.1, nor.2).normalized());
}
normals.push(tnormals);
}
Event::Leaf {
type_name: "FaceVertCounts",
contents,
byte_offset,
} => {
if !face_vert_counts.is_empty() {
return Err(PsyParseError::WrongNodeCount(
byte_offset,
"Meshes can only have one FaceVertCounts section.",
));
}
let mut text = contents;
while let IResult::Ok((remaining, count)) = ws_usize(text) {
text = remaining;
face_vert_counts.push(count);
}
}
Event::Leaf {
type_name: "FaceVertIndices",
contents,
byte_offset,
} => {
if !face_vert_indices.is_empty() {
return Err(PsyParseError::WrongNodeCount(
byte_offset,
"Meshes can only have one FaceVertIndices section.",
));
}
let mut text = contents;
while let IResult::Ok((remaining, index)) = ws_usize(text) {
text = remaining;
face_vert_indices.push(index);
}
}
Event::InnerClose { .. } => {
break;
}
_ => {
todo!(); // Return error.
}
}
verts.push(tverts);
}
// Make sure all time samples have same vert count
// Validation: make sure all time samples have same vert count.
let vert_count = verts[0].len();
for vs in &verts {
assert_eq!(vert_count, vs.len());
}
// Get normals, if they exist
for (_, mut text, _) in tree.iter_leaf_children_with_type("Normals") {
// Collect normals for this time sample
let mut tnormals = Vec::new();
while let IResult::Ok((remaining, nor)) = tuple((ws_f32, ws_f32, ws_f32))(text) {
text = remaining;
tnormals.push(Normal::new(nor.0, nor.1, nor.2).normalized());
}
normals.push(tnormals);
}
// Make sure normal's time samples and vert count match the vertices
// Validation: make sure normal's time samples and vert count match
// the vertices.
if !normals.is_empty() {
assert_eq!(normals.len(), verts.len());
for ns in &normals {
@ -80,22 +136,10 @@ pub fn parse_mesh_surface<'a>(
}
}
// Get face vert counts
if let Some((_, mut text, _)) = tree.iter_leaf_children_with_type("FaceVertCounts").nth(0) {
while let IResult::Ok((remaining, count)) = ws_usize(text) {
text = remaining;
face_vert_counts.push(count);
}
}
// Get face vert indices
if let Some((_, mut text, _)) = tree.iter_leaf_children_with_type("FaceVertIndices").nth(0) {
while let IResult::Ok((remaining, index)) = ws_usize(text) {
text = remaining;
face_vert_indices.push(index);
}
// Validation: make sure we have any mesh data.
if verts.is_empty() || face_vert_counts.is_empty() || face_vert_indices.is_empty() {
todo!("Meshes must have at least one non-empty of each of the following sections: Vertices, FaceVertCounts, FaceVertIndices.");
// Return an error.
}
// Build triangle mesh

View File

@ -1,20 +1,18 @@
#![allow(dead_code)]
use std::result::Result;
use std::{io::BufRead, result::Result};
use nom::{combinator::all_consuming, IResult};
use data_tree::{
reader::{DataTreeReader, ReaderError},
Event,
};
use kioku::Arena;
use data_tree::{reader::DataTreeReader, Event};
use crate::shading::{SimpleSurfaceShader, SurfaceShader};
use super::{
basics::ws_f32,
psy::{parse_color, PsyParseError},
DataTree,
};
// pub struct TriangleMesh {
@ -25,22 +23,22 @@ use super::{
// }
pub fn parse_surface_shader(
events: &mut DataTreeReader,
ident: Option<&str>,
_arena: &Arena,
events: &mut DataTreeReader<impl BufRead>,
_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 {
return Err(PsyParseError::MissingNode(
tree.byte_offset(),
"Expected a Type field in SurfaceShader.",
));
};
let shader = match type_name {
"Lambert" => {
let color = if let Some((_, contents, byte_offset)) =
tree.iter_leaf_children_with_type("Color").nth(0)
// Get shader type.
let shader = match events.next_event()? {
Event::Leaf {
type_name: "Type",
contents: "Lambert",
..
} => {
let color = if let Event::Leaf {
type_name: "Color",
contents,
byte_offset,
} = events.next_event()?
{
if let Ok(color) = parse_color(contents) {
color
@ -50,74 +48,108 @@ pub fn parse_surface_shader(
}
} else {
return Err(PsyParseError::MissingNode(
tree.byte_offset(),
events.byte_offset(),
"Expected a Color field in Lambert SurfaceShader.",
));
};
// Close shader node.
if let Event::InnerClose { .. } = events.next_event()? {
// Success, do nothing.
} else {
todo!(); // Return error.
}
Box::new(SimpleSurfaceShader::Lambert { color: color })
}
"GGX" => {
// Color
let color = if let Some((_, contents, byte_offset)) =
tree.iter_leaf_children_with_type("Color").nth(0)
{
if let Ok(color) = parse_color(contents) {
color
} else {
// Found color, but its contents is not in the right format
return Err(PsyParseError::UnknownError(byte_offset));
}
} else {
return Err(PsyParseError::MissingNode(
tree.byte_offset(),
"Expected a Color field in GTR SurfaceShader.",
));
};
Event::Leaf {
type_name: "Type",
contents: "GGX",
..
} => {
let mut color = None;
let mut roughness = None;
let mut fresnel = None;
// Roughness
let roughness = if let Some((_, contents, byte_offset)) =
tree.iter_leaf_children_with_type("Roughness").nth(0)
{
if let IResult::Ok((_, roughness)) = all_consuming(ws_f32)(contents) {
roughness
} else {
return Err(PsyParseError::UnknownError(byte_offset));
}
} else {
return Err(PsyParseError::MissingNode(
tree.byte_offset(),
"Expected a Roughness field in GTR SurfaceShader.",
));
};
loop {
match events.next_event()? {
// Color
Event::Leaf {
type_name: "Color",
contents,
byte_offset,
} => {
if let Ok(col) = parse_color(contents) {
color = Some(col);
} else {
// Found color, but its contents is not in the right
// format.
return Err(PsyParseError::UnknownError(byte_offset));
}
}
// Fresnel
let fresnel = if let Some((_, contents, byte_offset)) =
tree.iter_leaf_children_with_type("Fresnel").nth(0)
{
if let IResult::Ok((_, fresnel)) = all_consuming(ws_f32)(contents) {
fresnel
} else {
return Err(PsyParseError::UnknownError(byte_offset));
// Roughness
Event::Leaf {
type_name: "Roughness",
contents,
byte_offset,
} => {
if let IResult::Ok((_, rgh)) = all_consuming(ws_f32)(contents) {
roughness = Some(rgh);
} else {
return Err(PsyParseError::UnknownError(byte_offset));
}
}
// Fresnel
Event::Leaf {
type_name: "Fresnel",
contents,
byte_offset,
} => {
if let IResult::Ok((_, frs)) = all_consuming(ws_f32)(contents) {
fresnel = Some(frs);
} else {
return Err(PsyParseError::UnknownError(byte_offset));
}
}
Event::InnerClose { .. } => {
break;
}
_ => {
todo!(); // Return an error.
}
}
} else {
}
// Validation: make sure all fields are present.
if color == None || roughness == None || fresnel == None {
return Err(PsyParseError::MissingNode(
tree.byte_offset(),
"Expected a Fresnel field in GTR SurfaceShader.",
events.byte_offset(),
"GGX shader requires one of each field: Color, Roughness, Fresnel.",
));
};
}
Box::new(SimpleSurfaceShader::GGX {
color: color,
roughness: roughness,
fresnel: fresnel,
color: color.unwrap(),
roughness: roughness.unwrap(),
fresnel: fresnel.unwrap(),
})
}
"Emit" => {
let color = if let Some((_, contents, byte_offset)) =
tree.iter_leaf_children_with_type("Color").nth(0)
Event::Leaf {
type_name: "Type",
contents: "Emit",
..
} => {
let color = if let Event::Leaf {
type_name: "Color",
contents,
byte_offset,
} = events.next_event()?
{
if let Ok(color) = parse_color(contents) {
color
@ -127,15 +159,34 @@ pub fn parse_surface_shader(
}
} else {
return Err(PsyParseError::MissingNode(
tree.byte_offset(),
events.byte_offset(),
"Expected a Color field in Emit SurfaceShader.",
));
};
// Close shader node.
if let Event::InnerClose { .. } = events.next_event()? {
// Success, do nothing.
} else {
todo!(); // Return error.
}
Box::new(SimpleSurfaceShader::Emit { color: color })
}
_ => unimplemented!(),
Event::Leaf {
type_name: "Type",
byte_offset,
..
} => {
return Err(PsyParseError::MissingNode(
byte_offset,
"Unknown SurfaceShader type.",
));
}
_ => {
todo!(); // Return error.
}
};
Ok(shader)

View File

@ -127,8 +127,6 @@ impl Parser {
self.buf_consumed_idx += bytes_consumed;
self.total_bytes_processed += bytes_consumed;
// Hack the borrow checker, which doesn't understand
// loops apparently, and return.
Ok(event.add_to_byte_offset(self.total_bytes_processed - self.buf_consumed_idx))
}
EventParse::ReachedEnd => {
@ -157,6 +155,56 @@ impl Parser {
)),
}
}
pub fn peek_event<'a>(&'a mut self) -> Result<Event<'a>, Error> {
// Remove any consumed data.
if self.buf_consumed_idx > 0 {
self.buffer.replace_range(..self.buf_consumed_idx, "");
self.buf_consumed_idx = 0;
}
// Try to parse an event from the valid prefix.
match try_parse_event(&self.buffer) {
EventParse::Ok(event, _bytes_consumed) => {
if let Event::InnerClose { byte_offset, .. } = event {
if self.inner_opens == 0 {
return Err(Error::UnexpectedClose(
byte_offset + self.total_bytes_processed,
));
}
}
Ok(event.add_to_byte_offset(self.total_bytes_processed))
}
EventParse::ReachedEnd => {
// If we consumed all data, then if all nodes are properly
// closed we're done. Otherwise we need more input.
if self.inner_opens == 0 {
Ok(Event::ValidEnd)
} else {
Ok(Event::NeedMoreInput)
}
}
EventParse::IncompleteData => Ok(Event::NeedMoreInput),
// Hard errors.
EventParse::ExpectedTypeNameOrInnerClose(byte_offset) => Err(
Error::ExpectedTypeNameOrClose(byte_offset + self.total_bytes_processed),
),
EventParse::ExpectedOpenOrIdent(byte_offset) => Err(Error::ExpectedOpenOrIdent(
byte_offset + self.total_bytes_processed,
)),
EventParse::ExpectedInnerOpen(byte_offset) => Err(Error::ExpectedOpen(
byte_offset + self.total_bytes_processed,
)),
EventParse::UnexpectedIdent(byte_offset) => Err(Error::UnexpectedIdent(
byte_offset + self.total_bytes_processed,
)),
}
}
pub fn byte_offset(&self) -> usize {
self.total_bytes_processed + self.buf_consumed_idx
}
}
//--------------------------------------------------------------------------

View File

@ -81,4 +81,41 @@ impl<R: std::io::BufRead> DataTreeReader<R> {
}
}
}
pub fn peek_event<'a>(&'a mut self) -> Result<Event<'a>, ReaderError> {
loop {
let valid_end = match self.parser.peek_event()? {
Event::ValidEnd => true,
Event::NeedMoreInput => false,
e => {
return Ok(unsafe {
// Transmute because the borrow checker is
// over-conservative about this. It thinks
// the liftime isn't valid, but since we aren't
// mutating self after returning (and in fact
// can't because of the borrow) there's no way for
// the references in this to become invalid.
std::mem::transmute::<Event, Event>(e)
});
}
};
if !self.eof {
self.buf.clear();
let read = self.reader.read_line(&mut self.buf)?;
self.parser.push_data(&self.buf);
if read == 0 {
self.eof = true;
}
} else if !valid_end {
return Err(ReaderError::UnexpectedEOF);
} else {
return Ok(Event::ValidEnd);
}
}
}
pub fn byte_offset(&self) -> usize {
self.parser.byte_offset()
}
}