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:
parent
5196e8e2c2
commit
4f564d1474
|
@ -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 {
|
||||
|
|
|
@ -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_ {
|
||||
|
|
|
@ -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 {
|
||||
|
|
50
src/main.rs
50
src/main.rs
|
@ -47,15 +47,12 @@ use nom::bytes::complete::take_until;
|
|||
|
||||
use kioku::Arena;
|
||||
|
||||
use data_tree::{
|
||||
reader::{DataTreeReader, ReaderError},
|
||||
Event,
|
||||
};
|
||||
use data_tree::{reader::DataTreeReader, Event};
|
||||
|
||||
use crate::{
|
||||
accel::BVH4Node,
|
||||
bbox::BBox,
|
||||
parse::{parse_scene, DataTree},
|
||||
parse::parse_scene,
|
||||
// renderer::LightPath,
|
||||
surface::SurfaceIntersection,
|
||||
timer::Timer,
|
||||
|
@ -242,27 +239,14 @@ fn main() {
|
|||
// println!("\tParsed scene file in {:.3}s", t.tick());
|
||||
// }
|
||||
|
||||
let mut psy_file = io::BufReader::new(File::open(fp).unwrap());
|
||||
let file_path = args.value_of("input").unwrap();
|
||||
let mut psy_file = io::BufReader::new(File::open(file_path).unwrap());
|
||||
let mut events = DataTreeReader::new(&mut psy_file);
|
||||
|
||||
// Iterate through scenes and render them
|
||||
loop {
|
||||
t.tick();
|
||||
match events.next_event() {
|
||||
Ok(Event::ValidEnd) => {
|
||||
break;
|
||||
}
|
||||
|
||||
Ok(_) => {
|
||||
println!("Error: invalid scene in psy file.");
|
||||
break;
|
||||
}
|
||||
|
||||
Err(e) => {
|
||||
println!("Error: {:?}", e);
|
||||
break;
|
||||
}
|
||||
|
||||
// Parse a scene and render it.
|
||||
Ok(Event::InnerOpen {
|
||||
type_name: "Scene",
|
||||
|
@ -274,11 +258,13 @@ fn main() {
|
|||
}
|
||||
|
||||
let arena = Arena::new().with_block_size((1 << 20) * 4);
|
||||
let ident = ident.into::<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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
136
src/parse/psy.rs
136
src/parse/psy.rs
|
@ -26,7 +26,6 @@ use super::{
|
|||
psy_assembly::parse_assembly,
|
||||
psy_light::parse_distant_disk_light,
|
||||
psy_surface_shader::parse_surface_shader,
|
||||
DataTree,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -34,13 +33,13 @@ pub enum PsyParseError {
|
|||
// The first usize for all errors is their byte offset
|
||||
// into the psy content where they occured.
|
||||
UnknownError(usize),
|
||||
UnknownVariant(usize, &'static str), // Error message
|
||||
ExpectedInternalNode(usize, &'static str), // Error message
|
||||
ExpectedLeafNode(usize, &'static str), // Error message
|
||||
ExpectedIdent(usize, &'static str), // Error message
|
||||
MissingNode(usize, &'static str), // Error message
|
||||
IncorrectLeafData(usize, &'static str), // Error message
|
||||
WrongNodeCount(usize, &'static str, usize), // Error message, sections found
|
||||
UnknownVariant(usize, &'static str), // Error message
|
||||
ExpectedInternalNode(usize, &'static str), // Error message
|
||||
ExpectedLeafNode(usize, &'static str), // Error message
|
||||
ExpectedIdent(usize, &'static str), // Error message
|
||||
MissingNode(usize, &'static str), // Error message
|
||||
IncorrectLeafData(usize, &'static str), // Error message
|
||||
WrongNodeCount(usize, &'static str), // Error message
|
||||
InstancedMissingData(usize, &'static str, String), // Error message, data name
|
||||
ReaderError(ReaderError),
|
||||
}
|
||||
|
@ -87,15 +86,17 @@ impl PsyParseError {
|
|||
println!("Line {}: {}", line, error);
|
||||
}
|
||||
|
||||
PsyParseError::WrongNodeCount(offset, error, count) => {
|
||||
PsyParseError::WrongNodeCount(offset, error) => {
|
||||
let line = line_count_to_byte_offset(psy_content, offset);
|
||||
println!("Line {}: {} Found: {}", line, error, count);
|
||||
println!("Line {}: {}", line, error);
|
||||
}
|
||||
|
||||
PsyParseError::InstancedMissingData(offset, error, ref data_name) => {
|
||||
let line = line_count_to_byte_offset(psy_content, offset);
|
||||
println!("Line {}: {} Data name: '{}'", line, error, data_name);
|
||||
}
|
||||
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -124,10 +125,10 @@ fn line_count_to_byte_offset(text: &str, offset: usize) -> usize {
|
|||
pub fn parse_scene<'a>(
|
||||
arena: &'a Arena,
|
||||
events: &mut DataTreeReader<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.
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user