diff --git a/src/primitive.rs b/src/primitive.rs index 9da5435..b475529 100644 --- a/src/primitive.rs +++ b/src/primitive.rs @@ -506,17 +506,17 @@ impl Primitive for Cube { //Get normal of intersection point let normal = if tmin == t1.x { - Vector3::new(-1.0, 0.0, 0.0) + Vector3::new(1.0, 0.0, 0.0) } else if tmin == t1.y { Vector3::new(0.0, -1.0, 0.0) } else if tmin == t1.z { - Vector3::new(0.0, 0.0, -1.0) + Vector3::new(0.0, 0.0, 1.0) } else if tmin == t2.x { - Vector3::new(1.0, 0.0, 0.0) + Vector3::new(-1.0, 0.0, 0.0) } else if tmin == t2.y { Vector3::new(0.0, 1.0, 0.0) } else { - Vector3::new(0.0, 0.0, 1.0) + Vector3::new(0.0, 0.0, -1.0) }; Some(Intersection { @@ -535,6 +535,8 @@ impl Primitive for Cube { } // TRIANGLE ----------------------------------------------------------------- +// Points u,v,w will be pointing outward from uw x uv +// Using the right hand rule #[derive(Clone)] #[allow(dead_code)] pub struct Triangle { @@ -549,7 +551,7 @@ impl Triangle { pub fn new(u: Point3, v: Point3, w: Point3) -> Rc { let uv = v - u; let uw = w - u; - let normal = uv.cross(&uw).normalize(); + let normal = uw.cross(&uv).normalize(); let bln = u.inf(&v).inf(&w); let trf = u.sup(&v).sup(&w); let bounding_box = BoundingBox { bln, trf }; @@ -572,40 +574,43 @@ impl Triangle { impl Primitive for Triangle { fn intersect_ray(&self, ray: &Ray) -> Option { - let constant = self.u.coords.dot(&self.normal); - let denominator = ray.b.dot(&self.normal); - let t = (constant - ray.a.coords.dot(&self.normal)) / denominator; + let (u, v, w) = (self.u, self.v, self.w); + let e1 = v - u; + let e2 = w - u; + let b_cross_e2 = ray.b.cross(&e2); + let det = e1.dot(&b_cross_e2); - if t > INFINITY { + if det > -EPSILON && det < EPSILON { return None; } - let intersect = ray.at_t(t); + let inv_det = 1.0 / det; + let s = ray.a - u; + let p = inv_det * s.dot(&b_cross_e2); - let uv = self.v - self.u; - let vw = self.w - self.v; - let wu = self.u - self.w; - - let ui = intersect - self.u; - let vi = intersect - self.v; - let wi = intersect - self.w; - - let u_cross = uv.cross(&ui); - let v_cross = vw.cross(&vi); - let w_cross = wu.cross(&wi); - - let normal = self.normal; - - if u_cross.dot(&normal) >= 0.0 && v_cross.dot(&normal) >= 0.0 && w_cross.dot(&normal) >= 0.0 - { - Some(Intersection { - point: intersect, - normal: normal, - distance: t, - }) - } else { - None + if p < 0.0 || p > 1.0 { + return None; } + + let s_cross_e1 = s.cross(&e1); + let v = inv_det * ray.b.dot(&s_cross_e1); + + if v < 0.0 || p + v > 1.0 { + return None; + } + let t = inv_det * e2.dot(&s_cross_e1); + + if t > EPSILON + // ray intersection + { + let intersect = ray.at_t(t); + return Some(Intersection { + point: intersect, + normal: self.normal, + distance: t, + }); + } + None } fn intersect_bounding_box(&self, ray: &Ray) -> bool { diff --git a/src/state.rs b/src/state.rs index e435b97..3076e97 100644 --- a/src/state.rs +++ b/src/state.rs @@ -20,8 +20,8 @@ use winit::window::{Window, WindowBuilder}; const START_WIDTH: i32 = 1200; const START_HEIGHT: i32 = 700; -const COLOUR_CLEAR: [u8; 4] = [0x22, 0x00, 0x11, 0xff]; -const PIXEL_CLEAR: [u8; 4] = [0x55, 0x00, 0x22, 0xff]; +const COLOUR_CLEAR: [u8; 4] = [0x22, 0x00, 0x11, 0x00]; +const PIXEL_CLEAR: [u8; 4] = [0x55, 0x00, 0x22, 0x00]; pub const INIT_FILE: &str = "rhai/scene.rhai"; pub const SAVE_FILE: &str = "img.png"; @@ -153,9 +153,13 @@ impl State { None => break, }; //Shade colour for selected ray - let colour = &self.rays[index].shade_ray(&self.scene); - //Assign colour to pixel in frame - let rgba = colour.map_or(PIXEL_CLEAR, |colour| [colour.x, colour.y, colour.z, 255]); + let rgba = match &self.rays[index].shade_ray(&self.scene, 0) { + Some(mut colour) => { + colour = colour * 255.0; + [colour.x as u8, colour.y as u8, colour.z as u8, 0xff] + } + None => PIXEL_CLEAR, + }; frame[index * 4..(index + 1) * 4].copy_from_slice(&rgba); } Ok(()) @@ -248,6 +252,7 @@ fn create_window(event_loop: &EventLoop<()>) -> Window { .with_title("Hello Pixels + Dear ImGui") .with_inner_size(size) .with_min_inner_size(size) + .with_transparent(true) .build(event_loop) .unwrap() }