From 777580be17fc4340c204bf8fd7a0d58dc713eb9d Mon Sep 17 00:00:00 2001 From: Matthew Gordon Date: Thu, 12 Dec 2019 08:57:46 -0500 Subject: [PATCH] Fix triangle intersection passing when triangle is behind ray --- src/mesh.rs | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/mesh.rs b/src/mesh.rs index e2b94bc..c50c152 100644 --- a/src/mesh.rs +++ b/src/mesh.rs @@ -34,10 +34,18 @@ impl Intersect for Triangle { let barycentric_coordinates = barycentric_coordinates_from_signed_edge_functions( Vector3::from_iterator(edge_functions.iter().map(|e| e.abs())), ); + let transformed_z = barycentric_coordinates + .iter() + .zip(transformed_vertices.iter()) + .map(|(&coord, vertex)| vertex.z * coord) + .fold(T::zero(), |acc, z| acc + z); + if transformed_z.is_positive() != permuted_ray_direction.z.is_positive() { + return None; + } let location: Point3 = barycentric_coordinates .iter() .zip(self.vertices.iter()) - .map(|(&coord, vertex)| vertex.coords * coord) + .map(|(&barycentric_coord, vertex)| vertex.coords * barycentric_coord) .fold(Point3::new(T::zero(), T::zero(), T::zero()), |a, e| a + e); let distance = (ray.origin - location).norm(); let normal: Vector3 = barycentric_coordinates @@ -787,5 +795,31 @@ mod tests { None => true, } } + + #[quickcheck] + fn intersection_fails_when_triangle_is_behind_ray( + vertex0: Point3, + vertex1: Point3, + vertex2: Point3, + ray_origin: Point3, + barycentric_coords: BarycentricCoords, + ) -> bool { + let point_behind_ray = vertex0.coords * barycentric_coords.alpha + + vertex1.coords * barycentric_coords.beta + + vertex2.coords * barycentric_coords.gamma; + let ray = Ray { + origin: ray_origin, + direction: (ray_origin.coords - point_behind_ray).normalize(), + }; + let triangle = Triangle { + vertices: [vertex0, vertex1, vertex2], + normals: [Vector3::zeros(); 3], + material: Rc::new(LambertianMaterial::new_dummy()), + }; + match triangle.intersect(&ray) { + Some(_) => false, + None => true, + } + } } }