diff --git a/examples/dawn.rs b/examples/dawn.rs index 955bebb..2d1d7c2 100644 --- a/examples/dawn.rs +++ b/examples/dawn.rs @@ -35,16 +35,8 @@ fn main() { wavelength: Sample::Blackbody(4500.0), }; - let viewport = Rect::from_points( - &Point { x: 0.0, y: 0.0 }, - &Point { - x: width, - y: height, - }, - ); - println!("Tracing Rays!"); - let r = Scene::new(width as usize, height as usize, viewport) + let r = Scene::new(width as usize, height as usize) .with_object(o) .with_light(l); let image = r.render(rays); diff --git a/examples/laser-rainbow.rs b/examples/laser-rainbow.rs index 74508ff..40ebec8 100644 --- a/examples/laser-rainbow.rs +++ b/examples/laser-rainbow.rs @@ -71,16 +71,8 @@ fn main() { material: Box::new(floor_m.clone()), }; - let viewport = Rect::from_points( - &Point { x: 0.0, y: 0.0 }, - &Point { - x: width + 1.0, - y: height + 1.0, - }, - ); - println!("Tracing Rays!"); - let r = Scene::new(width as usize, height as usize, viewport) + let r = Scene::new(width as usize, height as usize) .with_light(laser(30.0, 694.0)) .with_light(laser(31.0, 676.0)) .with_light(laser(32.0, 647.0)) diff --git a/rustic.code-workspace b/rustic.code-workspace new file mode 100644 index 0000000..ef9f5d2 --- /dev/null +++ b/rustic.code-workspace @@ -0,0 +1,7 @@ +{ + "folders": [ + { + "path": "." + } + ] +} \ No newline at end of file diff --git a/src/geom.rs b/src/geom.rs index 9c643af..07f9f32 100644 --- a/src/geom.rs +++ b/src/geom.rs @@ -1,6 +1,7 @@ #![allow(missing_docs)] -use std::ops::{Add, Neg, Sub}; +use std::ops::{Add, Neg, Sub, Mul}; +use std::option::Option; #[derive(PartialOrd, PartialEq, Copy, Clone, Debug)] pub struct Point { @@ -14,6 +15,13 @@ pub struct Vector { pub y: f64, } +#[derive(Copy, Clone, Debug)] +pub struct Matrix { + pub a1: f64, pub b1: f64, + pub a2: f64, pub b2: f64, +} + + #[derive(PartialOrd, PartialEq, Copy, Clone, Debug)] pub struct Rect { pub top_left: Point, @@ -30,6 +38,88 @@ impl Neg for Vector { } } +impl Sub for Matrix { + type Output = Matrix; + fn sub(self, rhs: Matrix) -> Matrix { + Matrix { + a1: self.a1 - rhs.a1, + a2: self.a2 - rhs.a2, + b1: self.b1 - rhs.b1, + b2: self.b2 - rhs.b2, + } + } +} + +impl Add for Matrix { + type Output = Matrix; + fn add(self, rhs: Matrix) -> Matrix { + Matrix { + a1: self.a1 + rhs.a1, + a2: self.a2 + rhs.a2, + b1: self.b1 + rhs.b1, + b2: self.b2 + rhs.b2, + } + } +} + +impl Mul for Matrix { + type Output = Matrix; + fn mul(self, rhs: Matrix) -> Matrix { + Matrix { + a1: (self.a1 * rhs.a1) + (self.b1 * rhs.a2), + a2: (self.a2 * rhs.a1) + (self.b2 * rhs.a2), + b1: (self.a1 * rhs.b1) + (self.b1 * rhs.b2), + b2: (self.a2 * rhs.b1) + (self.b2 * rhs.b2), + } + } +} + +impl Mul for Matrix { + type Output = Matrix; + fn mul(self, rhs: f64) -> Matrix { + Matrix { + a1: self.a1 * rhs, + a2: self.a2 * rhs, + b1: self.b1 * rhs, + b2: self.b2 * rhs, + } + } +} + +impl Mul for Matrix { + type Output = Point; + fn mul(self, rhs: Point) -> Point { + Point { + x: (self.a1 * rhs.x) + (self.b1 * rhs.y), + y: (self.a2 * rhs.x) + (self.b2 * rhs.y), + } + } +} + +impl Mul for Matrix { + type Output = Vector; + fn mul(self, rhs: Vector) -> Vector { + Vector { + x: (self.a1 * rhs.x) + (self.b1 * rhs.y), + y: (self.a2 * rhs.x) + (self.b2 * rhs.y), + } + } +} + +impl Matrix { + pub fn inverse(self) -> Option { + let det = (self.a1 * self.b2) - (self.b1 * self.a2); + if det == 0.0 { + None + } else { + Some(Matrix { + a1: self.b2, b1: -self.b1, + a2: -self.a2, b2: self.a1, + } * (1.0/det)) + } + } +} + impl Sub for Point { type Output = Point; fn sub(self, rhs: Vector) -> Point { diff --git a/src/lib.rs b/src/lib.rs index 54c2ea0..585962f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -76,7 +76,7 @@ mod scene; /// This prelude contains everything to quickstart using Rustic Zen. pub mod prelude { - pub use geom::{Point, Rect}; + pub use geom::{Point}; pub use material::{HQZLegacy, Material}; pub use object::Object; pub use sampler::Sample; @@ -115,8 +115,6 @@ mod tests { use scene::Light; use scene::Scene; - use geom::{Point, Rect}; - use material::HQZLegacy; #[test] @@ -134,14 +132,7 @@ mod tests { wavelength: Sample::Blackbody(6900.0), }; - let viewport = Rect::from_points( - &Point { x: 0.0, y: 0.0 }, - &Point { - x: width, - y: height, - }, - ); - let r = Scene::new(width as usize, height as usize, viewport).with_light(l); + let r = Scene::new(width as usize, height as usize).with_light(l); let image = r.render(10_000); let data = image.to_rgb8(0.5, 0.5); @@ -183,15 +174,7 @@ mod tests { wavelength: Sample::Blackbody(6900.0), }; - let viewport = Rect::from_points( - &Point { x: 0.0, y: 0.0 }, - &Point { - x: width, - y: height, - }, - ); - - let r = Scene::new(width as usize, height as usize, viewport) + let r = Scene::new(width as usize, height as usize) .with_light(l) .with_object(o); let image = r.render(rays); @@ -235,15 +218,7 @@ mod tests { wavelength: Sample::Blackbody(6900.0), }; - let viewport = Rect::from_points( - &Point { x: 0.0, y: 0.0 }, - &Point { - x: width, - y: height, - }, - ); - - let r = Scene::new(width as usize, height as usize, viewport) + let r = Scene::new(width as usize, height as usize) .with_light(l) .with_object(o); let image = r.render(rays); diff --git a/src/ray.rs b/src/ray.rs index 8acfeac..a216a0f 100644 --- a/src/ray.rs +++ b/src/ray.rs @@ -1,4 +1,4 @@ -use geom::{Point, Rect, Vector}; +use geom::{Point, Rect, Vector, Matrix}; use image::Image; use object::Object; use prng::PRNG; @@ -128,18 +128,33 @@ impl Ray { } fn intersect_edge(&self, s1: Point, sd: Point) -> Option { - let slope = self.direction.y / self.direction.x; - let alpha = - ((s1.x - self.origin.x) * slope + (self.origin.y - s1.y)) / (sd.y - sd.x * slope); - if alpha < 0.0 || alpha > 1.0 { - return None; - } + let mat_a = Matrix { + a1: sd.x - s1.x, b1: self.origin.x - self.direction.x, + a2: sd.y - s1.y, b2: self.origin.y - self.direction.y, + }; - let distance = (s1.x + sd.x * alpha - self.origin.x) / self.direction.x; - if distance < 0.0 { - return None; + let omega = self.origin - s1; + + let result = mat_a.inverse().unwrap() * omega; + if (result.x >= 0.0) && (result.x <= 1.0) && (result.y > 0.0) { + Some(result.y) + } else { + None } - return Some(distance); + + + // let slope = self.direction.y / self.direction.x; + // let alpha = + // ((s1.x - self.origin.x) * slope + (self.origin.y - s1.y)) / (sd.y - sd.x * slope); + // if alpha < 0.0 || alpha > 1.0 { + // return None; + // } + + // let distance = (s1.x + sd.x * alpha - self.origin.x) / self.direction.x; + // if distance < 0.0 { + // return None; + // } + // return Some(distance); } pub fn furthest_aabb(&self, aabb: Rect) -> Option { @@ -294,7 +309,6 @@ mod test { } #[test] - #[ignore] fn furthest_aabb_hits_vertical() { let mut rng = PRNG::seed(0); @@ -323,8 +337,8 @@ mod test { assert!(result.is_some()); let result = result.unwrap(); println!("result: ({},{})", result.x, result.y); - assert_eq!(result.x, 0.0); - assert_eq!(result.y, 11.0); + assert_eq!(result.x.round(), 0.0); + assert_eq!(result.y.round(), 11.0); } #[test] diff --git a/src/scene.rs b/src/scene.rs index 0b4fb0b..7d847b4 100644 --- a/src/scene.rs +++ b/src/scene.rs @@ -1,4 +1,4 @@ -use geom::Rect; +use geom::{Point, Rect}; use image::Image; use object::Object; use prng::PRNG; @@ -53,12 +53,12 @@ pub struct Scene { impl Scene { /// Creates new Renderer ready for defining a scene. - pub fn new(resolution_x: usize, resolution_y: usize, viewport: Rect) -> Self { + pub fn new(resolution_x: usize, resolution_y: usize) -> Self { Self { seed: 0, lights: vec![], objects: vec![], - viewport, + viewport: Rect::from_points(&Point{ x: 0.0, y: 0.0 }, &Point { x: resolution_x as f64, y: resolution_y as f64 }), resolution_x, resolution_y, total_light_power: 0.0, @@ -126,7 +126,6 @@ impl Scene { #[cfg(test)] mod tests { use super::Scene; - use geom::{Point, Rect}; use material::HQZLegacy; use object::Object; use sampler::Sample; @@ -154,9 +153,7 @@ mod tests { wavelength: Sample::Blackbody(5800.0), }; - let viewport = Rect::from_points(&Point { x: 0.0, y: 0.0 }, &Point { x: 160.0, y: 90.0 }); - - let r = Scene::new(1920, 1080, viewport) + let r = Scene::new(1920, 1080) .with_light(l) .with_object(obj); r.render(100);