Progress on pbrt parser
This commit is contained in:
parent
e16a916413
commit
16b9c32632
2 changed files with 138 additions and 9 deletions
|
|
@ -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 {
|
||||
Pos3::new(
|
||||
self.mat[0][0] * pos.x()
|
||||
|
|
@ -93,6 +114,13 @@ impl AffineTransform {
|
|||
+ 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 {
|
||||
Pos3::new(
|
||||
self.inv[0][0] * pos.x() + self.inv[0][1] * pos.y() + self.inv[0][2] * pos.z(),
|
||||
|
|
|
|||
|
|
@ -7,7 +7,11 @@ use std::{
|
|||
|
||||
use miette::{Diagnostic, Error, IntoDiagnostic, Result, bail, miette};
|
||||
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>>> {
|
||||
input_iterator: Peekable<I>,
|
||||
|
|
@ -109,10 +113,10 @@ impl<I: Iterator<Item = Result<char>>> Lexer<I> {
|
|||
|
||||
#[derive(Debug)]
|
||||
enum Statement {
|
||||
AttributeStart,
|
||||
AttributeBegin,
|
||||
AttributeEnd,
|
||||
Include(String),
|
||||
LookAt { eye: Pos3, look_at: Pos3, up: Dir3 },
|
||||
ConcatTransform(AffineTransform),
|
||||
Unknown(String, Vec<String>),
|
||||
}
|
||||
|
||||
|
|
@ -160,16 +164,27 @@ fn parse_look_at(iter: &mut impl Iterator<Item = Result<String>>) -> Result<Stat
|
|||
.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> {
|
||||
type Item = Result<Statement>;
|
||||
fn parse_shape<I: Iterator<Item = Result<char>>>(
|
||||
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() {
|
||||
Some(Ok(s)) => match s.as_str() {
|
||||
"AttributeStart" => Some(Ok(Statement::AttributeStart)),
|
||||
"AttributeBegin" => Some(Ok(Statement::AttributeBegin)),
|
||||
"AttributeEnd" => Some(Ok(Statement::AttributeEnd)),
|
||||
"Include" => {
|
||||
let s = self
|
||||
|
|
@ -183,6 +198,7 @@ impl<I: Iterator<Item = Result<char>>> Iterator for Lexer<I> {
|
|||
Some(Ok(Statement::Include(s)))
|
||||
}
|
||||
"LookAt" => Some(parse_look_at(&mut self.input)),
|
||||
"Identity" => Some(Ok(Statement::ConcatTransform(AffineTransform::identity()))),
|
||||
_ => {
|
||||
if s.chars().any(|c| !c.is_ascii_alphabetic()) {
|
||||
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)))
|
||||
}
|
||||
}
|
||||
"Shape" => Some(parse_shape(&mut self.input)),
|
||||
},
|
||||
Some(Err(e)) => Some(Err(e)),
|
||||
None => None,
|
||||
|
|
@ -234,6 +251,7 @@ struct Parser<P> {
|
|||
path: P,
|
||||
inner: Option<Box<Parser<PathBuf>>>,
|
||||
iter: Lexer<BytesToChar<Bytes<BufReader<File>>>>,
|
||||
ctm: AffineTransform,
|
||||
}
|
||||
|
||||
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()?);
|
||||
Ok(Self {
|
||||
path,
|
||||
ctm: AffineTransform::identity(),
|
||||
inner: None,
|
||||
iter: Lexer::new(BytesToChar {
|
||||
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> {
|
||||
|
|
@ -261,7 +288,7 @@ impl<P: AsRef<Path>> Iterator for Parser<P> {
|
|||
self.inner = None;
|
||||
}
|
||||
|
||||
match self.iter.next() {
|
||||
match self.iter.next(self.ctm) {
|
||||
Some(Ok(Statement::Include(s))) => {
|
||||
let path = self.path.as_ref().parent().unwrap().join(s);
|
||||
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<()> {
|
||||
let mut tokens = 0;
|
||||
for token in Parser::new(path).unwrap() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue