diff --git a/ray-tracing-pbrt-scene/src/lib.rs b/ray-tracing-pbrt-scene/src/lib.rs index 9c95de1..b64928a 100644 --- a/ray-tracing-pbrt-scene/src/lib.rs +++ b/ray-tracing-pbrt-scene/src/lib.rs @@ -9,13 +9,17 @@ use ray_tracing_core::{ use std::{ collections::HashMap, path::{Path, PathBuf}, + sync::Arc, }; +use texture::PbrtTexture; use thiserror::Error; #[macro_use] mod tokenizer; mod error; + +mod texture; struct Lexer { input: Tokenizer, } @@ -65,6 +69,7 @@ enum Statement { Shape(ShapeType, ShapeAlpha), Unknown(String, Vec), Transform(AffineTransform), + Texture(String, Arc), } fn parse_look_at(iter: &mut Tokenizer) -> Result { @@ -363,7 +368,10 @@ fn parse_camera(tokenizer: &mut Tokenizer) -> Result { } impl Lexer { - fn next(&mut self) -> Option> { + fn next( + &mut self, + textures: &HashMap>, + ) -> Option> { match self.input.next() { Some(Ok(s)) => match s.as_str() { "AttributeBegin" => Some(Ok(Statement::AttributeBegin)), @@ -387,6 +395,10 @@ impl Lexer { "Shape" => Some(parse_shape(&mut self.input)), "Rotate" => Some(parse_rotate(&mut self.input)), "Transform" => Some(parse_transform(&mut self.input).map(Statement::Transform)), + "Texture" => Some( + texture::parse_texture(&mut self.input) + .map(|(name, texture)| Statement::Texture(name, texture)), + ), "ConcatTransform" => { Some(parse_transform(&mut self.input).map(Statement::ConcatTransform)) } @@ -550,20 +562,23 @@ impl + std::fmt::Debug> Parser

{ } impl> Parser

{ - fn next(&mut self) -> Option> { + fn next( + &mut self, + textures: &HashMap>, + ) -> Option> { if let Some(iter) = &mut self.inner { - if let Some(statement) = iter.next() { + if let Some(statement) = iter.next(textures) { return Some(statement); } self.inner = None; } - match self.iter.next() { + match self.iter.next(textures) { Some(Ok(Statement::Include(s))) => { let path = self.path.as_ref().parent().unwrap().join(s); self.inner = Some(Box::new(Parser::new(path).unwrap())); - self.next() + self.next(textures) } Some(s) => Some(s), None => None, @@ -653,7 +668,7 @@ struct PbrtScene { fn inner_parse_pbrt(path: impl AsRef + std::fmt::Debug) -> Result { // unwrap on context.last() ok because context is never empty - let mut context = vec![AffineTransform::identity()]; + let mut context_ctm = vec![AffineTransform::identity()]; let mut parser = Parser::new(path)?; @@ -663,23 +678,25 @@ fn inner_parse_pbrt(path: impl AsRef + std::fmt::Debug) -> Result { let mut named_transforms = HashMap::new(); + let mut textures = HashMap::new(); + loop { - let p = parser.next().ok_or_else(|| miette!(""))??; + let p = parser.next(&textures).ok_or_else(|| miette!(""))??; // dbg!(&p); match p { - Statement::AttributeBegin => context.push(*context.last().unwrap()), + Statement::AttributeBegin => context_ctm.push(*context_ctm.last().unwrap()), Statement::AttributeEnd => { - context.pop(); - if context.is_empty() { + context_ctm.pop(); + if context_ctm.is_empty() { return Err(miette!("Attribute end does not match.")); } } Statement::Include(_) => unreachable!(), Statement::ConcatTransform(affine_transform) => { - *context.last_mut().unwrap() *= affine_transform + *context_ctm.last_mut().unwrap() *= affine_transform } Statement::Transform(affine_transform) => { - *context.last_mut().unwrap() = affine_transform + *context_ctm.last_mut().unwrap() = affine_transform } Statement::Unknown(s, _items) => { eprintln!("Unknown statement: {s}") @@ -688,14 +705,14 @@ fn inner_parse_pbrt(path: impl AsRef + std::fmt::Debug) -> Result { if camera.is_some() { return Err(miette!("The camera can only be set once.")); } - camera = Some((c, *context.last().unwrap())); - named_transforms.insert(String::from("\"camera\""), *context.last().unwrap()); + camera = Some((c, *context_ctm.last().unwrap())); + named_transforms.insert(String::from("\"camera\""), *context_ctm.last().unwrap()); } Statement::CoordinateSystem(s) => { - named_transforms.insert(s, *context.last().unwrap()); + named_transforms.insert(s, *context_ctm.last().unwrap()); } Statement::CoordSysTransform(s) => { - *context.last_mut().unwrap() = *named_transforms + *context_ctm.last_mut().unwrap() = *named_transforms .get(&s) .ok_or_else(|| miette!("unknown transform"))?; } @@ -708,34 +725,36 @@ fn inner_parse_pbrt(path: impl AsRef + std::fmt::Debug) -> Result { let mut pbrt = Pbrt::new(PbrtWorldSettings { camera, camera_ctm }); - let mut context = vec![AffineTransform::identity()]; + let mut context_ctm = vec![AffineTransform::identity()]; - while let Some(p) = parser.next().transpose()? { + // let mut context_material = vec![]; + + while let Some(p) = parser.next(&textures).transpose()? { match p { - Statement::AttributeBegin => context.push(*context.last().unwrap()), + Statement::AttributeBegin => context_ctm.push(*context_ctm.last().unwrap()), Statement::AttributeEnd => { - context.pop(); + context_ctm.pop(); } Statement::Include(_) => unreachable!(), Statement::ConcatTransform(affine_transform) => { - *context.last_mut().unwrap() *= affine_transform + *context_ctm.last_mut().unwrap() *= affine_transform } Statement::Transform(affine_transform) => { - *context.last_mut().unwrap() = affine_transform + *context_ctm.last_mut().unwrap() = affine_transform } Statement::Shape(shape_type, shape_alpha) => { pbrt.scene.shapes.push(Shape { - ctm: *context.last().unwrap(), + ctm: *context_ctm.last().unwrap(), material: 0, obj: shape_type, alpha: shape_alpha, }); } Statement::CoordinateSystem(s) => { - named_transforms.insert(s, *context.last().unwrap()); + named_transforms.insert(s, *context_ctm.last().unwrap()); } Statement::CoordSysTransform(s) => { - *context.last_mut().unwrap() = *named_transforms + *context_ctm.last_mut().unwrap() = *named_transforms .get(&s) .ok_or_else(|| miette!("unknown transform"))?; } @@ -746,8 +765,6 @@ fn inner_parse_pbrt(path: impl AsRef + std::fmt::Debug) -> Result { } } - dbg!(named_transforms); - Ok(pbrt) } diff --git a/ray-tracing-pbrt-scene/src/texture.rs b/ray-tracing-pbrt-scene/src/texture.rs new file mode 100644 index 0000000..937e45c --- /dev/null +++ b/ray-tracing-pbrt-scene/src/texture.rs @@ -0,0 +1,120 @@ +use miette::{Result, miette}; +use ray_tracing_core::{color::Color, prelude::Float}; +use std::sync::Arc; + +use crate::tokenizer::Tokenizer; + +pub trait PbrtTexture: std::fmt::Debug { + fn get_2d_float_texture(self: Arc) -> Result>; + fn get_2d_spectrum_texture(self: Arc) -> Result>; +} + +pub trait Pbrt_2d_float_texture: std::fmt::Debug { + fn get(&self, u: Float, v: Float) -> Float; +} + +pub trait Pbrt_2d_spectrum_texture: std::fmt::Debug { + fn get(&self, u: Float, v: Float) -> Color; +} + +#[derive(Debug)] +enum TextureMapping { + UV, + Spherical, +} + +impl TextureMapping { + fn new(x: String) -> Result { + match x.as_str() { + "\"uv\"" => Ok(TextureMapping::UV), + "\"spherical\"" => Ok(TextureMapping::Spherical), + _ => Err(miette!("Error")), + } + } +} + +pub fn parse_texture(input: &mut Tokenizer) -> Result<(String, Arc)> { + let texture_name: String = input.parse_next()?; + let texture_type: String = input.parse_next()?; + + let texture_class: String = input.parse_next()?; + + match texture_class.as_str() { + "\"checkerboard\"" => { + let t = parse_dict!(input => + mapping, TextureMapping, TextureMapping::UV; + uscale, Float, 1.0; + vscale, Float, 1.0; + udelta, Float, 0.0; + vdelta, Float, 0.0; + dimension, u8, 2 + => + mapping, "\"mapping\"", TextureMapping::new(input.parse_parameter()?)?; + uscale, "\"uscale\"", input.parse_parameter()?; + vscale, "\"vscale\"", input.parse_parameter()?; + udelta, "\"udelta\"", input.parse_parameter()?; + vdelta, "\"vdelta\"", input.parse_parameter()?; + dimension, "\"dimension\"", input.parse_parameter()? + + ); + + dbg!(t); + todo!() + } + "\"checkerboard\"" => { + let t = parse_dict!(input => + mapping, TextureMapping, TextureMapping::UV; + uscale, Float, 1.0; + vscale, Float, 1.0; + udelta, Float, 0.0; + vdelta, Float, 0.0 + => + mapping, "\"mapping\"", TextureMapping::new(input.parse_parameter()?)?; + uscale, "\"uscale\"", input.parse_parameter()?; + vscale, "\"vscale\"", input.parse_parameter()?; + udelta, "\"udelta\"", input.parse_parameter()?; + vdelta, "\"vdelta\"", input.parse_parameter()? + + ); + + todo!() + } + _ => Err(miette!("unknown error")), + } +} + +#[derive(Debug)] +enum FloatTexture2d { + Value(Float), + Texture { + float: Option>, + spectrum: Option>, + }, +} + +#[derive(Debug)] +struct TextureD2 { + inner: T, + uscale: Float, + vscale: Float, + udelta: Float, + vdelta: Float, + mapping: TextureMapping, +} + +impl PbrtTexture for TextureD2 { + fn get_2d_float_texture(self: Arc) -> Result> { + todo!() + } + + fn get_2d_spectrum_texture(self: Arc) -> Result> { + todo!() + } +} + +#[derive(Debug)] +struct CheckerboardTexture { + dimension: u8, + tex1: FloatTexture2d, + tex2: FloatTexture2d, +}