Fix failed intersection when ray origin is insode sphere
Added unit test which detected a false miss when the sphere centre is behind the ray origin but the ray origin is inside the sphere.
This commit is contained in:
parent
3c24a084b9
commit
c144780fce
|
|
@ -43,13 +43,15 @@ impl<T: RealField> Sphere<T> {
|
|||
|
||||
impl<T: RealField> Intersect<T> for Sphere<T> {
|
||||
fn intersect(&self, ray: &Ray<T>) -> Option<IntersectionInfo<T>> {
|
||||
let ray_origin_to_sphere_centre = self.centre - ray.origin;
|
||||
let radius_squared = self.radius * self.radius;
|
||||
let is_inside_sphere = ray_origin_to_sphere_centre.norm_squared() <= radius_squared;
|
||||
// t0/p0 is the point on the ray that's closest to the centre of the sphere
|
||||
let t0 = (self.centre - ray.origin).dot(&ray.direction);
|
||||
if t0 < T::zero() {
|
||||
let t0 = ray_origin_to_sphere_centre.dot(&ray.direction);
|
||||
if !is_inside_sphere && t0 < T::zero() {
|
||||
// Sphere is behind ray origin
|
||||
return None;
|
||||
}
|
||||
let radius_squared = self.radius*self.radius;
|
||||
// Squared distance between ray origin and sphere centre
|
||||
let d0_squared = (ray.origin - self.centre).norm_squared();
|
||||
// Squared distance petween p0 and sphere centre
|
||||
|
|
@ -59,7 +61,7 @@ impl<T: RealField> Intersect<T> for Sphere<T> {
|
|||
return None;
|
||||
}
|
||||
let delta = (radius_squared - p0_dist_from_centre_squared).sqrt();
|
||||
let distance = if (self.centre - ray.origin).norm_squared() <= radius_squared {
|
||||
let distance = if is_inside_sphere {
|
||||
// radius origin is inside sphere
|
||||
t0 + delta
|
||||
} else {
|
||||
|
|
@ -188,6 +190,13 @@ mod tests {
|
|||
assert_matches!(s.intersect(&r), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ray_intersects_sphere_when_origin_is_inside() {
|
||||
let r = Ray::new(Vector3::new(1.0, 2.0, 3.0), Vector3::new(0.0, 0.0, 1.0));
|
||||
let s = Sphere::new(Vector3::new(1.5, 1.5, 2.0), 5.0);
|
||||
assert_matches!(s.intersect(&r), Some(_));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ray_intersects_plane() {
|
||||
let r = Ray::new(Vector3::new(1.0, 2.0, 3.0), Vector3::new(-1.0, 0.0, 1.0));
|
||||
|
|
|
|||
Loading…
Reference in New Issue