49 lines
1.2 KiB
Rust
49 lines
1.2 KiB
Rust
|
use cgmath::{InnerSpace, Vector3};
|
||
|
|
||
|
use super::ray::Ray;
|
||
|
|
||
|
pub struct Triangle {
|
||
|
pub points: [Vector3<f32>; 3],
|
||
|
}
|
||
|
|
||
|
impl Triangle {
|
||
|
pub fn new(v0: Vector3<f32>, v1: Vector3<f32>, v2: Vector3<f32>) -> Triangle {
|
||
|
Triangle {
|
||
|
points: [v0, v1, v2],
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// source: https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-rendering-a-triangle/moller-trumbore-ray-triangle-intersection
|
||
|
pub fn intersect_mt(&self, ray: &Ray, t: &mut f32) -> bool {
|
||
|
let v0v1 = self.points[1] - self.points[0];
|
||
|
let v0v2 = self.points[2] - self.points[0];
|
||
|
let pvec = ray.direction.cross(v0v2);
|
||
|
let det = v0v1.dot(pvec);
|
||
|
|
||
|
// ray and triangle are parallel if det is close to 0
|
||
|
if det.abs() < 0.001 {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
let inv_det = 1.0 / det;
|
||
|
|
||
|
let tvec = ray.origin - self.points[0];
|
||
|
let u = tvec.dot(pvec) * inv_det;
|
||
|
|
||
|
if u < 0.0 || u > 1.0 {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
let qvec = tvec.cross(v0v1);
|
||
|
let v = ray.direction.dot(qvec) * inv_det;
|
||
|
|
||
|
if v < 0.0 || u + v > 1.0 {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
*t = v0v2.dot(qvec) * inv_det;
|
||
|
|
||
|
true
|
||
|
}
|
||
|
}
|