Add frustum constructors and use to implement Projection->Frustum conversions

This commit is contained in:
Brendan Zabarauskas 2013-09-19 14:52:40 +10:00
parent 8c17832bf8
commit 279aa261a8
3 changed files with 50 additions and 4 deletions

View file

@ -15,8 +15,10 @@
//! View frustum for visibility determination //! View frustum for visibility determination
use matrix::{Matrix, Mat4};
use plane::Plane; use plane::Plane;
use point::Point3; use point::Point3;
use vector::{Vector, EuclideanVector};
#[deriving(Clone, Eq)] #[deriving(Clone, Eq)]
pub struct Frustum<S> { pub struct Frustum<S> {
@ -28,6 +30,32 @@ pub struct Frustum<S> {
far: Plane<S>, far: Plane<S>,
} }
impl<S: Float> Frustum<S> {
/// Constructs a frustum
pub fn new(left: Plane<S>, right: Plane<S>,
bottom: Plane<S>, top: Plane<S>,
near: Plane<S>, far: Plane<S>) -> Frustum<S> {
Frustum {
left: left,
right: right,
bottom: bottom,
top: top,
near: near,
far: far,
}
}
/// Extracts frustum planes from a projection matrix
pub fn from_mat4(mat: Mat4<S>) -> Frustum<S> {
Frustum::new(Plane::from_vec4(mat.r(3).add_v(&mat.r(0)).normalize()),
Plane::from_vec4(mat.r(3).sub_v(&mat.r(0)).normalize()),
Plane::from_vec4(mat.r(3).add_v(&mat.r(1)).normalize()),
Plane::from_vec4(mat.r(3).sub_v(&mat.r(1)).normalize()),
Plane::from_vec4(mat.r(3).add_v(&mat.r(2)).normalize()),
Plane::from_vec4(mat.r(3).sub_v(&mat.r(2)).normalize()))
}
}
#[deriving(Clone, Eq)] #[deriving(Clone, Eq)]
pub struct FrustumPoints<S> { pub struct FrustumPoints<S> {
near_top_left: Point3<S>, near_top_left: Point3<S>,

View file

@ -13,10 +13,13 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use std::cast::transmute;
use intersect::Intersect; use intersect::Intersect;
use point::{Point, Point3}; use point::{Point, Point3};
use ray::Ray3; use ray::Ray3;
use vector::{Vector, EuclideanVector, Vec3}; use vector::{Vec3, Vec4};
use vector::{Vector, EuclideanVector};
use std::fmt; use std::fmt;
@ -57,6 +60,11 @@ impl<S: Float> Plane<S> {
Plane { n: Vec3::new(a, b, c), d: d } Plane { n: Vec3::new(a, b, c), d: d }
} }
/// Construct a plane from the components of a four-dimensional vector
pub fn from_vec4(v: Vec4<S>) -> Plane<S> {
unsafe { transmute(v) }
}
/// Constructs a plane that passes through the the three points `a`, `b` and `c` /// Constructs a plane that passes through the the three points `a`, `b` and `c`
pub fn from_points(a: Point3<S>, b: Point3<S>, c: Point3<S>) -> Option<Plane<S>> { pub fn from_points(a: Point3<S>, b: Point3<S>, c: Point3<S>) -> Option<Plane<S>> {
// create two vectors that run parallel to the plane // create two vectors that run parallel to the plane

View file

@ -18,6 +18,7 @@ use std::num::{zero, one, cast};
use angle::{Angle, tan, cot}; use angle::{Angle, tan, cot};
use frustum::Frustum; use frustum::Frustum;
use matrix::{Mat4, ToMat4}; use matrix::{Mat4, ToMat4};
use plane::Plane;
/// Create a perspective projection matrix. /// Create a perspective projection matrix.
/// ///
@ -94,7 +95,8 @@ impl<S: Float, A: Angle<S>> PerspectiveFov<S, A> {
impl<S: Float, A: Angle<S>> Projection<S> for PerspectiveFov<S, A> { impl<S: Float, A: Angle<S>> Projection<S> for PerspectiveFov<S, A> {
fn to_frustum(&self) -> Frustum<S> { fn to_frustum(&self) -> Frustum<S> {
self.to_perspective().to_frustum() // TODO: Could this be faster?
Frustum::from_mat4(self.to_mat4())
} }
} }
@ -148,7 +150,8 @@ pub struct Perspective<S> {
impl<S: Float> Projection<S> for Perspective<S> { impl<S: Float> Projection<S> for Perspective<S> {
fn to_frustum(&self) -> Frustum<S> { fn to_frustum(&self) -> Frustum<S> {
fail!("Not yet implemented!"); // TODO: Could this be faster?
Frustum::from_mat4(self.to_mat4())
} }
} }
@ -195,7 +198,14 @@ pub struct Ortho<S> {
impl<S: Float> Projection<S> for Ortho<S> { impl<S: Float> Projection<S> for Ortho<S> {
fn to_frustum(&self) -> Frustum<S> { fn to_frustum(&self) -> Frustum<S> {
fail!("Not yet implemented!"); Frustum {
left: Plane::from_abcd( one::<S>(), zero::<S>(), zero::<S>(), self.left.clone()),
right: Plane::from_abcd(-one::<S>(), zero::<S>(), zero::<S>(), self.right.clone()),
bottom: Plane::from_abcd(zero::<S>(), one::<S>(), zero::<S>(), self.bottom.clone()),
top: Plane::from_abcd(zero::<S>(), -one::<S>(), zero::<S>(), self.top.clone()),
near: Plane::from_abcd(zero::<S>(), zero::<S>(), -one::<S>(), self.near.clone()),
far: Plane::from_abcd(zero::<S>(), zero::<S>(), one::<S>(), self.far.clone()),
}
} }
} }