Progress on pbrt parser

This commit is contained in:
hal8174 2025-07-31 22:54:53 +02:00
parent e16a916413
commit 16b9c32632
Signed by: hal8174
SSH key fingerprint: SHA256:JwuqS+eVfISfKr+DkDQ6NWAbGd1jFAHkPpCM1yCnlTs
2 changed files with 138 additions and 9 deletions

View file

@ -77,6 +77,27 @@ impl AffineTransform {
} }
} }
pub fn look_at(pos: Pos3, look: Pos3, up: Dir3) -> Self {
let dir = (look - pos).normalize();
let right = Dir3::cross(up.normalize(), dir).normalize();
let new_up = Dir3::cross(dir, right);
let mat = [
[right.x(), new_up.x(), dir.x(), pos.x()],
[right.y(), new_up.y(), dir.y(), pos.y()],
[right.z(), new_up.z(), dir.z(), pos.z()],
];
let inv = Self::invert(mat);
Self { mat, inv }
}
fn invert(mat: [[Float; 4]; 3]) -> [[Float; 3]; 3] {
eprintln!("Matrix inversion not implemented");
[[0.0; 3]; 3]
}
pub fn transform_pos(&self, pos: Pos3) -> Pos3 { pub fn transform_pos(&self, pos: Pos3) -> Pos3 {
Pos3::new( Pos3::new(
self.mat[0][0] * pos.x() self.mat[0][0] * pos.x()
@ -93,6 +114,13 @@ impl AffineTransform {
+ self.mat[2][3], + self.mat[2][3],
) )
} }
pub fn transform_dir(&self, dir: Dir3) -> Dir3 {
Dir3::new(
self.mat[0][0] * dir.x() + self.mat[0][1] * dir.y() + self.mat[0][2] * dir.z(),
self.mat[1][0] * dir.x() + self.mat[1][1] * dir.y() + self.mat[1][2] * dir.z(),
self.mat[2][0] * dir.x() + self.mat[2][1] * dir.y() + self.mat[2][2] * dir.z(),
)
}
pub fn transform_normal(&self, pos: Pos3) -> Pos3 { pub fn transform_normal(&self, pos: Pos3) -> Pos3 {
Pos3::new( Pos3::new(
self.inv[0][0] * pos.x() + self.inv[0][1] * pos.y() + self.inv[0][2] * pos.z(), self.inv[0][0] * pos.x() + self.inv[0][1] * pos.y() + self.inv[0][2] * pos.z(),

View file

@ -7,7 +7,11 @@ use std::{
use miette::{Diagnostic, Error, IntoDiagnostic, Result, bail, miette}; use miette::{Diagnostic, Error, IntoDiagnostic, Result, bail, miette};
use nom::IResult; use nom::IResult;
use ray_tracing_core::math::{Dir3, Pos3}; use ray_tracing_core::{
affine_transform::AffineTransform,
math::{Dir3, Pos3},
prelude::Float,
};
struct Tokenizer<I: Iterator<Item = Result<char>>> { struct Tokenizer<I: Iterator<Item = Result<char>>> {
input_iterator: Peekable<I>, input_iterator: Peekable<I>,
@ -109,10 +113,10 @@ impl<I: Iterator<Item = Result<char>>> Lexer<I> {
#[derive(Debug)] #[derive(Debug)]
enum Statement { enum Statement {
AttributeStart, AttributeBegin,
AttributeEnd, AttributeEnd,
Include(String), Include(String),
LookAt { eye: Pos3, look_at: Pos3, up: Dir3 }, ConcatTransform(AffineTransform),
Unknown(String, Vec<String>), Unknown(String, Vec<String>),
} }
@ -160,16 +164,27 @@ fn parse_look_at(iter: &mut impl Iterator<Item = Result<String>>) -> Result<Stat
.into_diagnostic()?, .into_diagnostic()?,
); );
Ok(Statement::LookAt { eye, look_at, up }) Ok(Statement::ConcatTransform(AffineTransform::look_at(
eye, look_at, up,
)))
} }
impl<I: Iterator<Item = Result<char>>> Iterator for Lexer<I> { fn parse_shape<I: Iterator<Item = Result<char>>>(
type Item = Result<Statement>; iter: &mut Peekable<Tokenizer<I>>,
) -> std::result::Result<Statement, Error> {
let shape_type = iter.next().ok_or(miette!(""))??;
fn next(&mut self) -> Option<Self::Item> { match shape_type.as_str() {
"sphere" => {}
_ => Err(miette!("")),
}
}
impl<I: Iterator<Item = Result<char>>> Lexer<I> {
fn next(&mut self, ctm: AffineTransform) -> Option<Result<Statement>> {
match self.input.next() { match self.input.next() {
Some(Ok(s)) => match s.as_str() { Some(Ok(s)) => match s.as_str() {
"AttributeStart" => Some(Ok(Statement::AttributeStart)), "AttributeBegin" => Some(Ok(Statement::AttributeBegin)),
"AttributeEnd" => Some(Ok(Statement::AttributeEnd)), "AttributeEnd" => Some(Ok(Statement::AttributeEnd)),
"Include" => { "Include" => {
let s = self let s = self
@ -183,6 +198,7 @@ impl<I: Iterator<Item = Result<char>>> Iterator for Lexer<I> {
Some(Ok(Statement::Include(s))) Some(Ok(Statement::Include(s)))
} }
"LookAt" => Some(parse_look_at(&mut self.input)), "LookAt" => Some(parse_look_at(&mut self.input)),
"Identity" => Some(Ok(Statement::ConcatTransform(AffineTransform::identity()))),
_ => { _ => {
if s.chars().any(|c| !c.is_ascii_alphabetic()) { if s.chars().any(|c| !c.is_ascii_alphabetic()) {
Some(Err(miette!("malformed identifier"))) Some(Err(miette!("malformed identifier")))
@ -202,6 +218,7 @@ impl<I: Iterator<Item = Result<char>>> Iterator for Lexer<I> {
Some(Ok(Statement::Unknown(s, v))) Some(Ok(Statement::Unknown(s, v)))
} }
} }
"Shape" => Some(parse_shape(&mut self.input)),
}, },
Some(Err(e)) => Some(Err(e)), Some(Err(e)) => Some(Err(e)),
None => None, None => None,
@ -234,6 +251,7 @@ struct Parser<P> {
path: P, path: P,
inner: Option<Box<Parser<PathBuf>>>, inner: Option<Box<Parser<PathBuf>>>,
iter: Lexer<BytesToChar<Bytes<BufReader<File>>>>, iter: Lexer<BytesToChar<Bytes<BufReader<File>>>>,
ctm: AffineTransform,
} }
impl<P: AsRef<Path> + std::fmt::Debug> Parser<P> { impl<P: AsRef<Path> + std::fmt::Debug> Parser<P> {
@ -242,12 +260,21 @@ impl<P: AsRef<Path> + std::fmt::Debug> Parser<P> {
let bufreader = BufReader::new(std::fs::File::open(&path).into_diagnostic()?); let bufreader = BufReader::new(std::fs::File::open(&path).into_diagnostic()?);
Ok(Self { Ok(Self {
path, path,
ctm: AffineTransform::identity(),
inner: None, inner: None,
iter: Lexer::new(BytesToChar { iter: Lexer::new(BytesToChar {
iter: bufreader.bytes(), iter: bufreader.bytes(),
}), }),
}) })
} }
fn apply_transform(&mut self, transform: AffineTransform) {
self.ctm *= transform;
}
fn set_transform(&mut self, transform: AffineTransform) {
self.ctm = transform;
}
} }
impl<P: AsRef<Path>> Iterator for Parser<P> { impl<P: AsRef<Path>> Iterator for Parser<P> {
@ -261,7 +288,7 @@ impl<P: AsRef<Path>> Iterator for Parser<P> {
self.inner = None; self.inner = None;
} }
match self.iter.next() { match self.iter.next(self.ctm) {
Some(Ok(Statement::Include(s))) => { Some(Ok(Statement::Include(s))) => {
let path = self.path.as_ref().parent().unwrap().join(s); let path = self.path.as_ref().parent().unwrap().join(s);
self.inner = Some(Box::new(Parser::new(path).unwrap())); self.inner = Some(Box::new(Parser::new(path).unwrap()));
@ -274,6 +301,80 @@ impl<P: AsRef<Path>> Iterator for Parser<P> {
} }
} }
enum ShapeType {
Sphere {
radius: Float,
zmin: Float,
zmax: Float,
phimax: Float,
},
}
struct Shape {
ctm: AffineTransform,
material: usize,
obj: ShapeType,
}
struct Pbrt {
settings: PbrtWorldSettings,
scene: PbrtScene,
}
impl Pbrt {
fn new() -> Self {
Self {
settings: todo!(),
scene: todo!(),
}
}
}
struct PbrtWorldSettings {}
struct PbrtScene {
shapes: Vec<Shape>,
}
#[derive(Clone)]
struct PbrtContext {
ctm: AffineTransform,
}
impl PbrtContext {
fn new() -> Self {
Self {
ctm: AffineTransform::identity(),
}
}
}
fn inner_parse_pbrt(
path: impl AsRef<Path> + std::fmt::Debug,
context: Option<PbrtContext>,
) -> Result<Pbrt> {
let mut context = vec![context.unwrap_or(PbrtContext::new())];
let mut parser = Parser::new(path)?;
let mut pbrt = Pbrt::new();
while let Some(p) = parser.next().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::Unknown(_, items) => todo!(),
}
}
todo!()
}
pub fn parse_pbrt_v4(path: impl AsRef<Path> + std::fmt::Debug) -> Result<()> { pub fn parse_pbrt_v4(path: impl AsRef<Path> + std::fmt::Debug) -> Result<()> {
let mut tokens = 0; let mut tokens = 0;
for token in Parser::new(path).unwrap() { for token in Parser::new(path).unwrap() {