From eb75d34636aa14cbb6bc5d52322f5b0a00687ce9 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Fri, 12 Jul 2013 13:41:03 +1000 Subject: [PATCH] Add vector conversion traits --- src/core/core.rs | 4 ++- src/core/vec.rs | 48 +++++++++++++++++++++++++++ src/geom/aabb.rs | 10 ++---- src/geom/plane.rs | 6 ++-- src/geom/point.rs | 82 +++++++++++++++++++++++++++++------------------ 5 files changed, 108 insertions(+), 42 deletions(-) diff --git a/src/core/core.rs b/src/core/core.rs index 846525f..9dfe04f 100644 --- a/src/core/core.rs +++ b/src/core/core.rs @@ -20,7 +20,9 @@ pub use self::swap::Swap; pub use self::mat::{Mat2, ToMat2, Mat3, ToMat3, Mat4, ToMat4}; pub use self::quat::{Quat, ToQuat}; -pub use self::vec::{Vec2, Vec3, Vec4}; +pub use self::vec::{Vec2, ToVec2, AsVec2}; +pub use self::vec::{Vec3, ToVec3, AsVec3}; +pub use self::vec::{Vec4, ToVec4, AsVec4}; pub mod dim; pub mod swap; diff --git a/src/core/vec.rs b/src/core/vec.rs index f3c69a2..9f060cb 100644 --- a/src/core/vec.rs +++ b/src/core/vec.rs @@ -46,6 +46,15 @@ pub type Vec2u32 = Vec2; pub type Vec2u64 = Vec2; pub type Vec2b = Vec2; +pub trait ToVec2 { + pub fn to_vec2(&self) -> Vec2; +} + +pub trait AsVec2 { + pub fn as_vec2<'a>(&'a self) -> &'a Vec2; + pub fn as_mut_vec2<'a>(&'a mut self) -> &'a mut Vec2; +} + impl_approx!(Vec2 { x, y }) impl Vec2 { @@ -81,6 +90,16 @@ impl Vec2 { } } +impl ToVec3 for Vec2 { + /// Converts the vector to a three-dimensional homogeneous vector: + /// `[x, y] -> [x, y, 0]` + pub fn to_vec3(&self) -> Vec3 { + Vec3::new((*self).index(0).clone(), + (*self).index(1).clone(), + zero!(T)) + } +} + impl Vec2 { #[inline] pub fn identity() -> Vec2 { @@ -567,6 +586,15 @@ pub type Vec3u32 = Vec3; pub type Vec3u64 = Vec3; pub type Vec3b = Vec3; +pub trait ToVec3 { + pub fn to_vec3(&self) -> Vec3; +} + +pub trait AsVec3 { + pub fn as_vec3<'a>(&'a self) -> &'a Vec3; + pub fn as_mut_vec3<'a>(&'a mut self) -> &'a mut Vec3; +} + impl_approx!(Vec3 { x, y, z }) impl Vec3 { @@ -603,6 +631,17 @@ impl Vec3 { } } +impl ToVec4 for Vec3 { + /// Converts the vector to a four-dimensional homogeneous vector: + /// `[x, y, z] -> [x, y, z, 0]` + pub fn to_vec4(&self) -> Vec4 { + Vec4::new((*self).index(0).clone(), + (*self).index(1).clone(), + (*self).index(2).clone(), + zero!(T)) + } +} + impl Vec3 { #[inline] pub fn identity() -> Vec3 { @@ -1152,6 +1191,15 @@ pub type Vec4u32 = Vec4; pub type Vec4u64 = Vec4; pub type Vec4b = Vec4; +pub trait ToVec4 { + pub fn to_vec4(&self) -> Vec4; +} + +pub trait AsVec4 { + pub fn as_vec4<'a>(&'a self) -> &'a Vec4; + pub fn as_mut_vec4<'a>(&'a mut self) -> &'a mut Vec4; +} + impl_approx!(Vec4 { x, y, z, w }) impl Vec4 { diff --git a/src/geom/aabb.rs b/src/geom/aabb.rs index a02a8fc..1088854 100644 --- a/src/geom/aabb.rs +++ b/src/geom/aabb.rs @@ -15,7 +15,7 @@ //! Axis-aligned bounding boxes -use core::{Vec2, Vec3}; +use core::{Vec2, AsVec2, Vec3, AsVec3}; use geom::{Point2, Point3}; pub struct AABB2 { @@ -36,9 +36,7 @@ impl AABB2 { #[inline] pub fn from_bounds(mn: Point2, mx: Point2) -> AABB2 { AABB2 { - center: Point2::from_vec(mn.as_vec() - .add_v(mx.as_vec()) - .div_t(two!(T))), + center: Point2::from_vec2(mn.as_vec2().add_v(mx.as_vec2()).div_t(two!(T))), size: mx - mn, } } @@ -62,9 +60,7 @@ impl AABB3 { #[inline] pub fn from_bounds(mn: Point3, mx: Point3) -> AABB3 { AABB3 { - center: Point3::from_vec(mn.as_vec() - .add_v(mx.as_vec()) - .div_t(two!(T))), + center: Point3::from_vec3(mn.as_vec3().add_v(mx.as_vec3()).div_t(two!(T))), size: mx - mn, } } diff --git a/src/geom/plane.rs b/src/geom/plane.rs index 3849710..6405121 100644 --- a/src/geom/plane.rs +++ b/src/geom/plane.rs @@ -13,7 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use core::{Vec3, Vec4, Mat3}; +use core::{Vec3, AsVec3, Vec4, Mat3}; use geom::{Point, Point3, Ray3}; /// A plane formed from the equation: `Ax + Bx + Cx + D = 0` @@ -59,7 +59,7 @@ impl Plane3 { /// Compute the distance from the plane to the point pub fn distance(&self, pos: &Point3) -> T { - self.normal.dot(pos.as_vec()) + self.distance + self.normal.dot(pos.as_vec3()) + self.distance } /// Computes the point at which `ray` intersects the plane @@ -94,7 +94,7 @@ impl Plane3 { } else { // compute the normal and the distance to the plane normal.normalize_self(); - let distance = -a.as_vec().dot(&normal); + let distance = -a.as_vec3().dot(&normal); Some(Plane3::from_nd(normal, distance)) } diff --git a/src/geom/point.rs b/src/geom/point.rs index 1c84d07..d2dcfa2 100644 --- a/src/geom/point.rs +++ b/src/geom/point.rs @@ -22,7 +22,10 @@ use std::cast; -use core::{Mat2, Mat3, Quat, Vec2, Vec3, Vec4}; +use core::{Mat2, Mat3, Quat}; +use core::{Vec2, ToVec2, AsVec2}; +use core::{Vec3, ToVec3, AsVec3}; +use core::{Vec4, ToVec4}; /// A geometric point pub trait Point: Eq @@ -31,9 +34,6 @@ pub trait Point: Eq + Mul + ApproxEq + ToStr { - pub fn as_vec<'a>(&'a self) -> &'a Vec; - pub fn as_mut_vec<'a>(&'a mut self) -> &'a mut Vec; - pub fn translate(&self, offset: &Vec) -> Self; pub fn scale(&self, factor: &Vec) -> Self; pub fn distance2(&self, other: &Self) -> T; @@ -54,7 +54,7 @@ impl Point2 { } #[inline] - pub fn from_vec(vec: Vec2) -> Point2 { + pub fn from_vec2(vec: Vec2) -> Point2 { unsafe { cast::transmute(vec) } } @@ -64,7 +64,26 @@ impl Point2 { } } -impl Point2 { +impl ToVec2 for Point2 { + #[inline] + pub fn to_vec2(&self) -> Vec2 { + self.as_vec2().clone() + } +} + +impl AsVec2 for Point2 { + #[inline] + pub fn as_vec2<'a>(&'a self) -> &'a Vec2 { + unsafe { cast::transmute(self) } + } + + #[inline] + pub fn as_mut_vec2<'a>(&'a mut self) -> &'a mut Vec2 { + unsafe { cast::transmute(self) } + } +} + +impl ToVec3 for Point2 { /// Converts the point to a three-dimensional homogeneous vector: /// `[x, y] -> [x, y, 1]` #[inline] @@ -84,21 +103,11 @@ impl Point2 { #[inline] pub fn rotate_m(&self, mat: &Mat2) -> Point2 { - Point2::from_vec(mat.mul_v(self.as_vec())) + Point2::from_vec2(mat.mul_v(self.as_vec2())) } } impl Point> for Point2 { - #[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 { (*self) + (*offset) @@ -177,7 +186,7 @@ impl Point3 { } #[inline] - pub fn from_vec(vec: Vec3) -> Point3 { + pub fn from_vec3(vec: Vec3) -> Point3 { unsafe { cast::transmute(vec) } } @@ -187,7 +196,28 @@ impl Point3 { } } -impl Point3 { +impl ToVec3 for Point3 { + /// Converts the point to a three-dimensional homogeneous vector: + /// `[x, y] -> [x, y, 1]` + #[inline] + pub fn to_vec3(&self) -> Vec3 { + self.as_vec3().clone() + } +} + +impl AsVec3 for Point3 { + #[inline] + pub fn as_vec3<'a>(&'a self) -> &'a Vec3 { + unsafe { cast::transmute(self) } + } + + #[inline] + pub fn as_mut_vec3<'a>(&'a mut self) -> &'a mut Vec3 { + unsafe { cast::transmute(self) } + } +} + +impl ToVec4 for Point3 { /// Converts the point to a four-dimensional homogeneous vector: /// `[x, y, z] -> [x, y, z, 1]` #[inline] @@ -202,26 +232,16 @@ impl Point3 { impl Point3 { #[inline] pub fn rotate_q(&self, quat: &Quat) -> Point3 { - Point3::from_vec(quat.mul_v(self.as_vec())) + Point3::from_vec3(quat.mul_v(self.as_vec3())) } #[inline] pub fn rotate_m(&self, mat: &Mat3) -> Point3 { - Point3::from_vec(mat.mul_v(self.as_vec())) + Point3::from_vec3(mat.mul_v(self.as_vec3())) } } impl Point> for Point3 { - #[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 { (*self) + (*offset)