First pbrt textures approach
This commit is contained in:
parent
b4d34aa6ca
commit
1196cb7758
2 changed files with 164 additions and 27 deletions
|
|
@ -9,13 +9,17 @@ use ray_tracing_core::{
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
|
sync::Arc,
|
||||||
};
|
};
|
||||||
|
use texture::PbrtTexture;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod tokenizer;
|
mod tokenizer;
|
||||||
|
|
||||||
mod error;
|
mod error;
|
||||||
|
|
||||||
|
mod texture;
|
||||||
struct Lexer {
|
struct Lexer {
|
||||||
input: Tokenizer,
|
input: Tokenizer,
|
||||||
}
|
}
|
||||||
|
|
@ -65,6 +69,7 @@ enum Statement {
|
||||||
Shape(ShapeType, ShapeAlpha),
|
Shape(ShapeType, ShapeAlpha),
|
||||||
Unknown(String, Vec<String>),
|
Unknown(String, Vec<String>),
|
||||||
Transform(AffineTransform),
|
Transform(AffineTransform),
|
||||||
|
Texture(String, Arc<dyn PbrtTexture>),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_look_at(iter: &mut Tokenizer) -> Result<Statement> {
|
fn parse_look_at(iter: &mut Tokenizer) -> Result<Statement> {
|
||||||
|
|
@ -363,7 +368,10 @@ fn parse_camera(tokenizer: &mut Tokenizer) -> Result<Statement> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Lexer {
|
impl Lexer {
|
||||||
fn next(&mut self) -> Option<Result<Statement>> {
|
fn next(
|
||||||
|
&mut self,
|
||||||
|
textures: &HashMap<String, Arc<dyn PbrtTexture>>,
|
||||||
|
) -> 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() {
|
||||||
"AttributeBegin" => Some(Ok(Statement::AttributeBegin)),
|
"AttributeBegin" => Some(Ok(Statement::AttributeBegin)),
|
||||||
|
|
@ -387,6 +395,10 @@ impl Lexer {
|
||||||
"Shape" => Some(parse_shape(&mut self.input)),
|
"Shape" => Some(parse_shape(&mut self.input)),
|
||||||
"Rotate" => Some(parse_rotate(&mut self.input)),
|
"Rotate" => Some(parse_rotate(&mut self.input)),
|
||||||
"Transform" => Some(parse_transform(&mut self.input).map(Statement::Transform)),
|
"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" => {
|
"ConcatTransform" => {
|
||||||
Some(parse_transform(&mut self.input).map(Statement::ConcatTransform))
|
Some(parse_transform(&mut self.input).map(Statement::ConcatTransform))
|
||||||
}
|
}
|
||||||
|
|
@ -550,20 +562,23 @@ impl<P: AsRef<Path> + std::fmt::Debug> Parser<P> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P: AsRef<Path>> Parser<P> {
|
impl<P: AsRef<Path>> Parser<P> {
|
||||||
fn next(&mut self) -> Option<Result<Statement>> {
|
fn next(
|
||||||
|
&mut self,
|
||||||
|
textures: &HashMap<String, Arc<dyn PbrtTexture>>,
|
||||||
|
) -> Option<Result<Statement>> {
|
||||||
if let Some(iter) = &mut self.inner {
|
if let Some(iter) = &mut self.inner {
|
||||||
if let Some(statement) = iter.next() {
|
if let Some(statement) = iter.next(textures) {
|
||||||
return Some(statement);
|
return Some(statement);
|
||||||
}
|
}
|
||||||
self.inner = None;
|
self.inner = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.iter.next() {
|
match self.iter.next(textures) {
|
||||||
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()));
|
||||||
|
|
||||||
self.next()
|
self.next(textures)
|
||||||
}
|
}
|
||||||
Some(s) => Some(s),
|
Some(s) => Some(s),
|
||||||
None => None,
|
None => None,
|
||||||
|
|
@ -653,7 +668,7 @@ struct PbrtScene {
|
||||||
|
|
||||||
fn inner_parse_pbrt(path: impl AsRef<Path> + std::fmt::Debug) -> Result<Pbrt> {
|
fn inner_parse_pbrt(path: impl AsRef<Path> + std::fmt::Debug) -> Result<Pbrt> {
|
||||||
// unwrap on context.last() ok because context is never empty
|
// 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)?;
|
let mut parser = Parser::new(path)?;
|
||||||
|
|
||||||
|
|
@ -663,23 +678,25 @@ fn inner_parse_pbrt(path: impl AsRef<Path> + std::fmt::Debug) -> Result<Pbrt> {
|
||||||
|
|
||||||
let mut named_transforms = HashMap::new();
|
let mut named_transforms = HashMap::new();
|
||||||
|
|
||||||
|
let mut textures = HashMap::new();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let p = parser.next().ok_or_else(|| miette!(""))??;
|
let p = parser.next(&textures).ok_or_else(|| miette!(""))??;
|
||||||
// dbg!(&p);
|
// dbg!(&p);
|
||||||
match p {
|
match p {
|
||||||
Statement::AttributeBegin => context.push(*context.last().unwrap()),
|
Statement::AttributeBegin => context_ctm.push(*context_ctm.last().unwrap()),
|
||||||
Statement::AttributeEnd => {
|
Statement::AttributeEnd => {
|
||||||
context.pop();
|
context_ctm.pop();
|
||||||
if context.is_empty() {
|
if context_ctm.is_empty() {
|
||||||
return Err(miette!("Attribute end does not match."));
|
return Err(miette!("Attribute end does not match."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Statement::Include(_) => unreachable!(),
|
Statement::Include(_) => unreachable!(),
|
||||||
Statement::ConcatTransform(affine_transform) => {
|
Statement::ConcatTransform(affine_transform) => {
|
||||||
*context.last_mut().unwrap() *= affine_transform
|
*context_ctm.last_mut().unwrap() *= affine_transform
|
||||||
}
|
}
|
||||||
Statement::Transform(affine_transform) => {
|
Statement::Transform(affine_transform) => {
|
||||||
*context.last_mut().unwrap() = affine_transform
|
*context_ctm.last_mut().unwrap() = affine_transform
|
||||||
}
|
}
|
||||||
Statement::Unknown(s, _items) => {
|
Statement::Unknown(s, _items) => {
|
||||||
eprintln!("Unknown statement: {s}")
|
eprintln!("Unknown statement: {s}")
|
||||||
|
|
@ -688,14 +705,14 @@ fn inner_parse_pbrt(path: impl AsRef<Path> + std::fmt::Debug) -> Result<Pbrt> {
|
||||||
if camera.is_some() {
|
if camera.is_some() {
|
||||||
return Err(miette!("The camera can only be set once."));
|
return Err(miette!("The camera can only be set once."));
|
||||||
}
|
}
|
||||||
camera = Some((c, *context.last().unwrap()));
|
camera = Some((c, *context_ctm.last().unwrap()));
|
||||||
named_transforms.insert(String::from("\"camera\""), *context.last().unwrap());
|
named_transforms.insert(String::from("\"camera\""), *context_ctm.last().unwrap());
|
||||||
}
|
}
|
||||||
Statement::CoordinateSystem(s) => {
|
Statement::CoordinateSystem(s) => {
|
||||||
named_transforms.insert(s, *context.last().unwrap());
|
named_transforms.insert(s, *context_ctm.last().unwrap());
|
||||||
}
|
}
|
||||||
Statement::CoordSysTransform(s) => {
|
Statement::CoordSysTransform(s) => {
|
||||||
*context.last_mut().unwrap() = *named_transforms
|
*context_ctm.last_mut().unwrap() = *named_transforms
|
||||||
.get(&s)
|
.get(&s)
|
||||||
.ok_or_else(|| miette!("unknown transform"))?;
|
.ok_or_else(|| miette!("unknown transform"))?;
|
||||||
}
|
}
|
||||||
|
|
@ -708,34 +725,36 @@ fn inner_parse_pbrt(path: impl AsRef<Path> + std::fmt::Debug) -> Result<Pbrt> {
|
||||||
|
|
||||||
let mut pbrt = Pbrt::new(PbrtWorldSettings { camera, camera_ctm });
|
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 {
|
match p {
|
||||||
Statement::AttributeBegin => context.push(*context.last().unwrap()),
|
Statement::AttributeBegin => context_ctm.push(*context_ctm.last().unwrap()),
|
||||||
Statement::AttributeEnd => {
|
Statement::AttributeEnd => {
|
||||||
context.pop();
|
context_ctm.pop();
|
||||||
}
|
}
|
||||||
Statement::Include(_) => unreachable!(),
|
Statement::Include(_) => unreachable!(),
|
||||||
Statement::ConcatTransform(affine_transform) => {
|
Statement::ConcatTransform(affine_transform) => {
|
||||||
*context.last_mut().unwrap() *= affine_transform
|
*context_ctm.last_mut().unwrap() *= affine_transform
|
||||||
}
|
}
|
||||||
Statement::Transform(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) => {
|
Statement::Shape(shape_type, shape_alpha) => {
|
||||||
pbrt.scene.shapes.push(Shape {
|
pbrt.scene.shapes.push(Shape {
|
||||||
ctm: *context.last().unwrap(),
|
ctm: *context_ctm.last().unwrap(),
|
||||||
material: 0,
|
material: 0,
|
||||||
obj: shape_type,
|
obj: shape_type,
|
||||||
alpha: shape_alpha,
|
alpha: shape_alpha,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Statement::CoordinateSystem(s) => {
|
Statement::CoordinateSystem(s) => {
|
||||||
named_transforms.insert(s, *context.last().unwrap());
|
named_transforms.insert(s, *context_ctm.last().unwrap());
|
||||||
}
|
}
|
||||||
Statement::CoordSysTransform(s) => {
|
Statement::CoordSysTransform(s) => {
|
||||||
*context.last_mut().unwrap() = *named_transforms
|
*context_ctm.last_mut().unwrap() = *named_transforms
|
||||||
.get(&s)
|
.get(&s)
|
||||||
.ok_or_else(|| miette!("unknown transform"))?;
|
.ok_or_else(|| miette!("unknown transform"))?;
|
||||||
}
|
}
|
||||||
|
|
@ -746,8 +765,6 @@ fn inner_parse_pbrt(path: impl AsRef<Path> + std::fmt::Debug) -> Result<Pbrt> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg!(named_transforms);
|
|
||||||
|
|
||||||
Ok(pbrt)
|
Ok(pbrt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
120
ray-tracing-pbrt-scene/src/texture.rs
Normal file
120
ray-tracing-pbrt-scene/src/texture.rs
Normal file
|
|
@ -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<Self>) -> Result<Arc<dyn Pbrt_2d_float_texture>>;
|
||||||
|
fn get_2d_spectrum_texture(self: Arc<Self>) -> Result<Arc<dyn Pbrt_2d_spectrum_texture>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
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<Self> {
|
||||||
|
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<dyn PbrtTexture>)> {
|
||||||
|
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<Arc<dyn Pbrt_2d_float_texture>>,
|
||||||
|
spectrum: Option<Arc<dyn Pbrt_2d_spectrum_texture>>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct TextureD2<T> {
|
||||||
|
inner: T,
|
||||||
|
uscale: Float,
|
||||||
|
vscale: Float,
|
||||||
|
udelta: Float,
|
||||||
|
vdelta: Float,
|
||||||
|
mapping: TextureMapping,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: PbrtTexture> PbrtTexture for TextureD2<T> {
|
||||||
|
fn get_2d_float_texture(self: Arc<Self>) -> Result<Arc<dyn Pbrt_2d_float_texture>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_2d_spectrum_texture(self: Arc<Self>) -> Result<Arc<dyn Pbrt_2d_spectrum_texture>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct CheckerboardTexture {
|
||||||
|
dimension: u8,
|
||||||
|
tex1: FloatTexture2d,
|
||||||
|
tex2: FloatTexture2d,
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue