Added triangle/ray intersection code.

As a test, the image written out is now a raytraced triangle,
with its color representing its UV coordinates.
This commit is contained in:
Nathan Vegdahl 2015-12-28 14:43:30 -08:00
parent 539dc47b4e
commit 54f4c278ca
2 changed files with 53 additions and 2 deletions

View File

@ -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##"

34
src/triangle.rs Normal file
View File

@ -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
}
}