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:
parent
539dc47b4e
commit
54f4c278ca
21
src/main.rs
21
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##"
|
||||
|
|
34
src/triangle.rs
Normal file
34
src/triangle.rs
Normal 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
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user