Reworked ray-sphere intersection which was failing tests
This commit is contained in:
parent
d9af6dad94
commit
700de75337
|
|
@ -128,6 +128,7 @@ mod tests {
|
||||||
Some(IntersectionInfo {
|
Some(IntersectionInfo {
|
||||||
location,
|
location,
|
||||||
distance: _,
|
distance: _,
|
||||||
|
normal: _,
|
||||||
}) => location,
|
}) => location,
|
||||||
None => panic!(),
|
None => panic!(),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -45,23 +45,26 @@ impl<T: RealField> Intersect<T> for Sphere<T> {
|
||||||
fn intersect(&self, ray: &Ray<T>) -> Option<IntersectionInfo<T>> {
|
fn intersect(&self, ray: &Ray<T>) -> Option<IntersectionInfo<T>> {
|
||||||
// t0/p0 is the point on the ray that's closest to the centre of the sphere
|
// 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);
|
let t0 = (self.centre - ray.origin).dot(&ray.direction);
|
||||||
let delta_squared =
|
if t0 < T::zero() {
|
||||||
t0 * t0 - ((ray.origin - self.centre).norm_squared() - self.radius * self.radius);
|
// Sphere is behind ray origin
|
||||||
if delta_squared > self.radius {
|
|
||||||
//No initersection
|
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let delta = delta_squared.sqrt();
|
let radius_squared = self.radius*self.radius;
|
||||||
let distance = if (self.centre - ray.origin).norm() <= 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
|
||||||
|
let p0_dist_from_centre_squared = d0_squared - t0*t0;
|
||||||
|
if p0_dist_from_centre_squared > radius_squared {
|
||||||
|
// Sphere is in front of ray but ray misses
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let delta = (radius_squared - p0_dist_from_centre_squared).sqrt();
|
||||||
|
let distance = if (self.centre - ray.origin).norm_squared() <= radius_squared {
|
||||||
// radius origin is inside sphere
|
// radius origin is inside sphere
|
||||||
t0 + delta
|
t0 + delta
|
||||||
} else {
|
} else {
|
||||||
t0 - delta
|
t0 - delta
|
||||||
};
|
};
|
||||||
if distance < T::zero() {
|
|
||||||
// Sphere is behind ray origin
|
|
||||||
return None;
|
|
||||||
};
|
|
||||||
let location = ray.point_at(distance);
|
let location = ray.point_at(distance);
|
||||||
let normal = (location - self.centre).normalize();
|
let normal = (location - self.centre).normalize();
|
||||||
Some(IntersectionInfo {
|
Some(IntersectionInfo {
|
||||||
|
|
@ -200,6 +203,7 @@ mod tests {
|
||||||
Some(IntersectionInfo {
|
Some(IntersectionInfo {
|
||||||
distance: _,
|
distance: _,
|
||||||
location,
|
location,
|
||||||
|
normal: _,
|
||||||
}) => assert!((location.x - (-5.0f64)).abs() < 0.0000000001),
|
}) => assert!((location.x - (-5.0f64)).abs() < 0.0000000001),
|
||||||
None => panic!(),
|
None => panic!(),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue