Cleaned up implementation of ray/triangle intersection test.
This commit is contained in:
parent
f371e0643a
commit
a1840ec408
|
@ -17,28 +17,19 @@ use ray::Ray;
|
||||||
/// Intersection" by Woop et al.
|
/// Intersection" by Woop et al.
|
||||||
pub fn intersect_ray(ray: &Ray, tri: (Point, Point, Point)) -> Option<(f32, f32, f32, f32)> {
|
pub fn intersect_ray(ray: &Ray, tri: (Point, Point, Point)) -> Option<(f32, f32, f32, f32)> {
|
||||||
// Calculate the permuted dimension indices for the new ray space.
|
// Calculate the permuted dimension indices for the new ray space.
|
||||||
let zi = {
|
let (xi, yi, zi) = {
|
||||||
let xabs = ray.dir.x().abs();
|
let xabs = ray.dir.x().abs();
|
||||||
let yabs = ray.dir.y().abs();
|
let yabs = ray.dir.y().abs();
|
||||||
let zabs = ray.dir.z().abs();
|
let zabs = ray.dir.z().abs();
|
||||||
|
|
||||||
if xabs > yabs && xabs > zabs {
|
if xabs > yabs && xabs > zabs {
|
||||||
0
|
(1, 2, 0)
|
||||||
} else if yabs > zabs {
|
} else if yabs > zabs {
|
||||||
1
|
(2, 0, 1)
|
||||||
} else {
|
} else {
|
||||||
2
|
(0, 1, 2)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let (xi, yi) = if ray.dir.get_n(zi) >= 0.0 {
|
|
||||||
let xi = if zi == 2 { 0 } else { zi + 1 };
|
|
||||||
let yi = if xi == 2 { 0 } else { xi + 1 };
|
|
||||||
(xi, yi)
|
|
||||||
} else {
|
|
||||||
let xi = if zi == 2 { 0 } else { zi + 1 };
|
|
||||||
let yi = if xi == 2 { 0 } else { xi + 1 };
|
|
||||||
(yi, xi)
|
|
||||||
};
|
|
||||||
|
|
||||||
let dir_x = ray.dir.get_n(xi);
|
let dir_x = ray.dir.get_n(xi);
|
||||||
let dir_y = ray.dir.get_n(yi);
|
let dir_y = ray.dir.get_n(yi);
|
||||||
|
@ -54,29 +45,23 @@ pub fn intersect_ray(ray: &Ray, tri: (Point, Point, Point)) -> Option<(f32, f32,
|
||||||
let p1 = tri.1 - ray.orig;
|
let p1 = tri.1 - ray.orig;
|
||||||
let p2 = tri.2 - ray.orig;
|
let p2 = tri.2 - ray.orig;
|
||||||
|
|
||||||
let p0x = p0.get_n(xi) - sx * p0.get_n(zi);
|
let p0x = p0.get_n(xi) - (sx * p0.get_n(zi));
|
||||||
let p0y = p0.get_n(yi) - sy * p0.get_n(zi);
|
let p0y = p0.get_n(yi) - (sy * p0.get_n(zi));
|
||||||
let p1x = p1.get_n(xi) - sx * p1.get_n(zi);
|
let p1x = p1.get_n(xi) - (sx * p1.get_n(zi));
|
||||||
let p1y = p1.get_n(yi) - sy * p1.get_n(zi);
|
let p1y = p1.get_n(yi) - (sy * p1.get_n(zi));
|
||||||
let p2x = p2.get_n(xi) - sx * p2.get_n(zi);
|
let p2x = p2.get_n(xi) - (sx * p2.get_n(zi));
|
||||||
let p2y = p2.get_n(yi) - sy * p2.get_n(zi);
|
let p2y = p2.get_n(yi) - (sy * p2.get_n(zi));
|
||||||
|
|
||||||
// Calculate scaled barycentric coordinates.
|
// Calculate scaled barycentric coordinates.
|
||||||
let mut e0 = (p2x * p1y) - (p2y * p1x);
|
let mut e0 = (p1x * p2y) - (p1y * p2x);
|
||||||
let mut e1 = (p0x * p2y) - (p0y * p2x);
|
let mut e1 = (p2x * p0y) - (p2y * p0x);
|
||||||
let mut e2 = (p1x * p0y) - (p1y * p0x);
|
let mut e2 = (p0x * p1y) - (p0y * p1x);
|
||||||
|
|
||||||
// Fallback to test against edges using double precision.
|
// Fallback to test against edges using double precision.
|
||||||
if e0 == 0.0 || e1 == 0.0 || e2 == 0.0 {
|
if e0 == 0.0 || e1 == 0.0 || e2 == 0.0 {
|
||||||
let p2xp1y = p2x as f64 * p1y as f64;
|
e0 = ((p1x as f64 * p2y as f64) - (p1y as f64 * p2x as f64)) as f32;
|
||||||
let p2yp1x = p2y as f64 * p1x as f64;
|
e1 = ((p2x as f64 * p0y as f64) - (p2y as f64 * p0x as f64)) as f32;
|
||||||
e0 = (p2xp1y - p2yp1x) as f32;
|
e2 = ((p0x as f64 * p1y as f64) - (p0y as f64 * p1x as f64)) as f32;
|
||||||
let p0xp2y = p0x as f64 * p2y as f64;
|
|
||||||
let p0yp2x = p0y as f64 * p2x as f64;
|
|
||||||
e1 = (p0xp2y - p0yp2x) as f32;
|
|
||||||
let p1xp0y = p1x as f64 * p0y as f64;
|
|
||||||
let p1yp0x = p1y as f64 * p0x as f64;
|
|
||||||
e2 = (p1xp0y - p1yp0x) as f32;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the ray hit the triangle.
|
// Check if the ray hit the triangle.
|
||||||
|
@ -97,15 +82,11 @@ pub fn intersect_ray(ray: &Ray, tri: (Point, Point, Point)) -> Option<(f32, f32,
|
||||||
let t = (e0 * p0z) + (e1 * p1z) + (e2 * p2z);
|
let t = (e0 * p0z) + (e1 * p1z) + (e2 * p2z);
|
||||||
|
|
||||||
// Check if the hitpoint t is within ray min/max t.
|
// Check if the hitpoint t is within ray min/max t.
|
||||||
if det >= 0.0 {
|
if det > 0.0 && (t <= 0.0 || t > (ray.max_t * det)) {
|
||||||
if t <= 0.0 || t > (ray.max_t * det) {
|
|
||||||
return None;
|
return None;
|
||||||
}
|
} else if det < 0.0 && (t >= 0.0 || t < (ray.max_t * det)) {
|
||||||
} else {
|
|
||||||
if -t <= 0.0 || -t > (ray.max_t * -det) {
|
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Return t and the hitpoint barycentric coordinates.
|
// Return t and the hitpoint barycentric coordinates.
|
||||||
let inv_det = 1.0 / det;
|
let inv_det = 1.0 / det;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user