diff --git a/src/geom/geom.rs b/src/geom/geom.rs index f9874ff..ed9db33 100644 --- a/src/geom/geom.rs +++ b/src/geom/geom.rs @@ -14,7 +14,7 @@ // limitations under the License. pub use self::plane::Plane; -pub use self::point::{Point2, Point3}; +pub use self::point::{Point, Point2, Point3}; pub use self::ray::Ray3; pub mod plane; diff --git a/src/geom/plane.rs b/src/geom/plane.rs index 781ce8d..2691f44 100644 --- a/src/geom/plane.rs +++ b/src/geom/plane.rs @@ -14,7 +14,7 @@ // limitations under the License. use core::{Vec3, Vec4, Mat3}; -use geom::{Point3, Ray3}; +use geom::{Point, Point3, Ray3}; #[path = "../num_macros.rs"] mod num_macros; @@ -34,7 +34,7 @@ pub struct Plane { dist: T, } -impl Plane { +impl Plane { /// # Arguments /// /// - `a`: the `x` component of the normal @@ -60,7 +60,7 @@ impl Plane { /// Compute the distance from the plane to the point pub fn distance(&self, pos: &Point3) -> T { - self.norm.dot(&**pos) + self.dist + self.norm.dot(pos.as_vec()) + self.dist } /// Computes the point at which `ray` intersects the plane @@ -79,14 +79,14 @@ impl Plane { } } -impl> Plane { +impl Plane { /// Constructs a plane that passes through the the three points `a`, `b` and `c` pub fn from_3p(a: Point3, b: Point3, c: Point3) -> Option> { // create two vectors that run parallel to the plane - let v0 = (*b).sub_v(&*a); - let v1 = (*c).sub_v(&*a); + let v0 = b.as_vec().sub_v(a.as_vec()); + let v1 = c.as_vec().sub_v(a.as_vec()); // find the vector that is perpendicular to v1 and v2 let mut norm = v0.cross(&v1); @@ -95,7 +95,7 @@ impl> Plane { } else { // compute the normal and the distance to the plane norm.normalize_self(); - let dist = -a.dot(&norm); + let dist = -a.as_vec().dot(&norm); Some(Plane::from_nd(norm, dist)) } @@ -115,7 +115,7 @@ impl> Plane { } else { // The end-point of the ray is at the three-plane intersection between // `self`, `other`, and a tempory plane positioned at the origin - do Plane::from_nd(ray_dir.clone(), zero!(T)).intersection_3pl(self, other).map |ray_pos| { + do Plane::from_nd(ray_dir.clone(), zero!(T)).intersection_3pl(self, other).map |&ray_pos| { Ray3 { pos: ray_pos.clone(), dir: ray_dir.clone(), @@ -136,9 +136,11 @@ impl> Plane { self.norm.y.clone(), other_a.norm.y.clone(), other_b.norm.y.clone(), self.norm.z.clone(), other_a.norm.z.clone(), other_b.norm.z.clone()); do mx.inverse().map |m| { - Point3(m.mul_v(&Vec3::new(self.dist.clone(), - other_a.dist.clone(), - other_b.dist.clone()))) + Point::from_vec( + m.mul_v(&Vec3::new(self.dist.clone(), + other_a.dist.clone(), + other_b.dist.clone())) + ) } } } @@ -189,7 +191,7 @@ mod tests { let p1 = Plane::from_abcd(0.0, -1.0, 0.0, 2.0); let p2 = Plane::from_abcd(0.0, 0.0, 1.0, 1.0); - assert_eq!(p0.intersection_3pl(&p1, &p2).unwrap(), Point3::new(1.0, -2.0, 1.0)); + assert_eq!(p0.intersection_3pl(&p1, &p2), Some(Point3::new(1.0, -2.0, 1.0))); } #[test] diff --git a/src/geom/point.rs b/src/geom/point.rs index 6294dcd..160281f 100644 --- a/src/geom/point.rs +++ b/src/geom/point.rs @@ -13,31 +13,55 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::cast; + use core::{Vec2, Vec3}; /// A geometric point pub trait Point: Eq + ApproxEq + ToStr { + pub fn from_vec(vec: V) -> Self; + pub fn as_vec<'a>(&'a self) -> &'a V; + pub fn as_mut_vec<'a>(&'a mut self) -> &'a mut V; + pub fn translate(&self, offset: &V) -> Self; pub fn distance(&self, other: &Self) -> T; } /// A two-dimensional point #[deriving(Clone, Eq)] -pub struct Point2(Vec2); +pub struct Point2 { x: T, y: T } impl Point2 { + #[inline] pub fn new(x: T, y: T) -> Point2 { - Point2(Vec2::new(x, y)) + Point2 { x: x, y: y } } } -impl Point> for Point2 { - pub fn translate(&self, offset: &Vec2) -> Point2 { - Point2(self.add_v(offset)) +impl Point> for Point2 { + #[inline] + pub fn from_vec(vec: Vec2) -> Point2 { + unsafe { cast::transmute(vec) } } + #[inline] + pub fn as_vec<'a>(&'a self) -> &'a Vec2 { + unsafe { cast::transmute(self) } + } + + #[inline] + pub fn as_mut_vec<'a>(&'a mut self) -> &'a mut Vec2 { + unsafe { cast::transmute(self) } + } + + #[inline] + pub fn translate(&self, offset: &Vec2) -> Point2 { + Point::from_vec(self.as_vec().add_v(offset)) + } + + #[inline] pub fn distance(&self, other: &Point2) -> T { - (**self).distance(&**other) + self.as_vec().distance(other.as_vec()) } } @@ -54,7 +78,8 @@ impl> ApproxEq for Point2 { #[inline] pub fn approx_eq_eps(&self, other: &Point2, epsilon: &T) -> bool { - (**self).approx_eq_eps(&**other, epsilon) + self.x.approx_eq_eps(&other.x, epsilon) && + self.y.approx_eq_eps(&other.y, epsilon) } } @@ -76,21 +101,39 @@ mod test_point2 { /// A three-dimensional point #[deriving(Clone, Eq)] -pub struct Point3(Vec3); +pub struct Point3 { x: T, y: T, z: T } impl Point3 { + #[inline] pub fn new(x: T, y: T, z: T) -> Point3 { - Point3(Vec3::new(x, y, z)) + Point3 { x: x, y: y, z: z } } } -impl Point> for Point3 { - pub fn translate(&self, offset: &Vec3) -> Point3 { - Point3(self.add_v(offset)) +impl Point> for Point3 { + #[inline] + pub fn from_vec(vec: Vec3) -> Point3 { + unsafe { cast::transmute(vec) } } + #[inline] + pub fn as_vec<'a>(&'a self) -> &'a Vec3 { + unsafe { cast::transmute(self) } + } + + #[inline] + pub fn as_mut_vec<'a>(&'a mut self) -> &'a mut Vec3 { + unsafe { cast::transmute(self) } + } + + #[inline] + pub fn translate(&self, offset: &Vec3) -> Point3 { + Point::from_vec(self.as_vec().add_v(offset)) + } + + #[inline] pub fn distance(&self, other: &Point3) -> T { - (**self).distance(&**other) + self.as_vec().distance(other.as_vec()) } } @@ -107,7 +150,9 @@ impl> ApproxEq for Point3 { #[inline] pub fn approx_eq_eps(&self, other: &Point3, epsilon: &T) -> bool { - (**self).approx_eq_eps(&**other, epsilon) + self.x.approx_eq_eps(&other.x, epsilon) && + self.y.approx_eq_eps(&other.y, epsilon) && + self.z.approx_eq_eps(&other.z, epsilon) } } diff --git a/src/world/frustum.rs b/src/world/frustum.rs index 26e6ca1..2c1e4ef 100644 --- a/src/world/frustum.rs +++ b/src/world/frustum.rs @@ -41,7 +41,7 @@ pub struct FrustumPoints { far_bottom_right: Point3, } -impl Frustum { +impl Frustum { /// Constructs a frustum pub fn from_planes(left: Plane, right: Plane, bottom: Plane, top: Plane, @@ -80,7 +80,7 @@ impl Frustum { } } -impl> Frustum { +impl Frustum { /// Computes where the frustum planes intersect to form corners and returns /// a struct containing the eight resulting position vectors. pub fn to_points(&self) -> FrustumPoints { diff --git a/src/world/projection.rs b/src/world/projection.rs index d372324..c0f692f 100644 --- a/src/world/projection.rs +++ b/src/world/projection.rs @@ -28,7 +28,7 @@ mod num_macros; /// This is the equivalent of the gluPerspective function, the algorithm of which /// can be found [here](http://www.opengl.org/wiki/GluPerspective_code). /// -pub fn perspective(fovy: T, aspectRatio: T, near: T, far: T) -> Mat4 { +pub fn perspective(fovy: T, aspectRatio: T, near: T, far: T) -> Mat4 { let ymax = near * (fovy / two!(T)).to_radians().tan(); let xmax = ymax * aspectRatio; @@ -41,7 +41,7 @@ pub fn perspective(fovy: T, aspectRatio: T, near: T, far: T) -> /// This is the equivalent of the now deprecated [glFrustrum] /// (http://www.opengl.org/sdk/docs/man2/xhtml/glFrustum.xml) function. /// -pub fn frustum(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Mat4 { +pub fn frustum(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Mat4 { let c0r0 = (two!(T) * near) / (right - left); let c0r1 = zero!(T); let c0r2 = zero!(T); @@ -74,7 +74,7 @@ pub fn frustum(left: T, right: T, bottom: T, top: T, near: T, fa /// This is the equivalent of the now deprecated [glOrtho] /// (http://www.opengl.org/sdk/docs/man2/xhtml/glOrtho.xml) function. /// -pub fn ortho(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Mat4 { +pub fn ortho(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Mat4 { let c0r0 = two!(T) / (right - left); let c0r1 = zero!(T); let c0r2 = zero!(T); @@ -116,7 +116,7 @@ pub struct PerspectiveFOV { far: T, } -impl PerspectiveFOV { +impl PerspectiveFOV { pub fn to_perspective(&self) -> Result, ~str> { do self.if_valid { let angle = self.fovy / two!(T); @@ -135,7 +135,7 @@ impl PerspectiveFOV { } } -impl Projection for PerspectiveFOV { +impl Projection for PerspectiveFOV { pub fn if_valid(&self, f: &fn() -> U) -> Result { let frac_pi_2: T = Real::frac_pi_2(); cond! ( @@ -169,7 +169,7 @@ pub struct Perspective { far: T, } -impl Projection for Perspective { +impl Projection for Perspective { pub fn if_valid(&self, f: &fn() -> U) -> Result { cond! ( (self.left > self.right) { Err(fmt!("`left` cannot be greater than `right`, found: left: %? right: %?", self.left, self.right)) } @@ -275,7 +275,7 @@ pub struct Ortho { far: T, } -impl Projection for Ortho { +impl Projection for Ortho { pub fn if_valid(&self, f: &fn() -> U) -> Result { cond! ( (self.left > self.right) { Err(fmt!("`left` cannot be greater than `right`, found: left: %? right: %?", self.left, self.right)) }