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 {
|
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(),
|
||||||
|
|
|
||||||
|
|
@ -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() {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue