diff --git a/src/cgmath/frustum.rs b/src/cgmath/frustum.rs index 4268347..4593f56 100644 --- a/src/cgmath/frustum.rs +++ b/src/cgmath/frustum.rs @@ -15,8 +15,10 @@ //! View frustum for visibility determination +use matrix::{Matrix, Mat4}; use plane::Plane; use point::Point3; +use vector::{Vector, EuclideanVector}; #[deriving(Clone, Eq)] pub struct Frustum { @@ -28,6 +30,32 @@ pub struct Frustum { far: Plane, } +impl Frustum { + /// Constructs a frustum + pub fn new(left: Plane, right: Plane, + bottom: Plane, top: Plane, + near: Plane, far: Plane) -> Frustum { + 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) -> Frustum { + 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)] pub struct FrustumPoints { near_top_left: Point3, diff --git a/src/cgmath/plane.rs b/src/cgmath/plane.rs index 4d3d3b1..85ee3a2 100644 --- a/src/cgmath/plane.rs +++ b/src/cgmath/plane.rs @@ -13,10 +13,13 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::cast::transmute; + use intersect::Intersect; use point::{Point, Point3}; use ray::Ray3; -use vector::{Vector, EuclideanVector, Vec3}; +use vector::{Vec3, Vec4}; +use vector::{Vector, EuclideanVector}; use std::fmt; @@ -57,6 +60,11 @@ impl Plane { 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) -> Plane { + unsafe { transmute(v) } + } + /// Constructs a plane that passes through the the three points `a`, `b` and `c` pub fn from_points(a: Point3, b: Point3, c: Point3) -> Option> { // create two vectors that run parallel to the plane diff --git a/src/cgmath/projection.rs b/src/cgmath/projection.rs index bb8d009..74dea98 100644 --- a/src/cgmath/projection.rs +++ b/src/cgmath/projection.rs @@ -18,6 +18,7 @@ use std::num::{zero, one, cast}; use angle::{Angle, tan, cot}; use frustum::Frustum; use matrix::{Mat4, ToMat4}; +use plane::Plane; /// Create a perspective projection matrix. /// @@ -94,7 +95,8 @@ impl> PerspectiveFov { impl> Projection for PerspectiveFov { fn to_frustum(&self) -> Frustum { - self.to_perspective().to_frustum() + // TODO: Could this be faster? + Frustum::from_mat4(self.to_mat4()) } } @@ -148,7 +150,8 @@ pub struct Perspective { impl Projection for Perspective { fn to_frustum(&self) -> Frustum { - fail!("Not yet implemented!"); + // TODO: Could this be faster? + Frustum::from_mat4(self.to_mat4()) } } @@ -195,7 +198,14 @@ pub struct Ortho { impl Projection for Ortho { fn to_frustum(&self) -> Frustum { - fail!("Not yet implemented!"); + Frustum { + left: Plane::from_abcd( one::(), zero::(), zero::(), self.left.clone()), + right: Plane::from_abcd(-one::(), zero::(), zero::(), self.right.clone()), + bottom: Plane::from_abcd(zero::(), one::(), zero::(), self.bottom.clone()), + top: Plane::from_abcd(zero::(), -one::(), zero::(), self.top.clone()), + near: Plane::from_abcd(zero::(), zero::(), -one::(), self.near.clone()), + far: Plane::from_abcd(zero::(), zero::(), one::(), self.far.clone()), + } } }