diff --git a/ray-tracing-pbrt-scene/src/lib.rs b/ray-tracing-pbrt-scene/src/lib.rs index ac4b750..8f4b7ce 100644 --- a/ray-tracing-pbrt-scene/src/lib.rs +++ b/ray-tracing-pbrt-scene/src/lib.rs @@ -31,7 +31,7 @@ enum Statement { WorldBegin, Include(String), ConcatTransform(AffineTransform), - Shape(ShapeType), + Shape(ShapeType, ShapeAlpha), Unknown(String, Vec), Transform(AffineTransform), } @@ -56,24 +56,34 @@ fn parse_shape(iter: &mut Tokenizer) -> Result { let zmin = -radius; let zmax = radius; let phimax = 360.0; + let mut alpha = ShapeAlpha::None; while let Some(p) = iter.next_if(|p| p.starts_with('"')).transpose()? { match p.as_str() { "\"float radius\"" => { radius = iter.parse_parameter()?; } + "\"float alpha\"" => { + alpha = ShapeAlpha::Value(iter.parse_parameter()?); + } + "\"texture alpha\"" => { + alpha = ShapeAlpha::Texture(iter.parse_parameter()?); + } _ => { bail!("unknown argument {}", p) } } } - Ok(Statement::Shape(ShapeType::Sphere { - radius, - zmin, - zmax, - phimax, - })) + Ok(Statement::Shape( + ShapeType::Sphere { + radius, + zmin, + zmax, + phimax, + }, + alpha, + )) } "\"trianglemesh\"" => { let mut indices = Vec::new(); @@ -81,6 +91,7 @@ fn parse_shape(iter: &mut Tokenizer) -> Result { let mut n = Vec::new(); let mut s = Vec::new(); let mut uv = Vec::new(); + let mut alpha = ShapeAlpha::None; while let Some(q) = iter.next_if(|p| p.starts_with('"')).transpose()? { match q.as_str() { @@ -99,6 +110,12 @@ fn parse_shape(iter: &mut Tokenizer) -> Result { "\"point2 uv\"" => { 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) } @@ -128,19 +145,23 @@ fn parse_shape(iter: &mut Tokenizer) -> Result { if !uv.is_empty() && uv.len() != p.len() { bail!("Number of uvs not equal to number of positions.") } - Ok(Statement::Shape(ShapeType::TriangleMesh { - indices, - p, - n, - s, - uv, - })) + Ok(Statement::Shape( + ShapeType::TriangleMesh { + indices, + p, + n, + s, + uv, + }, + alpha, + )) } "\"bilinearmesh\"" => { let mut indices = Vec::new(); let mut p = Vec::new(); let mut n = Vec::new(); let mut uv = Vec::new(); + let mut alpha = ShapeAlpha::None; while let Some(q) = iter.next_if(|p| p.starts_with('"')).transpose()? { match q.as_str() { @@ -156,6 +177,12 @@ fn parse_shape(iter: &mut Tokenizer) -> Result { "\"vector N\"" => { 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) } @@ -183,12 +210,10 @@ fn parse_shape(iter: &mut Tokenizer) -> Result { if !uv.is_empty() && uv.len() != p.len() { bail!("Number of uvs not equal to number of positions.") } - Ok(Statement::Shape(ShapeType::BilinearMesh { - indices, - p, - n, - uv, - })) + Ok(Statement::Shape( + ShapeType::BilinearMesh { indices, p, n, uv }, + alpha, + )) } "\"loopsubdiv\"" => { @@ -196,6 +221,7 @@ fn parse_shape(iter: &mut Tokenizer) -> Result { let mut indices = Vec::new(); let mut p = Vec::new(); + let mut alpha = ShapeAlpha::None; while let Some(q) = iter.next_if(|p| p.starts_with('"')).transpose()? { match q.as_str() { @@ -208,6 +234,12 @@ fn parse_shape(iter: &mut Tokenizer) -> Result { "\"integer levels\"" => { levels = iter.parse_parameter()?; } + "\"float alpha\"" => { + alpha = ShapeAlpha::Value(iter.parse_parameter()?); + } + "\"texture alpha\"" => { + alpha = ShapeAlpha::Texture(iter.parse_parameter()?); + } _ => { bail!("unknown argument {}", q) } @@ -222,17 +254,17 @@ fn parse_shape(iter: &mut Tokenizer) -> Result { bail!("p is a required field") } - Ok(Statement::Shape(ShapeType::LoopSubDiv { - levels, - indices, - p, - })) + Ok(Statement::Shape( + ShapeType::LoopSubDiv { levels, indices, p }, + alpha, + )) } "\"disk\"" => { let mut height = 0.0; let mut radius = 1.0; let mut innerradius = 0.0; let mut phimax = 360.0; + let mut alpha = ShapeAlpha::None; while let Some(q) = iter.next_if(|p| p.starts_with('"')).transpose()? { match q.as_str() { @@ -240,18 +272,57 @@ fn parse_shape(iter: &mut Tokenizer) -> Result { "\"float radius\"" => radius = iter.parse_parameter()?, "\"float innerradius\"" => innerradius = 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) } } } - Ok(Statement::Shape(ShapeType::Disk { - height, - radius, - innerradius, - phimax, - })) + Ok(Statement::Shape( + ShapeType::Disk { + height, + radius, + 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)), } @@ -426,7 +497,6 @@ struct Parser

{ impl + std::fmt::Debug> Parser

{ fn new(path: P) -> Result { - dbg!(&path); Ok(Self { iter: Lexer::new(path.as_ref())?, path, @@ -489,6 +559,18 @@ enum ShapeType { innerradius: f64, phimax: f64, }, + PlyMesh { + filename: String, + displacement: Option, + edgelength: Float, + }, +} + +#[derive(Debug)] +enum ShapeAlpha { + None, + Value(Float), + Texture(String), } #[derive(Debug)] @@ -496,6 +578,7 @@ struct Shape { ctm: AffineTransform, material: usize, obj: ShapeType, + alpha: ShapeAlpha, } #[derive(Debug)] @@ -545,7 +628,12 @@ fn inner_parse_pbrt( 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); match p { Statement::AttributeBegin => context.push(context.last().ok_or(miette!(""))?.clone()), @@ -559,17 +647,39 @@ fn inner_parse_pbrt( Statement::Transform(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 { ctm: context.last().unwrap().ctm, material: 0, obj: shape_type, + alpha: shape_alpha, }); } Statement::Unknown(s, items) => { eprintln!("Unknown statement: {s}") } - Statement::WorldBegin => (), + s => bail!("unexpected statemnet in world settings: {s:?}"), } }