Rendering something parsed from a pbrt file
This commit is contained in:
parent
c8ff77a0a9
commit
6d363aecd0
7 changed files with 316 additions and 127 deletions
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
40
ray-tracing-pbrt-scene/src/scene.rs
Normal file
40
ray-tracing-pbrt-scene/src/scene.rs
Normal 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
|
||||
}
|
||||
}
|
||||
154
ray-tracing-pbrt-scene/src/shape.rs
Normal file
154
ray-tracing-pbrt-scene/src/shape.rs
Normal 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
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue