More error handling

This commit is contained in:
hal8174 2025-08-09 23:23:36 +02:00
parent 5b5e491cb2
commit b56f952e9b
Signed by: hal8174
SSH key fingerprint: SHA256:NN98ZYwnrreQLSOV/g+amY7C3yL/mS1heD7bi5t6PPw

View file

@ -31,7 +31,7 @@ enum Statement {
WorldBegin, WorldBegin,
Include(String), Include(String),
ConcatTransform(AffineTransform), ConcatTransform(AffineTransform),
Shape(ShapeType), Shape(ShapeType, ShapeAlpha),
Unknown(String, Vec<String>), Unknown(String, Vec<String>),
Transform(AffineTransform), Transform(AffineTransform),
} }
@ -56,24 +56,34 @@ fn parse_shape(iter: &mut Tokenizer) -> Result<Statement> {
let zmin = -radius; let zmin = -radius;
let zmax = radius; let zmax = radius;
let phimax = 360.0; let phimax = 360.0;
let mut alpha = ShapeAlpha::None;
while let Some(p) = iter.next_if(|p| p.starts_with('"')).transpose()? { while let Some(p) = iter.next_if(|p| p.starts_with('"')).transpose()? {
match p.as_str() { match p.as_str() {
"\"float radius\"" => { "\"float radius\"" => {
radius = iter.parse_parameter()?; radius = iter.parse_parameter()?;
} }
"\"float alpha\"" => {
alpha = ShapeAlpha::Value(iter.parse_parameter()?);
}
"\"texture alpha\"" => {
alpha = ShapeAlpha::Texture(iter.parse_parameter()?);
}
_ => { _ => {
bail!("unknown argument {}", p) bail!("unknown argument {}", p)
} }
} }
} }
Ok(Statement::Shape(ShapeType::Sphere { Ok(Statement::Shape(
radius, ShapeType::Sphere {
zmin, radius,
zmax, zmin,
phimax, zmax,
})) phimax,
},
alpha,
))
} }
"\"trianglemesh\"" => { "\"trianglemesh\"" => {
let mut indices = Vec::new(); let mut indices = Vec::new();
@ -81,6 +91,7 @@ fn parse_shape(iter: &mut Tokenizer) -> Result<Statement> {
let mut n = Vec::new(); let mut n = Vec::new();
let mut s = Vec::new(); let mut s = Vec::new();
let mut uv = Vec::new(); let mut uv = Vec::new();
let mut alpha = ShapeAlpha::None;
while let Some(q) = iter.next_if(|p| p.starts_with('"')).transpose()? { while let Some(q) = iter.next_if(|p| p.starts_with('"')).transpose()? {
match q.as_str() { match q.as_str() {
@ -99,6 +110,12 @@ fn parse_shape(iter: &mut Tokenizer) -> Result<Statement> {
"\"point2 uv\"" => { "\"point2 uv\"" => {
iter.parse_list_2(&mut uv, |u, v| [u, v])?; iter.parse_list_2(&mut uv, |u, v| [u, v])?;
} }
"\"float alpha\"" => {
alpha = ShapeAlpha::Value(iter.parse_parameter()?);
}
"\"texture alpha\"" => {
alpha = ShapeAlpha::Texture(iter.parse_parameter()?);
}
_ => { _ => {
bail!("unknown argument {}", q) bail!("unknown argument {}", q)
} }
@ -128,19 +145,23 @@ fn parse_shape(iter: &mut Tokenizer) -> Result<Statement> {
if !uv.is_empty() && uv.len() != p.len() { if !uv.is_empty() && uv.len() != p.len() {
bail!("Number of uvs not equal to number of positions.") bail!("Number of uvs not equal to number of positions.")
} }
Ok(Statement::Shape(ShapeType::TriangleMesh { Ok(Statement::Shape(
indices, ShapeType::TriangleMesh {
p, indices,
n, p,
s, n,
uv, s,
})) uv,
},
alpha,
))
} }
"\"bilinearmesh\"" => { "\"bilinearmesh\"" => {
let mut indices = Vec::new(); let mut indices = Vec::new();
let mut p = Vec::new(); let mut p = Vec::new();
let mut n = Vec::new(); let mut n = Vec::new();
let mut uv = Vec::new(); let mut uv = Vec::new();
let mut alpha = ShapeAlpha::None;
while let Some(q) = iter.next_if(|p| p.starts_with('"')).transpose()? { while let Some(q) = iter.next_if(|p| p.starts_with('"')).transpose()? {
match q.as_str() { match q.as_str() {
@ -156,6 +177,12 @@ fn parse_shape(iter: &mut Tokenizer) -> Result<Statement> {
"\"vector N\"" => { "\"vector N\"" => {
iter.parse_list_3(&mut n, Dir3::new)?; iter.parse_list_3(&mut n, Dir3::new)?;
} }
"\"float alpha\"" => {
alpha = ShapeAlpha::Value(iter.parse_parameter()?);
}
"\"texture alpha\"" => {
alpha = ShapeAlpha::Texture(iter.parse_parameter()?);
}
_ => { _ => {
bail!("unknown argument {}", q) bail!("unknown argument {}", q)
} }
@ -183,12 +210,10 @@ fn parse_shape(iter: &mut Tokenizer) -> Result<Statement> {
if !uv.is_empty() && uv.len() != p.len() { if !uv.is_empty() && uv.len() != p.len() {
bail!("Number of uvs not equal to number of positions.") bail!("Number of uvs not equal to number of positions.")
} }
Ok(Statement::Shape(ShapeType::BilinearMesh { Ok(Statement::Shape(
indices, ShapeType::BilinearMesh { indices, p, n, uv },
p, alpha,
n, ))
uv,
}))
} }
"\"loopsubdiv\"" => { "\"loopsubdiv\"" => {
@ -196,6 +221,7 @@ fn parse_shape(iter: &mut Tokenizer) -> Result<Statement> {
let mut indices = Vec::new(); let mut indices = Vec::new();
let mut p = Vec::new(); let mut p = Vec::new();
let mut alpha = ShapeAlpha::None;
while let Some(q) = iter.next_if(|p| p.starts_with('"')).transpose()? { while let Some(q) = iter.next_if(|p| p.starts_with('"')).transpose()? {
match q.as_str() { match q.as_str() {
@ -208,6 +234,12 @@ fn parse_shape(iter: &mut Tokenizer) -> Result<Statement> {
"\"integer levels\"" => { "\"integer levels\"" => {
levels = iter.parse_parameter()?; levels = iter.parse_parameter()?;
} }
"\"float alpha\"" => {
alpha = ShapeAlpha::Value(iter.parse_parameter()?);
}
"\"texture alpha\"" => {
alpha = ShapeAlpha::Texture(iter.parse_parameter()?);
}
_ => { _ => {
bail!("unknown argument {}", q) bail!("unknown argument {}", q)
} }
@ -222,17 +254,17 @@ fn parse_shape(iter: &mut Tokenizer) -> Result<Statement> {
bail!("p is a required field") bail!("p is a required field")
} }
Ok(Statement::Shape(ShapeType::LoopSubDiv { Ok(Statement::Shape(
levels, ShapeType::LoopSubDiv { levels, indices, p },
indices, alpha,
p, ))
}))
} }
"\"disk\"" => { "\"disk\"" => {
let mut height = 0.0; let mut height = 0.0;
let mut radius = 1.0; let mut radius = 1.0;
let mut innerradius = 0.0; let mut innerradius = 0.0;
let mut phimax = 360.0; let mut phimax = 360.0;
let mut alpha = ShapeAlpha::None;
while let Some(q) = iter.next_if(|p| p.starts_with('"')).transpose()? { while let Some(q) = iter.next_if(|p| p.starts_with('"')).transpose()? {
match q.as_str() { match q.as_str() {
@ -240,18 +272,57 @@ fn parse_shape(iter: &mut Tokenizer) -> Result<Statement> {
"\"float radius\"" => radius = iter.parse_parameter()?, "\"float radius\"" => radius = iter.parse_parameter()?,
"\"float innerradius\"" => innerradius = iter.parse_parameter()?, "\"float innerradius\"" => innerradius = iter.parse_parameter()?,
"\"float phimax\"" => phimax = iter.parse_parameter()?, "\"float phimax\"" => phimax = iter.parse_parameter()?,
"\"float alpha\"" => {
alpha = ShapeAlpha::Value(iter.parse_parameter()?);
}
"\"texture alpha\"" => {
alpha = ShapeAlpha::Texture(iter.parse_parameter()?);
}
_ => { _ => {
bail!("unknown argument {}", q) bail!("unknown argument {}", q)
} }
} }
} }
Ok(Statement::Shape(ShapeType::Disk { Ok(Statement::Shape(
height, ShapeType::Disk {
radius, height,
innerradius, radius,
phimax, innerradius,
})) phimax,
},
alpha,
))
}
"\"plymesh\"" => {
let mut filename = String::new();
let mut displacement = None;
let mut edgelength = 1.0;
let mut alpha = ShapeAlpha::None;
while let Some(q) = iter.next_if(|p| p.starts_with('"')).transpose()? {
match q.as_str() {
"\"string filename\"" => filename = dbg!(iter.parse_parameter()?),
"\"texture displacement\"" => displacement = Some(iter.parse_parameter()?),
"\"float edgelength\"" => edgelength = iter.parse_parameter()?,
"\"float alpha\"" => {
alpha = ShapeAlpha::Value(iter.parse_parameter()?);
}
"\"texture alpha\"" => {
alpha = ShapeAlpha::Texture(iter.parse_parameter()?);
}
_ => {
bail!("unknown argument {}", q)
}
}
}
Ok(Statement::Shape(
ShapeType::PlyMesh {
filename,
displacement,
edgelength,
},
alpha,
))
} }
_ => Err(miette!("Unknown shape {}", shape_type)), _ => Err(miette!("Unknown shape {}", shape_type)),
} }
@ -426,7 +497,6 @@ struct Parser<P> {
impl<P: AsRef<Path> + std::fmt::Debug> Parser<P> { impl<P: AsRef<Path> + std::fmt::Debug> Parser<P> {
fn new(path: P) -> Result<Self> { fn new(path: P) -> Result<Self> {
dbg!(&path);
Ok(Self { Ok(Self {
iter: Lexer::new(path.as_ref())?, iter: Lexer::new(path.as_ref())?,
path, path,
@ -489,6 +559,18 @@ enum ShapeType {
innerradius: f64, innerradius: f64,
phimax: f64, phimax: f64,
}, },
PlyMesh {
filename: String,
displacement: Option<String>,
edgelength: Float,
},
}
#[derive(Debug)]
enum ShapeAlpha {
None,
Value(Float),
Texture(String),
} }
#[derive(Debug)] #[derive(Debug)]
@ -496,6 +578,7 @@ struct Shape {
ctm: AffineTransform, ctm: AffineTransform,
material: usize, material: usize,
obj: ShapeType, obj: ShapeType,
alpha: ShapeAlpha,
} }
#[derive(Debug)] #[derive(Debug)]
@ -545,7 +628,12 @@ fn inner_parse_pbrt(
let mut pbrt = Pbrt::new(); let mut pbrt = Pbrt::new();
while let Some(p) = parser.next(context.last().unwrap()).transpose()? { // parse global settings
loop {
let p = parser
.next(context.last().unwrap())
.ok_or_else(|| miette!(""))??;
// dbg!(&p); // dbg!(&p);
match p { match p {
Statement::AttributeBegin => context.push(context.last().ok_or(miette!(""))?.clone()), Statement::AttributeBegin => context.push(context.last().ok_or(miette!(""))?.clone()),
@ -559,17 +647,39 @@ fn inner_parse_pbrt(
Statement::Transform(affine_transform) => { Statement::Transform(affine_transform) => {
context.last_mut().ok_or(miette!(""))?.ctm = dbg!(affine_transform) context.last_mut().ok_or(miette!(""))?.ctm = dbg!(affine_transform)
} }
Statement::Shape(shape_type) => { Statement::Unknown(s, items) => {
eprintln!("Unknown statement: {s}")
}
Statement::WorldBegin => break,
s => bail!("unexpected statemnet in global settings: {s:?}"),
}
}
while let Some(p) = parser.next(context.last().unwrap()).transpose()? {
match p {
Statement::AttributeBegin => context.push(context.last().ok_or(miette!(""))?.clone()),
Statement::AttributeEnd => {
context.pop();
}
Statement::Include(_) => unreachable!(),
Statement::ConcatTransform(affine_transform) => {
context.last_mut().ok_or(miette!(""))?.ctm *= affine_transform
}
Statement::Transform(affine_transform) => {
context.last_mut().ok_or(miette!(""))?.ctm = dbg!(affine_transform)
}
Statement::Shape(shape_type, shape_alpha) => {
pbrt.scene.shapes.push(Shape { pbrt.scene.shapes.push(Shape {
ctm: context.last().unwrap().ctm, ctm: context.last().unwrap().ctm,
material: 0, material: 0,
obj: shape_type, obj: shape_type,
alpha: shape_alpha,
}); });
} }
Statement::Unknown(s, items) => { Statement::Unknown(s, items) => {
eprintln!("Unknown statement: {s}") eprintln!("Unknown statement: {s}")
} }
Statement::WorldBegin => (), s => bail!("unexpected statemnet in world settings: {s:?}"),
} }
} }