diff --git a/src/main.rs b/src/main.rs index 2ed6811..3a5c5de 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,6 +8,7 @@ mod ray; mod bbox; mod data_tree; mod image; +mod triangle; use std::path::Path; @@ -15,6 +16,8 @@ use docopt::Docopt; use image::Image; use data_tree::DataTree; +use math::{Point, Vector}; +use ray::Ray; // ---------------------------------------------------------------- @@ -54,9 +57,23 @@ fn main() { return; } - // Write output image + // Write output image of ray-traced triangle + let p1 = Point::new(10.0, 80.0, 1.0); + let p2 = Point::new(420.0, 40.0, 1.0); + let p3 = Point::new(235.0, 490.0, 1.0); let mut img = Image::new(512, 512); - img.set(256, 256, (255, 255, 255)); + for y in 0..img.height() { + for x in 0..img.width() { + let ray = Ray::new(Point::new(x as f32, y as f32, 0.0), + Vector::new(0.0, 0.0, 1.0)); + if let Some((_, u, v)) = triangle::intersect_ray(&ray, (p1, p2, p3)) { + let r = (u * 255.0) as u8; + let g = (v * 255.0) as u8; + let b = ((1.0 - u - v) * 255.0).max(0.0) as u8; + img.set(x, y, (r, g, b)); + } + } + } let _ = img.write_binary_ppm(Path::new(&args.arg_imgpath)); let test_string = r##" diff --git a/src/triangle.rs b/src/triangle.rs new file mode 100644 index 0000000..fbf3856 --- /dev/null +++ b/src/triangle.rs @@ -0,0 +1,34 @@ +#![allow(dead_code)] + +use std; +use ray::Ray; +use math::{Point, cross, dot}; + +/// Intersects ray with tri, returning (t, u, v), or None if no intersection. +pub fn intersect_ray(ray: &Ray, tri: (Point, Point, Point)) -> Option<(f32, f32, f32)> { + let edge1 = tri.1 - tri.0; + let edge2 = tri.2 - tri.0; + let pvec = cross(ray.dir, edge2); + let det = dot(edge1, pvec); + + if det <= -std::f32::EPSILON || det >= std::f32::EPSILON { + let inv_det = 1.0 / det; + let tvec = ray.orig - tri.0; + let qvec = cross(tvec, edge1); + + let u = dot(tvec, pvec) * inv_det; + if u < 0.0 || u > 1.0 { + return None; + } + + let v = dot(ray.dir, qvec) * inv_det; + if v < 0.0 || (u + v) > 1.0 { + return None; + } + + let t = dot(edge2, qvec) * inv_det; + return Some((t, u, v)); + } else { + return None; // Ray is parallell to the plane of the triangle + } +}