diff --git a/ray-tracing-core/src/affine_transform.rs b/ray-tracing-core/src/affine_transform.rs index 9998282..a0f52b5 100644 --- a/ray-tracing-core/src/affine_transform.rs +++ b/ray-tracing-core/src/affine_transform.rs @@ -224,6 +224,23 @@ impl AffineTransform { + self.mat[2][3], ) } + + pub fn inverse_transform_pos(&self, pos: Pos3) -> Pos3 { + Pos3::new( + self.inv[0][0] * pos.x() + + self.inv[0][1] * pos.y() + + self.inv[0][2] * pos.z() + + self.inv[0][3], + self.inv[1][0] * pos.x() + + self.inv[1][1] * pos.y() + + self.inv[1][2] * pos.z() + + self.inv[1][3], + self.inv[2][0] * pos.x() + + self.inv[2][1] * pos.y() + + self.inv[2][2] * pos.z() + + self.inv[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(), @@ -231,13 +248,27 @@ impl AffineTransform { 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 { - Pos3::new( + pub fn inverse_transform_dir(&self, dir: Dir3) -> Dir3 { + Dir3::new( + self.inv[0][0] * dir.x() + self.inv[0][1] * dir.y() + self.inv[0][2] * dir.z(), + self.inv[1][0] * dir.x() + self.inv[1][1] * dir.y() + self.inv[1][2] * dir.z(), + self.inv[2][0] * dir.x() + self.inv[2][1] * dir.y() + self.inv[2][2] * dir.z(), + ) + } + pub fn transform_normal(&self, pos: Dir3) -> Dir3 { + Dir3::new( self.inv[0][0] * pos.x() + self.inv[0][1] * pos.y() + self.inv[0][2] * pos.z(), self.inv[1][0] * pos.x() + self.inv[1][1] * pos.y() + self.inv[1][2] * pos.z(), self.inv[2][0] * pos.x() + self.inv[2][1] * pos.y() + self.inv[2][2] * pos.z(), ) } + pub fn inverse_transform_normal(&self, pos: Dir3) -> Dir3 { + Dir3::new( + self.mat[0][0] * pos.x() + self.mat[0][1] * pos.y() + self.mat[0][2] * pos.z(), + self.mat[1][0] * pos.x() + self.mat[1][1] * pos.y() + self.mat[1][2] * pos.z(), + self.mat[2][0] * pos.x() + self.mat[2][1] * pos.y() + self.mat[2][2] * pos.z(), + ) + } pub fn transform_ray(&self, ray: Ray) -> Ray { Ray::new( @@ -302,7 +333,7 @@ impl Mul for AffineTransform { self.mat[2][0] * rhs.mat[0][2] + self.mat[2][1] * rhs.mat[1][2] + self.mat[2][2] * rhs.mat[2][2] - + self.mat[2][3] * rhs.mat[3][3], + + self.mat[2][3] * rhs.mat[3][2], self.mat[2][0] * rhs.mat[0][3] + self.mat[2][1] * rhs.mat[1][3] + self.mat[2][2] * rhs.mat[2][3] @@ -376,7 +407,7 @@ impl Mul for AffineTransform { rhs.inv[2][0] * self.inv[0][2] + rhs.inv[2][1] * self.inv[1][2] + rhs.inv[2][2] * self.inv[2][2] - + rhs.inv[2][3] * self.inv[3][3], + + rhs.inv[2][3] * self.inv[3][2], rhs.inv[2][0] * self.inv[0][3] + rhs.inv[2][1] * self.inv[1][3] + rhs.inv[2][2] * self.inv[2][3] diff --git a/ray-tracing-pbrt-scene/src/lib.rs b/ray-tracing-pbrt-scene/src/lib.rs index 3196f9a..95d6e8b 100644 --- a/ray-tracing-pbrt-scene/src/lib.rs +++ b/ray-tracing-pbrt-scene/src/lib.rs @@ -483,7 +483,11 @@ fn parse_transform(input: &mut Tokenizer) -> Result { } fn parse_translate(iter: &mut Tokenizer) -> Result> { - let pos = Pos3::new(iter.parse_next()?, iter.parse_next()?, iter.parse_next()?); + let pos = Pos3::new( + -iter.parse_next()?, + -iter.parse_next()?, + -iter.parse_next()?, + ); Ok(Statement::ConcatTransform(AffineTransform::translation( pos, @@ -592,7 +596,7 @@ impl Pbrt { scene: PbrtScene { shapes: Vec::new(), infinite_light: Some(scene::PbrtInfiniteLight { - color: Color::white(), + color: Color::new(0.4, 0.45, 0.5), }), }, } diff --git a/ray-tracing-pbrt-scene/src/material.rs b/ray-tracing-pbrt-scene/src/material.rs index a050559..4c837da 100644 --- a/ray-tracing-pbrt-scene/src/material.rs +++ b/ray-tracing-pbrt-scene/src/material.rs @@ -98,6 +98,34 @@ impl PbrtMaterial for PbrtDielectricMaterial { let _ = u; Color::black() } + + fn sample(&self, u: Float, v: Float, w_in: Dir3, rng: &mut R) -> SampleResult { + let _ = rng; + let _ = v; + let _ = u; + let _ = match self.eta { + Either::A(Either::A(eta)) => eta, + _ => todo!(), + }; + + // let c = w_in.y(); + // let w_out = -w_in * eta + // + (eta * c - Float::sqrt(1.0 - eta * eta * (1.0 - c * c))) * Dir3::new(0.0, -1.0, 1.0); + + SampleResult::new( + Dir3::new(0.0, 2.0 * w_in.y(), 0.0) - w_in, + Color::white(), + true, + ) + } + + fn pdf(&self, u: Float, v: Float, w_in: Dir3, w_out: Dir3) -> Float { + let _ = w_in; + let _ = v; + let _ = u; + let _ = w_out; + 0.0 + } } #[derive(Debug)] diff --git a/ray-tracing-pbrt-scene/src/shape.rs b/ray-tracing-pbrt-scene/src/shape.rs index 7992705..8fc787f 100644 --- a/ray-tracing-pbrt-scene/src/shape.rs +++ b/ray-tracing-pbrt-scene/src/shape.rs @@ -77,11 +77,7 @@ fn quadratic(a: Float, b: Float, c: Float) -> (Option, Option) { let root_discrim = Float::sqrt(discrim); - let q = if b < 0.0 { - -0.5 * (b - root_discrim) - } else { - -0.5 * (b + root_discrim) - }; + let q = -0.5 * (b + Float::copysign(root_discrim, b)); let mut t0 = q / a; let mut t1 = c / q; @@ -124,8 +120,10 @@ fn bilinear_intersection( false }) .filter_map(|u| { - let uo = patch[0].as_dir() * u + patch[2].as_dir() * (1.0 - u); - let ud = patch[1].as_dir() * u + patch[3].as_dir() * (1.0 - u) - uo; + // dbg!(a, b, c, u, a * u * u + b * u + c); + + let uo = patch[0].as_dir() * (1.0 - u) + patch[2].as_dir() * u; + let ud = patch[1].as_dir() * (1.0 - u) + patch[3].as_dir() * u - uo; let deltao = uo - ray.start().as_dir(); @@ -133,23 +131,22 @@ fn bilinear_intersection( let p2 = perp.length_squared(); - let v1 = deltao.x() * ray.dir().y() - + perp.z() + let v1 = deltao.x() * ray.dir().y() * perp.z() + ray.dir().x() * perp.y() * deltao.z() + perp.x() * deltao.y() * ray.dir().z() - - deltao.x() * perp.y() * deltao.z() + - deltao.x() * perp.y() * ray.dir().z() - ray.dir().x() * deltao.y() * perp.z() - perp.x() * ray.dir().y() * deltao.z(); - let t1 = deltao.x() * ud.y() - + perp.z() + let t1 = deltao.x() * ud.y() * perp.z() + ud.x() * perp.y() * deltao.z() + perp.x() * deltao.y() * ud.z() - - deltao.x() * perp.y() * deltao.z() + - deltao.x() * perp.y() * ud.z() - ud.x() * deltao.y() * perp.z() - perp.x() * ud.y() * deltao.z(); - if t1 >= min && t1 <= max && 0.0 < v1 && v1 <= p2 { + // dbg!(t1 / p2, v1 / p2); + if min * p2 <= t1 && t1 <= max * p2 && 0.0 <= v1 && v1 <= p2 { Some((t1 / p2, u, v1 / p2)) } else { None @@ -220,7 +217,8 @@ impl Shape { } return Some(Intersection::new( t, - (ray.at(t) - Pos3::zero()).normalize(), + self.ctm + .inverse_transform_normal((ray.at(t).as_dir()).normalize()), Some(UVMaterial { u: phi, v: Float::acos(p.z() / radius), @@ -245,7 +243,7 @@ impl Shape { { return Some(Intersection::new( t, - Dir3::up(), + Dir3::new(0.0, 0.0, 1.0), Some(UVMaterial { u, v, diff --git a/ray-tracing-pbrt-scene/src/texture/checkerboard.rs b/ray-tracing-pbrt-scene/src/texture/checkerboard.rs index 28052c9..ac6d84a 100644 --- a/ray-tracing-pbrt-scene/src/texture/checkerboard.rs +++ b/ray-tracing-pbrt-scene/src/texture/checkerboard.rs @@ -49,16 +49,7 @@ pub(super) struct SpectrumCheckerboardTexture2d { impl Pbrt2dSpectrumTexture for SpectrumCheckerboardTexture2d { fn get(&self, u: Float, v: Float) -> Color { let (u, v) = self.mapping.map(u, v); - - let even = if u >= 0.0 { - u.fract() >= 0.5 - } else { - u.fract() >= -0.5 - } ^ if v >= 0.0 { - v.fract() >= 0.5 - } else { - v.fract() >= -0.5 - }; + let even = (u.floor() as i64 + v.floor() as i64) % 2 == 0; match &self.tex[even as usize] { Either::A(v) => *v, diff --git a/ray-tracing-tev/src/main.rs b/ray-tracing-tev/src/main.rs index 1ec709b..b9aa5fe 100644 --- a/ray-tracing-tev/src/main.rs +++ b/ray-tracing-tev/src/main.rs @@ -230,7 +230,7 @@ fn main() { Pos3::new(3.0, 4.0, 1.5), Pos3::new(0.5, 0.5, 0.0), Dir3::new(0.0, 0.0, 1.0), - Float::to_radians(45.0), + Float::to_radians(90.0), ); let s = &pbrt.scene;