Add Ray2<>Aabb2 intersection impl

This commit is contained in:
Brandon Waskiewicz 2014-05-29 23:42:23 -04:00
parent 814b845de7
commit 4f17d73f23
2 changed files with 63 additions and 2 deletions

View file

@ -22,9 +22,11 @@
use point::{Point, Point2, Point3};
use vector::{Vector, Vector2, Vector3};
use num::BaseNum;
use ray::{Ray2};
use intersect::Intersect;
use num::{BaseNum, BaseFloat};
use std::fmt;
use std::num::{zero, one};
use std::num::{zero, one, Float};
pub trait Aabb<S: BaseNum, V: Vector<S>, P: Point<S, V>> {
/// Create a new AABB using two points as opposing corners.
@ -172,3 +174,46 @@ impl<S: BaseNum> fmt::Show for Aabb3<S> {
write!(f, "[{} - {}]", self.min, self.max)
}
}
impl<S: BaseFloat> Intersect<Option<Point2<S>>> for (Ray2<S>, Aabb2<S>) {
fn intersection(&self) -> Option<Point2<S>> {
match *self {
(ref ray, ref aabb) => {
let mut tmin: S = Float::neg_infinity();
let mut tmax: S = Float::infinity();
if ray.direction.x != zero() {
let tx1 = (aabb.min.x - ray.origin.x) / ray.direction.x;
let tx2 = (aabb.max.x - ray.origin.x) / ray.direction.x;
tmin = tmin.max(tx1.min(tx2));
tmax = tmax.min(tx1.max(tx2));
}
if ray.direction.y != zero() {
let ty1 = (aabb.min.y - ray.origin.y) / ray.direction.y;
let ty2 = (aabb.max.y - ray.origin.y) / ray.direction.y;
tmin = tmin.max(ty1.min(ty2));
tmax = tmax.min(ty1.max(ty2));
}
if tmin < zero() && tmax < zero() {
None
}
else if tmax >= tmin {
if tmin >= zero() {
Some(Point2::new(ray.origin.x + ray.direction.x * tmin,
ray.origin.y + ray.direction.y * tmin))
}
else {
Some(Point2::new(ray.origin.x + ray.direction.x * tmax,
ray.origin.y + ray.direction.y * tmax))
}
}
else {
None
}
}
}
}
}

View file

@ -20,6 +20,8 @@ extern crate cgmath;
use cgmath::aabb::*;
use cgmath::point::{Point2, Point3};
use cgmath::vector::{Vector2, Vector3};
use cgmath::ray::{Ray};
use cgmath::intersect::Intersect;
#[test]
fn test_aabb() {
@ -64,3 +66,17 @@ fn test_aabb() {
assert_eq!(aabb.mul_v(&Vector3::new(1i, 2i, 3i)),
Aabb3::new(Point3::new(-20i, -20i, -15i), Point3::new(10i, 60i, 15i)));
}
#[test]
fn test_aabb_ray_intersect() {
let aabb = Aabb2::new(Point2::new(-5.0f32, 5.0), Point2::new(5.0, 10.0));
let ray1 = Ray::new(Point2::new(0.0f32, 0.0), Vector2::new(0.0, 1.0));
let ray2 = Ray::new(Point2::new(-10.0f32, 0.0), Vector2::new(2.5, 1.0));
let ray3 = Ray::new(Point2::new(0.0f32, 0.0), Vector2::new(-1.0, -1.0));
let ray4 = Ray::new(Point2::new(3.0f32, 7.0), Vector2::new(1.0, 1.0));
assert_eq!((ray1, aabb).intersection(), Some(Point2::new(0.0, 5.0)));
assert_eq!((ray2, aabb).intersection(), Some(Point2::new(2.5, 5.0)));
assert_eq!((ray3, aabb).intersection(), None);
assert_eq!((ray4, aabb).intersection(), Some(Point2::new(5.0, 9.0)));
}