Add Plane struct
This commit is contained in:
parent
10c8992cf4
commit
041c940931
|
|
@ -1,4 +1,4 @@
|
||||||
use nalgebra::{RealField, Vector3};
|
use nalgebra::{convert, RealField, Vector3};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Ray<T: RealField> {
|
pub struct Ray<T: RealField> {
|
||||||
|
|
@ -56,6 +56,45 @@ impl<T: RealField> Intersect<T> for Sphere<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Plane<T: RealField> {
|
||||||
|
normal: Vector3<T>,
|
||||||
|
distance_from_origin: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: RealField> Plane<T> {
|
||||||
|
pub fn new(normal: Vector3<T>, distance_from_origin: T) -> Plane<T> {
|
||||||
|
normal.normalize();
|
||||||
|
Plane {
|
||||||
|
normal,
|
||||||
|
distance_from_origin,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: RealField> Intersect<T> for Plane<T> {
|
||||||
|
fn intersect(&self, ray: &Ray<T>) -> Option<IntersectionInfo<T>> {
|
||||||
|
let ray_direction_dot_plane_normal = ray.direction.dot(&self.normal);
|
||||||
|
let point_on_plane = self.normal * self.distance_from_origin;
|
||||||
|
let point_on_plane_minus_ray_origin_dot_normal =
|
||||||
|
(point_on_plane - ray.origin).dot(&self.normal);
|
||||||
|
if ray_direction_dot_plane_normal == convert(0.0) {
|
||||||
|
//Ray is parallel to plane
|
||||||
|
if point_on_plane_minus_ray_origin_dot_normal != convert(0.0) {
|
||||||
|
//Ray is not in plane
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let t = point_on_plane_minus_ray_origin_dot_normal / ray_direction_dot_plane_normal;
|
||||||
|
if t < convert(0.0) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some(IntersectionInfo {
|
||||||
|
distance: t,
|
||||||
|
location: ray.point_at(t),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use quickcheck_macros::quickcheck;
|
use quickcheck_macros::quickcheck;
|
||||||
|
|
@ -121,4 +160,30 @@ mod tests {
|
||||||
let s = Sphere::new(Vector3::new(-5.0, 1.5, 15.0), 5.0);
|
let s = Sphere::new(Vector3::new(-5.0, 1.5, 15.0), 5.0);
|
||||||
assert_matches!(s.intersect(&r), None);
|
assert_matches!(s.intersect(&r), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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));
|
||||||
|
let p = Plane::new(Vector3::new(1.0, 0.0, 0.0), -5.0);
|
||||||
|
assert_matches!(p.intersect(&r), Some(_));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ray_does_not_intersect_plane() {
|
||||||
|
let r = Ray::new(Vector3::new(1.0, 2.0, 3.0), Vector3::new(1.0, 0.0, 1.0));
|
||||||
|
let p = Plane::new(Vector3::new(1.0, 0.0, 0.0), -5.0);
|
||||||
|
assert_matches!(p.intersect(&r), None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn intersection_point_is_on_plane() {
|
||||||
|
let r = Ray::new(Vector3::new(1.0, 2.0, 3.0), Vector3::new(-1.0, 0.0, 1.0));
|
||||||
|
let p = Plane::new(Vector3::new(1.0, 0.0, 0.0), -5.0);
|
||||||
|
match p.intersect(&r) {
|
||||||
|
Some(IntersectionInfo { distance, location }) => {
|
||||||
|
assert!((location.x - (-5.0f64)).abs() < 0.0000000001)
|
||||||
|
}
|
||||||
|
None => panic!()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue