Tokenize into enum instead of string
This commit is contained in:
parent
c48790f32f
commit
b54a2b16fe
5 changed files with 376 additions and 340 deletions
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
scene::PbrtScene,
|
||||
shape::{Shape, ShapeAlpha, ShapeType},
|
||||
tokenizer::Tokenizer,
|
||||
tokenizer::{Token, Tokenizer},
|
||||
};
|
||||
use material::PbrtMaterial;
|
||||
use miette::{IntoDiagnostic, Result, bail, miette};
|
||||
|
|
@ -76,7 +76,7 @@ enum Statement {
|
|||
CoordinateSystem(String),
|
||||
CoordSysTransform(String),
|
||||
Shape(ShapeType, ShapeAlpha),
|
||||
Unknown(String, Vec<String>),
|
||||
Unknown(String, Vec<Token>),
|
||||
Transform(AffineTransform),
|
||||
Texture(String, Arc<dyn PbrtTexture>),
|
||||
Material(Arc<dyn PbrtMaterial>),
|
||||
|
|
@ -96,10 +96,12 @@ fn parse_look_at(iter: &mut Tokenizer) -> Result<Statement> {
|
|||
}
|
||||
|
||||
fn parse_shape(iter: &mut Tokenizer) -> Result<Statement> {
|
||||
let shape_type = iter.next().ok_or(miette!("unable to get shape type"))??;
|
||||
let shape_type = iter
|
||||
.next_if_string_value()
|
||||
.ok_or(miette!("unable to get shape type"))??;
|
||||
|
||||
match shape_type.as_str() {
|
||||
"\"sphere\"" => {
|
||||
"sphere" => {
|
||||
let t = parse_dict!(iter =>
|
||||
radius, Float, 1.0;
|
||||
zmin, Float, {-radius};
|
||||
|
|
@ -107,12 +109,12 @@ fn parse_shape(iter: &mut Tokenizer) -> Result<Statement> {
|
|||
phimax, Float, 360.0;
|
||||
alpha, ShapeAlpha, ShapeAlpha::None
|
||||
=>
|
||||
radius, "\"float radius\"", iter.parse_parameter()?;
|
||||
zmin, "\"float zmin\"", iter.parse_parameter()?;
|
||||
zmax, "\"float zmax\"", iter.parse_parameter()?;
|
||||
phimax, "\"float phimax\"", iter.parse_parameter()?;
|
||||
alpha, "\"float alpha\"", ShapeAlpha::Value(iter.parse_parameter()?);
|
||||
alpha, "\"texture alpha\"", ShapeAlpha::Texture(iter.parse_parameter()?)
|
||||
radius, "float radius", iter.parse_parameter()?;
|
||||
zmin, "float zmin", iter.parse_parameter()?;
|
||||
zmax, "float zmax", iter.parse_parameter()?;
|
||||
phimax, "float phimax", iter.parse_parameter()?;
|
||||
alpha, "float alpha", ShapeAlpha::Value(iter.parse_parameter()?);
|
||||
alpha, "texture alpha", ShapeAlpha::Texture(iter.parse_parameter()?)
|
||||
);
|
||||
Ok(Statement::Shape(
|
||||
ShapeType::Sphere {
|
||||
|
|
@ -124,7 +126,7 @@ fn parse_shape(iter: &mut Tokenizer) -> Result<Statement> {
|
|||
t.alpha,
|
||||
))
|
||||
}
|
||||
"\"trianglemesh\"" => {
|
||||
"trianglemesh" => {
|
||||
let t = parse_dict!(iter =>
|
||||
p, Vec<Pos3>, Vec::new();
|
||||
n, Vec<Dir3>, Vec::new();
|
||||
|
|
@ -133,13 +135,13 @@ fn parse_shape(iter: &mut Tokenizer) -> Result<Statement> {
|
|||
indices, Vec<usize>, Vec::new();
|
||||
alpha, ShapeAlpha, ShapeAlpha::None
|
||||
=>
|
||||
p, "\"point3 P\"", iter.parse_list_3(Pos3::new)?;
|
||||
n, "\"normal N\"", iter.parse_list_3(Dir3::new)?;
|
||||
s, "\"normal S\"", iter.parse_list_3(Dir3::new)?;
|
||||
uv, "\"point2 uv\"", iter.parse_list_2(|u, v| [u, v])?;
|
||||
indices, "\"integer indices\"", iter.parse_list()?;
|
||||
alpha, "\"float alpha\"", ShapeAlpha::Value(iter.parse_parameter()?);
|
||||
alpha, "\"texture alpha\"", ShapeAlpha::Texture(iter.parse_parameter()?)
|
||||
p, "point3 P", iter.parse_list_3(Pos3::new)?;
|
||||
n, "normal N", iter.parse_list_3(Dir3::new)?;
|
||||
s, "normal S", iter.parse_list_3(Dir3::new)?;
|
||||
uv, "point2 uv", iter.parse_list_2(|u, v| [u, v])?;
|
||||
indices, "integer indices", iter.parse_list()?;
|
||||
alpha, "float alpha", ShapeAlpha::Value(iter.parse_parameter()?);
|
||||
alpha, "texture alpha", ShapeAlpha::Texture(iter.parse_parameter()?)
|
||||
);
|
||||
|
||||
if t.p.len() < 3 {
|
||||
|
|
@ -178,7 +180,7 @@ fn parse_shape(iter: &mut Tokenizer) -> Result<Statement> {
|
|||
t.alpha,
|
||||
))
|
||||
}
|
||||
"\"bilinearmesh\"" => {
|
||||
"bilinearmesh" => {
|
||||
let t = parse_dict!(iter =>
|
||||
p, Vec<Pos3>, Vec::new();
|
||||
n, Vec<Dir3>, Vec::new();
|
||||
|
|
@ -186,12 +188,12 @@ fn parse_shape(iter: &mut Tokenizer) -> Result<Statement> {
|
|||
indices, Vec<usize>, Vec::new();
|
||||
alpha, ShapeAlpha, ShapeAlpha::None
|
||||
=>
|
||||
p, "\"point3 P\"", iter.parse_list_3(Pos3::new)?;
|
||||
n, "\"normal N\"", iter.parse_list_3(Dir3::new)?;
|
||||
uv, "\"point2 uv\"", iter.parse_list_2(|u, v| [u, v])?;
|
||||
indices, "\"integer indices\"", iter.parse_list()?;
|
||||
alpha, "\"float alpha\"", ShapeAlpha::Value(iter.parse_parameter()?);
|
||||
alpha, "\"texture alpha\"", ShapeAlpha::Texture(iter.parse_parameter()?)
|
||||
p, "point3 P", iter.parse_list_3(Pos3::new)?;
|
||||
n, "normal N", iter.parse_list_3(Dir3::new)?;
|
||||
uv, "point2 uv", iter.parse_list_2(|u, v| [u, v])?;
|
||||
indices, "integer indices", iter.parse_list()?;
|
||||
alpha, "float alpha", ShapeAlpha::Value(iter.parse_parameter()?);
|
||||
alpha, "texture alpha", ShapeAlpha::Texture(iter.parse_parameter()?)
|
||||
);
|
||||
|
||||
if t.p.len() < 4 {
|
||||
|
|
@ -226,18 +228,18 @@ fn parse_shape(iter: &mut Tokenizer) -> Result<Statement> {
|
|||
t.alpha,
|
||||
))
|
||||
}
|
||||
"\"loopsubdiv\"" => {
|
||||
"loopsubdiv" => {
|
||||
let t = parse_dict!(iter =>
|
||||
levels, u32, 3;
|
||||
indices, Vec<usize>, Vec::new();
|
||||
p, Vec<Pos3>, Vec::new();
|
||||
alpha, ShapeAlpha, ShapeAlpha::None
|
||||
=>
|
||||
levels, "\"integer levels\"", iter.parse_parameter()?;
|
||||
indices, "\"integer indices\"", iter.parse_list()?;
|
||||
p, "\"point3 P\"", iter.parse_list_3(Pos3::new)?;
|
||||
alpha, "\"float alpha\"", ShapeAlpha::Value(iter.parse_parameter()?);
|
||||
alpha, "\"texture alpha\"", ShapeAlpha::Texture(iter.parse_parameter()?)
|
||||
levels, "integer levels", iter.parse_parameter()?;
|
||||
indices, "integer indices", iter.parse_list()?;
|
||||
p, "point3 P", iter.parse_list_3(Pos3::new)?;
|
||||
alpha, "float alpha", ShapeAlpha::Value(iter.parse_parameter()?);
|
||||
alpha, "texture alpha", ShapeAlpha::Texture(iter.parse_parameter()?)
|
||||
);
|
||||
|
||||
if t.indices.is_empty() {
|
||||
|
|
@ -257,7 +259,7 @@ fn parse_shape(iter: &mut Tokenizer) -> Result<Statement> {
|
|||
t.alpha,
|
||||
))
|
||||
}
|
||||
"\"disk\"" => {
|
||||
"disk" => {
|
||||
let t = parse_dict!(iter =>
|
||||
height, Float, 0.0;
|
||||
radius, Float, 1.0;
|
||||
|
|
@ -265,12 +267,12 @@ fn parse_shape(iter: &mut Tokenizer) -> Result<Statement> {
|
|||
phimax, Float, 360.0;
|
||||
alpha, ShapeAlpha, ShapeAlpha::None
|
||||
=>
|
||||
height, "\"float height\"", iter.parse_parameter()?;
|
||||
radius, "\"float radius\"", iter.parse_parameter()?;
|
||||
innerradius, "\"float innerradius\"", iter.parse_parameter()?;
|
||||
phimax, "\"float phimax\"", iter.parse_parameter()?;
|
||||
alpha, "\"float alpha\"", ShapeAlpha::Value(iter.parse_parameter()?);
|
||||
alpha, "\"texture alpha\"", ShapeAlpha::Texture(iter.parse_parameter()?)
|
||||
height, "float height", iter.parse_parameter()?;
|
||||
radius, "float radius", iter.parse_parameter()?;
|
||||
innerradius, "float innerradius", iter.parse_parameter()?;
|
||||
phimax, "float phimax", iter.parse_parameter()?;
|
||||
alpha, "float alpha", ShapeAlpha::Value(iter.parse_parameter()?);
|
||||
alpha, "texture alpha", ShapeAlpha::Texture(iter.parse_parameter()?)
|
||||
);
|
||||
|
||||
Ok(Statement::Shape(
|
||||
|
|
@ -283,18 +285,18 @@ fn parse_shape(iter: &mut Tokenizer) -> Result<Statement> {
|
|||
t.alpha,
|
||||
))
|
||||
}
|
||||
"\"plymesh\"" => {
|
||||
"plymesh" => {
|
||||
let t = parse_dict!(iter =>
|
||||
filename, String, String::new();
|
||||
displacement, Option<String>, None;
|
||||
edgelength, Float, 1.0;
|
||||
alpha, ShapeAlpha, ShapeAlpha::None
|
||||
=>
|
||||
filename, "\"string filename\"", iter.parse_parameter()?;
|
||||
displacement, "\"string displacement\"", Some(iter.parse_parameter()?);
|
||||
edgelength, "\"float edgelength\"", iter.parse_parameter()?;
|
||||
alpha, "\"float alpha\"", ShapeAlpha::Value(iter.parse_parameter()?);
|
||||
alpha, "\"texture alpha\"", ShapeAlpha::Texture(iter.parse_parameter()?)
|
||||
filename, "string filename", iter.parse_parameter()?;
|
||||
displacement, "string displacement", Some(iter.parse_parameter()?);
|
||||
edgelength, "float edgelength", iter.parse_parameter()?;
|
||||
alpha, "float alpha", ShapeAlpha::Value(iter.parse_parameter()?);
|
||||
alpha, "texture alpha", ShapeAlpha::Texture(iter.parse_parameter()?)
|
||||
);
|
||||
|
||||
Ok(Statement::Shape(
|
||||
|
|
@ -312,11 +314,11 @@ fn parse_shape(iter: &mut Tokenizer) -> Result<Statement> {
|
|||
|
||||
fn parse_camera(tokenizer: &mut Tokenizer) -> Result<Statement> {
|
||||
let camera_type = tokenizer
|
||||
.next()
|
||||
.next_if_string_value()
|
||||
.ok_or(miette!("unable to get shape type"))??;
|
||||
|
||||
match camera_type.as_str() {
|
||||
"\"orthographic\"" => {
|
||||
"orthographic" => {
|
||||
let t = parse_dict!(tokenizer =>
|
||||
shutteropen, Float, 0.0;
|
||||
shutterclose, Float, 1.0;
|
||||
|
|
@ -325,12 +327,12 @@ fn parse_camera(tokenizer: &mut Tokenizer) -> Result<Statement> {
|
|||
lens_radius, Float, 0.0;
|
||||
focal_distance, Float, Float::powi(10.0, 30)
|
||||
=>
|
||||
shutteropen, "\"float shutteropen\"", tokenizer.parse_parameter()?;
|
||||
shutterclose, "\"float shutterclose\"", tokenizer.parse_parameter()?;
|
||||
frame_aspect_ratio, "\"float frameaspectratio\"", Some(tokenizer.parse_parameter()?);
|
||||
screen_window, "\"float screenwindow\"", Some(tokenizer.parse_parameter()?);
|
||||
lens_radius, "\"float lensradius\"", tokenizer.parse_parameter()?;
|
||||
focal_distance, "\"float focaldistance\"", tokenizer.parse_parameter()?
|
||||
shutteropen, "float shutteropen", tokenizer.parse_parameter()?;
|
||||
shutterclose, "float shutterclose", tokenizer.parse_parameter()?;
|
||||
frame_aspect_ratio, "float frameaspectratio", Some(tokenizer.parse_parameter()?);
|
||||
screen_window, "float screenwindow", Some(tokenizer.parse_parameter()?);
|
||||
lens_radius, "float lensradius", tokenizer.parse_parameter()?;
|
||||
focal_distance, "float focaldistance", tokenizer.parse_parameter()?
|
||||
);
|
||||
|
||||
Ok(Statement::Camera(PbrtCamera {
|
||||
|
|
@ -344,7 +346,7 @@ fn parse_camera(tokenizer: &mut Tokenizer) -> Result<Statement> {
|
|||
shutter_close: t.shutterclose,
|
||||
}))
|
||||
}
|
||||
"\"perspective\"" => {
|
||||
"perspective" => {
|
||||
let t = parse_dict!(tokenizer =>
|
||||
shutteropen, Float, 0.0;
|
||||
shutterclose, Float, 1.0;
|
||||
|
|
@ -354,13 +356,13 @@ fn parse_camera(tokenizer: &mut Tokenizer) -> Result<Statement> {
|
|||
focal_distance, Float, Float::powi(10.0, 30);
|
||||
fov, Float, 90.0
|
||||
=>
|
||||
shutteropen, "\"float shutteropen\"", tokenizer.parse_parameter()?;
|
||||
shutterclose, "\"float shutterclose\"", tokenizer.parse_parameter()?;
|
||||
frame_aspect_ratio, "\"float frameaspectratio\"", Some(tokenizer.parse_parameter()?);
|
||||
screen_window, "\"float screenwindow\"", Some(tokenizer.parse_parameter()?);
|
||||
lens_radius, "\"float lensradius\"", tokenizer.parse_parameter()?;
|
||||
focal_distance, "\"float focaldistance\"", tokenizer.parse_parameter()?;
|
||||
fov, "\"float fov\"", tokenizer.parse_parameter()?
|
||||
shutteropen, "float shutteropen", tokenizer.parse_parameter()?;
|
||||
shutterclose, "float shutterclose", tokenizer.parse_parameter()?;
|
||||
frame_aspect_ratio, "float frameaspectratio", Some(tokenizer.parse_parameter()?);
|
||||
screen_window, "float screenwindow", Some(tokenizer.parse_parameter()?);
|
||||
lens_radius, "float lensradius", tokenizer.parse_parameter()?;
|
||||
focal_distance, "float focaldistance", tokenizer.parse_parameter()?;
|
||||
fov, "float fov", tokenizer.parse_parameter()?
|
||||
);
|
||||
|
||||
Ok(Statement::Camera(PbrtCamera {
|
||||
|
|
@ -382,16 +384,15 @@ fn parse_camera(tokenizer: &mut Tokenizer) -> Result<Statement> {
|
|||
impl Lexer {
|
||||
fn next(&mut self, context: &PbrtContext) -> Option<Result<Statement>> {
|
||||
match self.input.next() {
|
||||
Some(Ok(s)) => match s.as_str() {
|
||||
Some(Ok(Token::Identifier(s))) => match s.as_str() {
|
||||
"AttributeBegin" => Some(Ok(Statement::AttributeBegin)),
|
||||
"AttributeEnd" => Some(Ok(Statement::AttributeEnd)),
|
||||
"Include" => {
|
||||
let s = self
|
||||
.input
|
||||
.next()
|
||||
.next_if_string_value()
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.trim_matches('"')
|
||||
.to_string();
|
||||
|
||||
Some(Ok(Statement::Include(s)))
|
||||
|
|
@ -434,9 +435,8 @@ impl Lexer {
|
|||
} else {
|
||||
let mut v = Vec::new();
|
||||
|
||||
while let Some(p) = self
|
||||
.input
|
||||
.next_if(|s| !s.starts_with(|c: char| c.is_ascii_alphabetic()))
|
||||
while let Some(p) =
|
||||
self.input.next_if(|s| !matches!(s, Token::Identifier(_)))
|
||||
{
|
||||
match p {
|
||||
Ok(c) => v.push(c),
|
||||
|
|
@ -448,6 +448,10 @@ impl Lexer {
|
|||
}
|
||||
}
|
||||
},
|
||||
Some(Ok(s)) => Some(Err(miette!(
|
||||
labels = vec![self.input.last_span_labeled(Some("here"))],
|
||||
"expected identifier got {s:?}"
|
||||
))),
|
||||
Some(Err(e)) => Some(Err(e)),
|
||||
None => None,
|
||||
}
|
||||
|
|
@ -455,29 +459,14 @@ impl Lexer {
|
|||
}
|
||||
|
||||
fn parse_transform(input: &mut Tokenizer) -> Result<AffineTransform> {
|
||||
if !input
|
||||
.next()
|
||||
.is_none_or(|p| p.is_ok_and(|p| p.as_str() == "["))
|
||||
{
|
||||
bail!("expected list.")
|
||||
}
|
||||
|
||||
input.next_expect_bracket_open()?;
|
||||
let mut v = [0.0; 16];
|
||||
|
||||
for i in &mut v {
|
||||
*i = input
|
||||
.next()
|
||||
.ok_or(miette!("value expected"))??
|
||||
.parse::<Float>()
|
||||
.into_diagnostic()?;
|
||||
*i = input.parse_next()?;
|
||||
}
|
||||
|
||||
if !input
|
||||
.next()
|
||||
.is_none_or(|p| p.is_ok_and(|p| p.as_str() == "]"))
|
||||
{
|
||||
bail!("expected list end.")
|
||||
}
|
||||
input.next_expect_bracket_close()?;
|
||||
|
||||
if v[3] != 0.0 || v[7] != 0.0 || v[11] != 0.0 || v[15] != 1.0 {
|
||||
bail!("invalid transform entry")
|
||||
|
|
@ -509,24 +498,11 @@ fn parse_scale(iter: &mut Tokenizer) -> Result<Statement> {
|
|||
}
|
||||
|
||||
fn parse_rotate(iter: &mut Tokenizer) -> Result<Statement> {
|
||||
let angle = iter
|
||||
.next()
|
||||
.ok_or(miette!("missing argument"))??
|
||||
.parse()
|
||||
.into_diagnostic()?;
|
||||
let angle = iter.parse_parameter()?;
|
||||
let dir = Dir3::new(
|
||||
iter.next()
|
||||
.ok_or(miette!("missing argument"))??
|
||||
.parse()
|
||||
.into_diagnostic()?,
|
||||
iter.next()
|
||||
.ok_or(miette!("missing argument"))??
|
||||
.parse()
|
||||
.into_diagnostic()?,
|
||||
iter.next()
|
||||
.ok_or(miette!("missing argument"))??
|
||||
.parse()
|
||||
.into_diagnostic()?,
|
||||
iter.parse_parameter()?,
|
||||
iter.parse_parameter()?,
|
||||
iter.parse_parameter()?,
|
||||
);
|
||||
|
||||
Ok(Statement::ConcatTransform(AffineTransform::rotation(
|
||||
|
|
@ -721,7 +697,7 @@ fn inner_parse_pbrt(path: impl AsRef<Path> + std::fmt::Debug) -> Result<Pbrt> {
|
|||
return Err(miette!("The camera can only be set once."));
|
||||
}
|
||||
camera = Some((c, context.get_ctm()));
|
||||
named_transforms.insert(String::from("\"camera\""), context.get_ctm());
|
||||
named_transforms.insert(String::from("camera"), context.get_ctm());
|
||||
}
|
||||
Statement::CoordinateSystem(s) => {
|
||||
named_transforms.insert(s, context.get_ctm());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue