Parsing more stuff.
This commit is contained in:
parent
96a24fcc28
commit
8fcf815dbf
3 changed files with 253 additions and 17 deletions
|
|
@ -10,7 +10,9 @@ struct Args {
|
|||
fn main() -> Result<(), miette::Error> {
|
||||
let args = Args::parse();
|
||||
|
||||
dbg!(parse_pbrt_v4(args.filename)?);
|
||||
let t = parse_pbrt_v4(args.filename)?;
|
||||
|
||||
// dbg!(t);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,6 +119,7 @@ enum Statement {
|
|||
ConcatTransform(AffineTransform),
|
||||
Shape(ShapeType),
|
||||
Unknown(String, Vec<String>),
|
||||
Transform(AffineTransform),
|
||||
}
|
||||
|
||||
fn parse_look_at(iter: &mut impl Iterator<Item = Result<String>>) -> Result<Statement> {
|
||||
|
|
@ -165,9 +166,10 @@ fn parse_look_at(iter: &mut impl Iterator<Item = Result<String>>) -> Result<Stat
|
|||
.into_diagnostic()?,
|
||||
);
|
||||
|
||||
Ok(Statement::ConcatTransform(AffineTransform::look_at(
|
||||
eye, look_at, up,
|
||||
)))
|
||||
Ok(Statement::ConcatTransform(
|
||||
AffineTransform::look_at(eye, look_at, up)
|
||||
.ok_or(miette!("Unable to calculate inverse of matrix"))?,
|
||||
))
|
||||
}
|
||||
|
||||
fn parse_parameter<I, T>(iter: &mut Peekable<Tokenizer<I>>) -> Result<T>
|
||||
|
|
@ -383,7 +385,7 @@ fn parse_shape<I: Iterator<Item = Result<char>>>(
|
|||
"\"normal N\"" => {
|
||||
parse_list_3(iter, &mut n, Dir3::new)?;
|
||||
}
|
||||
"\"vector N\"" => {
|
||||
"\"vector S\"" => {
|
||||
parse_list_3(iter, &mut s, Dir3::new)?;
|
||||
}
|
||||
"\"point2 uv\"" => {
|
||||
|
|
@ -427,8 +429,9 @@ fn parse_shape<I: Iterator<Item = Result<char>>>(
|
|||
}))
|
||||
}
|
||||
"\"bilinearmesh\"" => {
|
||||
let mut indices = Vec::new();
|
||||
let mut p = Vec::new();
|
||||
|
||||
let mut n = Vec::new();
|
||||
let mut uv = Vec::new();
|
||||
|
||||
while let Some(q) = iter
|
||||
|
|
@ -436,21 +439,50 @@ fn parse_shape<I: Iterator<Item = Result<char>>>(
|
|||
.transpose()?
|
||||
{
|
||||
match q.as_str() {
|
||||
"\"integer indices\"" => {
|
||||
parse_list(iter, &mut indices)?;
|
||||
}
|
||||
"\"point3 P\"" => {
|
||||
parse_list_3(iter, &mut p, Pos3::new)?;
|
||||
}
|
||||
"\"point2 uv\"" => {
|
||||
parse_list_2(iter, &mut uv, |u, v| [u, v])?;
|
||||
}
|
||||
"\"vector N\"" => {
|
||||
parse_list_3(iter, &mut n, Dir3::new)?;
|
||||
}
|
||||
_ => {
|
||||
bail!("unknown argument {}", q)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if p.len() < 4 {
|
||||
bail!("At least 3 points required.")
|
||||
}
|
||||
if indices.is_empty() && p.len() != 4 {
|
||||
bail!("Indices required for trianglemesh with more than 3 points.")
|
||||
}
|
||||
|
||||
if indices.len() % 4 != 0 {
|
||||
bail!(
|
||||
"number of indices must be divisible by 4. num indices: {}",
|
||||
indices.len()
|
||||
)
|
||||
}
|
||||
|
||||
if !n.is_empty() && n.len() != p.len() {
|
||||
bail!("Number of normals not equal to number of positions.")
|
||||
}
|
||||
|
||||
if !uv.is_empty() && uv.len() != p.len() {
|
||||
bail!("Number of uvs not equal to number of positions.")
|
||||
}
|
||||
Ok(Statement::Shape(ShapeType::BilinearMesh {
|
||||
p: [p[0], p[1], p[2], p[3]],
|
||||
uv: [uv[0], uv[1], uv[2], uv[3]],
|
||||
indices,
|
||||
p,
|
||||
n,
|
||||
uv,
|
||||
}))
|
||||
}
|
||||
|
||||
|
|
@ -494,6 +526,34 @@ fn parse_shape<I: Iterator<Item = Result<char>>>(
|
|||
p,
|
||||
}))
|
||||
}
|
||||
"\"disk\"" => {
|
||||
let mut height = 0.0;
|
||||
let mut radius = 1.0;
|
||||
let mut innerradius = 0.0;
|
||||
let mut phimax = 360.0;
|
||||
|
||||
while let Some(q) = iter
|
||||
.next_if(|p| p.as_ref().is_ok_and(|p| p.starts_with('"')))
|
||||
.transpose()?
|
||||
{
|
||||
match q.as_str() {
|
||||
"\"float height\"" => height = parse_parameter(iter)?,
|
||||
"\"float radius\"" => radius = parse_parameter(iter)?,
|
||||
"\"float innerradius\"" => innerradius = parse_parameter(iter)?,
|
||||
"\"float phimax\"" => phimax = parse_parameter(iter)?,
|
||||
_ => {
|
||||
bail!("unknown argument {}", q)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Statement::Shape(ShapeType::Disk {
|
||||
height,
|
||||
radius,
|
||||
innerradius,
|
||||
phimax,
|
||||
}))
|
||||
}
|
||||
_ => Err(miette!("Unknown shape {}", shape_type)),
|
||||
}
|
||||
}
|
||||
|
|
@ -517,7 +577,16 @@ impl<I: Iterator<Item = Result<char>>> Lexer<I> {
|
|||
}
|
||||
"LookAt" => Some(parse_look_at(&mut self.input)),
|
||||
"Identity" => Some(Ok(Statement::ConcatTransform(AffineTransform::identity()))),
|
||||
"Translate" => Some(parse_translate(&mut self.input)),
|
||||
"Scale" => Some(parse_scale(&mut self.input)),
|
||||
"Shape" => Some(parse_shape(&mut self.input)),
|
||||
"Rotate" => Some(parse_rotate(&mut self.input)),
|
||||
"Transform" => {
|
||||
Some(parse_transform(&mut self.input).map(|a| Statement::Transform(a)))
|
||||
}
|
||||
"ConcatTransform" => {
|
||||
Some(parse_transform(&mut self.input).map(|a| Statement::ConcatTransform(a)))
|
||||
}
|
||||
_ => {
|
||||
if s.chars().any(|c| !c.is_ascii_alphabetic()) {
|
||||
Some(Err(miette!("malformed identifier")))
|
||||
|
|
@ -544,6 +613,114 @@ impl<I: Iterator<Item = Result<char>>> Lexer<I> {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_transform<I: Iterator<Item = Result<char>>>(
|
||||
input: &mut Peekable<Tokenizer<I>>,
|
||||
) -> Result<AffineTransform> {
|
||||
if !input
|
||||
.next()
|
||||
.is_none_or(|p| p.is_ok_and(|p| p.as_str() == "["))
|
||||
{
|
||||
bail!("expected list.")
|
||||
}
|
||||
|
||||
let mut v = [0.0; 16];
|
||||
|
||||
for i in 0..16 {
|
||||
v[i] = input
|
||||
.next()
|
||||
.ok_or(miette!("value expected"))??
|
||||
.parse::<Float>()
|
||||
.into_diagnostic()?;
|
||||
}
|
||||
|
||||
if !input
|
||||
.next()
|
||||
.is_none_or(|p| p.is_ok_and(|p| p.as_str() == "]"))
|
||||
{
|
||||
bail!("expected list end.")
|
||||
}
|
||||
|
||||
if v[3] != 0.0 || v[7] != 0.0 || v[11] != 0.0 || v[15] != 1.0 {
|
||||
bail!("invalid transform entry")
|
||||
}
|
||||
|
||||
Ok(AffineTransform::new([
|
||||
[v[0], v[4], v[8], v[12]],
|
||||
[v[1], v[5], v[9], v[13]],
|
||||
[v[2], v[6], v[10], v[14]],
|
||||
])
|
||||
.ok_or(miette!("Unable to invert transformation"))?)
|
||||
}
|
||||
|
||||
fn parse_translate<I: Iterator<Item = Result<char>>>(
|
||||
iter: &mut Peekable<Tokenizer<I>>,
|
||||
) -> Result<Statement> {
|
||||
let pos = Pos3::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()?,
|
||||
);
|
||||
|
||||
Ok(Statement::ConcatTransform(AffineTransform::translation(
|
||||
pos,
|
||||
)))
|
||||
}
|
||||
|
||||
fn parse_scale<I: Iterator<Item = Result<char>>>(
|
||||
iter: &mut Peekable<Tokenizer<I>>,
|
||||
) -> Result<Statement> {
|
||||
Ok(Statement::ConcatTransform(AffineTransform::scale(
|
||||
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()?,
|
||||
)))
|
||||
}
|
||||
|
||||
fn parse_rotate<I: Iterator<Item = Result<char>>>(
|
||||
iter: &mut Peekable<Tokenizer<I>>,
|
||||
) -> Result<Statement> {
|
||||
let angle = iter
|
||||
.next()
|
||||
.ok_or(miette!("missing argument"))??
|
||||
.parse()
|
||||
.into_diagnostic()?;
|
||||
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()?,
|
||||
);
|
||||
|
||||
Ok(Statement::ConcatTransform(AffineTransform::rotation(
|
||||
angle, dir,
|
||||
)))
|
||||
}
|
||||
struct BytesToChar<I> {
|
||||
iter: I,
|
||||
}
|
||||
|
|
@ -623,14 +800,22 @@ enum ShapeType {
|
|||
uv: Vec<[Float; 2]>,
|
||||
},
|
||||
BilinearMesh {
|
||||
p: [Pos3; 4],
|
||||
uv: [[Float; 2]; 4],
|
||||
indices: Vec<usize>,
|
||||
p: Vec<Pos3>,
|
||||
n: Vec<Dir3>,
|
||||
uv: Vec<[Float; 2]>,
|
||||
},
|
||||
LoopSubDiv {
|
||||
levels: u32,
|
||||
indices: Vec<usize>,
|
||||
p: Vec<Pos3>,
|
||||
},
|
||||
Disk {
|
||||
height: f64,
|
||||
radius: f64,
|
||||
innerradius: f64,
|
||||
phimax: f64,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
@ -698,6 +883,9 @@ fn inner_parse_pbrt(
|
|||
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) => {
|
||||
pbrt.scene.shapes.push(Shape {
|
||||
ctm: context.last().unwrap().ctm,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue