Merge pull request #9 from JeffBelgum/intersections
ray-plane and ray-sphere intersection
This commit is contained in:
commit
2e2a75e7ed
6 changed files with 75 additions and 4 deletions
|
@ -15,6 +15,7 @@
|
|||
|
||||
use std::cast::transmute;
|
||||
use std::fmt;
|
||||
use std::num::Zero;
|
||||
|
||||
use intersect::Intersect;
|
||||
use point::{Point, Point3};
|
||||
|
@ -22,6 +23,7 @@ use ray::Ray3;
|
|||
use vector::{Vec3, Vec4};
|
||||
use vector::{Vector, EuclideanVector};
|
||||
|
||||
|
||||
/// A 3-dimendional plane formed from the equation: `a*x + b*y + c*z - d = 0`.
|
||||
///
|
||||
/// # Fields
|
||||
|
@ -86,7 +88,14 @@ impl<S: Float> Plane<S> {
|
|||
|
||||
impl<S: Float> Intersect<Option<Point3<S>>> for (Plane<S>, Ray3<S>) {
|
||||
fn intersection(&self) -> Option<Point3<S>> {
|
||||
fail!("Not yet implemented");
|
||||
match *self {
|
||||
(ref p, ref r) =>
|
||||
{
|
||||
let t = -(p.d + r.origin.dot(&p.n)) / r.direction.dot(&p.n);
|
||||
if t < Zero::zero() { None }
|
||||
else { Some(r.origin.add_v(&r.direction.mul_s(t))) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ use vector::*;
|
|||
#[deriving(Eq, Zero, Clone)]
|
||||
pub struct Point2<S> { x: S, y: S }
|
||||
|
||||
/// A point in 2-dimensional space.
|
||||
/// A point in 3-dimensional space.
|
||||
#[deriving(Eq, Zero, Clone)]
|
||||
pub struct Point3<S> { x: S, y: S, z: S }
|
||||
|
||||
|
|
|
@ -15,10 +15,37 @@
|
|||
|
||||
//! Bounding sphere
|
||||
|
||||
use point::Point3;
|
||||
use intersect::Intersect;
|
||||
use point::{Point, Point3};
|
||||
use ray::Ray3;
|
||||
use vector::Vector;
|
||||
|
||||
use std::num::NumCast;
|
||||
use std::num;
|
||||
|
||||
fn cast<T: NumCast, U: NumCast>(n: T) -> U {
|
||||
num::cast(n).unwrap()
|
||||
}
|
||||
|
||||
#[deriving(Clone, Eq)]
|
||||
pub struct Sphere<S> {
|
||||
center: Point3<S>,
|
||||
radius: S,
|
||||
}
|
||||
|
||||
impl<S: Float> Intersect<Option<Point3<S>>> for (Sphere<S>, Ray3<S>) {
|
||||
fn intersection(&self) -> Option<Point3<S>> {
|
||||
match *self {
|
||||
(ref s, ref r) =>
|
||||
{
|
||||
let l = s.center.sub_p(&r.origin);
|
||||
let tca = l.dot(&r.direction);
|
||||
if tca < cast(0.0) { return None; }
|
||||
let d2 = l.dot(&l) - tca*tca;
|
||||
if (d2 > s.radius*s.radius) { return None; }
|
||||
let thc = num::sqrt(s.radius*s.radius - d2);
|
||||
Some(r.origin.add_v(&r.direction.mul_s(tca - thc)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
|
||||
use cgmath::plane::*;
|
||||
use cgmath::point::*;
|
||||
use cgmath::vector::*;
|
||||
use cgmath::ray::*;
|
||||
use cgmath::intersect::Intersect;
|
||||
|
||||
#[test]
|
||||
fn test_from_points() {
|
||||
|
@ -28,3 +31,16 @@ fn test_from_points() {
|
|||
Point3::new(0.0, 5.0, 5.0)),
|
||||
None); // The points are parallel
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ray_intersection() {
|
||||
let p0 = Plane::from_abcd(1f64, 0f64, 0f64, -7f64);
|
||||
let r0: Ray3<f64> = Ray::new(Point3::new(2f64, 3f64, 4f64), Vec3::new(1f64, 1f64, 1f64).normalize());
|
||||
assert_eq!((p0, r0).intersection(), Some(Point3::new(7f64, 8f64, 9f64)));
|
||||
|
||||
let p1 = Plane::from_points(Point3::new(5f64, 0f64, 5f64),
|
||||
Point3::new(5f64, 5f64, 5f64),
|
||||
Point3::new(5f64, 0f64, -1f64)).unwrap();
|
||||
let r1: Ray3<f64> = Ray::new(Point3::new(0f64, 0f64, 0f64), Vec3::new(-1f64, 0f64, 0f64).normalize());
|
||||
assert_eq!((p1, r1).intersection(), None); // r1 points away from p1
|
||||
}
|
||||
|
|
19
src/tests/sphere.rs
Normal file
19
src/tests/sphere.rs
Normal file
|
@ -0,0 +1,19 @@
|
|||
use cgmath::sphere::*;
|
||||
use cgmath::point::*;
|
||||
use cgmath::vector::*;
|
||||
use cgmath::ray::*;
|
||||
use cgmath::intersect::Intersect;
|
||||
use std::num;
|
||||
|
||||
#[test]
|
||||
fn test_intersection() {
|
||||
let sphere = Sphere {center: Point3::new(0f64,0f64,0f64), radius: 1f64};
|
||||
let r0: Ray3<f64> = Ray::new(Point3::new(0f64, 0f64, 5f64), Vec3::new(0f64, 0f64, -5f64).normalize());
|
||||
let r1: Ray3<f64> = Ray::new(Point3::new(num::cos(1f64), 0f64, 5f64), Vec3::new(0f64, 0f64, -5f64).normalize());
|
||||
let r2: Ray3<f64> = Ray::new(Point3::new(1f64, 0f64, 5f64), Vec3::new(0f64, 0f64, -5f64).normalize());
|
||||
let r3: Ray3<f64> = Ray::new(Point3::new(2f64, 0f64, 5f64), Vec3::new(0f64, 0f64, -5f64).normalize());
|
||||
assert_eq!((sphere,r0).intersection(), Some(Point3::new(0f64, 0f64, 1f64)));
|
||||
assert_approx_eq!((sphere,r1).intersection().unwrap(), Point3::new(num::cos(1f64), 0f64, num::sin(1f64)));
|
||||
assert_eq!((sphere,r2).intersection(), Some(Point3::new(1f64, 0f64, 0f64)));
|
||||
assert_eq!((sphere,r3).intersection(), None);
|
||||
}
|
|
@ -37,4 +37,4 @@ pub mod transform;
|
|||
// pub mod frustum;
|
||||
// pub mod intersect;
|
||||
// pub mod obb;
|
||||
// pub mod sphere;
|
||||
pub mod sphere;
|
||||
|
|
Loading…
Reference in a new issue