Rendering something parsed from a pbrt file

This commit is contained in:
hal8174 2025-08-20 23:20:41 +02:00
parent c8ff77a0a9
commit 6d363aecd0
Signed by: hal8174
SSH key fingerprint: SHA256:NN98ZYwnrreQLSOV/g+amY7C3yL/mS1heD7bi5t6PPw
7 changed files with 316 additions and 127 deletions

View file

@ -1,4 +1,9 @@
use crate::{texture::Pbrt_2d_float_texture, tokenizer::Tokenizer};
use crate::{
scene::PbrtScene,
shape::{Shape, ShapeAlpha, ShapeType},
texture::Pbrt_2d_float_texture,
tokenizer::Tokenizer,
};
use error::SourceFile;
use material::PbrtMaterial;
use miette::{Diagnostic, IntoDiagnostic, Result, SourceSpan, bail, miette};
@ -21,6 +26,8 @@ mod tokenizer;
mod either;
mod error;
mod material;
pub mod scene;
mod shape;
mod texture;
struct Lexer {
@ -595,64 +602,10 @@ impl Parser {
}
}
#[derive(Debug)]
enum ShapeType {
Sphere {
radius: Float,
zmin: Float,
zmax: Float,
phimax: Float,
},
TriangleMesh {
indices: Vec<usize>,
p: Vec<Pos3>,
n: Vec<Dir3>,
s: Vec<Dir3>,
uv: Vec<[Float; 2]>,
},
BilinearMesh {
indices: Vec<usize>,
p: Vec<Pos3>,
n: Vec<Dir3>,
uv: Vec<[Float; 2]>,
},
LoopSubDiv {
levels: u32,
indices: Vec<usize>,
p: Vec<Pos3>,
},
Disk {
height: Float,
radius: Float,
innerradius: Float,
phimax: Float,
},
PlyMesh {
filename: String,
displacement: Option<String>,
edgelength: Float,
},
}
#[derive(Debug)]
enum ShapeAlpha {
None,
Value(Float),
Texture(String),
}
#[derive(Debug)]
struct Shape {
ctm: AffineTransform,
material: Arc<dyn PbrtMaterial>,
obj: ShapeType,
alpha: ShapeAlpha,
}
#[derive(Debug)]
pub struct Pbrt {
settings: PbrtWorldSettings,
scene: PbrtScene,
pub settings: PbrtWorldSettings,
pub scene: PbrtScene,
}
impl Pbrt {
@ -670,11 +623,6 @@ struct PbrtWorldSettings {
camera_ctm: AffineTransform,
}
#[derive(Debug)]
struct PbrtScene {
shapes: Vec<Shape>,
}
#[derive(Debug)]
pub struct PbrtContext {
ctm: Vec<AffineTransform>,
@ -861,7 +809,7 @@ fn inner_parse_pbrt(path: impl AsRef<Path> + std::fmt::Debug) -> Result<Pbrt> {
}
}
dbg!(context);
// dbg!(context);
Ok(pbrt)
}

View file

@ -0,0 +1,40 @@
use ray_tracing_core::{prelude::Rng, scene::Scene};
use crate::shape::Shape;
#[derive(Debug)]
pub struct PbrtScene {
pub(crate) shapes: Vec<Shape>,
}
impl<R: Rng> Scene<R> for PbrtScene {
fn intersect(
&self,
ray: ray_tracing_core::prelude::Ray,
min: ray_tracing_core::prelude::Float,
max: ray_tracing_core::prelude::Float,
) -> Option<ray_tracing_core::scene::Intersection<'_, R>> {
let mut i = None;
for s in &self.shapes {
if let Some(new_i) = s.intersect::<R>(ray, min, max)
&& i.as_ref()
.is_none_or(|i: &ray_tracing_core::scene::Intersection<'_, R>| {
i.t() > new_i.t()
})
{
i = Some(new_i);
}
}
i
}
fn sample_light(
&self,
w_in: ray_tracing_core::prelude::Dir3,
intersection: &ray_tracing_core::scene::Intersection<'_, R>,
rng: &mut R,
) -> Option<ray_tracing_core::scene::LightSample<'_, R>> {
None
}
}

View file

@ -0,0 +1,154 @@
use std::sync::Arc;
use ray_tracing_core::{affine_transform::AffineTransform, prelude::*, scene::Intersection};
use crate::material::PbrtMaterial;
#[derive(Debug)]
pub(crate) struct Shape {
pub(crate) ctm: AffineTransform,
pub(crate) material: Arc<dyn PbrtMaterial>,
pub(crate) obj: ShapeType,
pub(crate) alpha: ShapeAlpha,
}
#[derive(Debug)]
pub(crate) enum ShapeAlpha {
None,
Value(Float),
Texture(String),
}
#[derive(Debug)]
pub(crate) enum ShapeType {
Sphere {
radius: Float,
zmin: Float,
zmax: Float,
phimax: Float,
},
TriangleMesh {
indices: Vec<usize>,
p: Vec<Pos3>,
n: Vec<Dir3>,
s: Vec<Dir3>,
uv: Vec<[Float; 2]>,
},
BilinearMesh {
indices: Vec<usize>,
p: Vec<Pos3>,
n: Vec<Dir3>,
uv: Vec<[Float; 2]>,
},
LoopSubDiv {
levels: u32,
indices: Vec<usize>,
p: Vec<Pos3>,
},
Disk {
height: Float,
radius: Float,
innerradius: Float,
phimax: Float,
},
PlyMesh {
filename: String,
displacement: Option<String>,
edgelength: Float,
},
}
impl Shape {
pub(crate) fn intersect<R: Rng>(
&self,
ray: Ray,
min: Float,
max: Float,
) -> Option<Intersection<R>> {
let ray = self.ctm.transform_ray(ray);
match &self.obj {
&ShapeType::Sphere {
radius,
zmin,
zmax,
phimax,
} => {
let a = ray.dir().length_squared();
let b = 2.0 * Dir3::dot(ray.dir(), ray.start() - Pos3::zero());
let c = Dir3::dot(ray.start() - Pos3::zero(), ray.start() - Pos3::zero())
- radius * radius;
let dir = ray.dir().normalize();
let v = ray.start() - (b / (2.0 * a) * dir);
let length = (v - Pos3::zero()).length();
let discrim = 4.0 * a * (radius + length) * (radius - length);
if discrim > 0.0 {
let root_discrim = Float::sqrt(discrim);
let q = if b < 0.0 {
-0.5 * (b - root_discrim)
} else {
-0.5 * (b + root_discrim)
};
let mut t0 = q / a;
let mut t1 = c / q;
if t1 < t0 {
std::mem::swap(&mut t1, &mut t0);
}
if let Some(t) = [t0, t1]
.into_iter()
.filter(|&t| {
if min <= t && t <= max {
let p = ray.at(t0);
let mut phi = Float::atan2(p.y(), p.x());
if phi < 0.0 {
phi += 2.0 * FloatConsts::PI;
}
if zmin <= p.z() && p.z() <= zmax && phi <= phimax {
return true;
}
}
false
})
.next()
{
return Some(Intersection::new(
t,
(ray.at(t) - Pos3::zero()).normalize(),
None,
None,
0.0,
));
}
}
}
ShapeType::TriangleMesh {
indices,
p,
n,
s,
uv,
} => (),
ShapeType::BilinearMesh { indices, p, n, uv } => (),
ShapeType::LoopSubDiv { levels, indices, p } => todo!(),
ShapeType::Disk {
height,
radius,
innerradius,
phimax,
} => (),
ShapeType::PlyMesh {
filename,
displacement,
edgelength,
} => (),
}
None
}
}