diff --git a/src/lib.rs b/src/lib.rs index 9de11f7..3c391c0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,7 +22,7 @@ extern crate num as num_lib; pub use matrix::Matrix4; pub use matrix2d::Matrix2D; -pub use point::Point2D; +pub use point::{Point2D, Point3D}; pub use rect::Rect; pub use side_offsets::SideOffsets2D; pub use side_offsets::SideOffsets2DSimdI32; diff --git a/src/matrix.rs b/src/matrix.rs index 4641109..85ff4d2 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -8,7 +8,7 @@ // except according to those terms. use approxeq::ApproxEq; -use point::Point2D; +use point::{Point2D, Point3D}; pub fn Matrix4( m11: f32, m12: f32, m13: f32, m14: f32, @@ -84,6 +84,17 @@ impl Matrix4 { p.x * self.m12 + p.y * self.m22 + self.m42) } + /// Transform the 3d point, and perform perspective division. + #[inline] + pub fn transform_homogenous(&self, p: &Point3D) -> Point3D { + let x = p.x * self.m11 + p.y * self.m21 + p.z * self.m31 + self.m41; + let y = p.x * self.m12 + p.y * self.m22 + p.z * self.m32 + self.m42; + let z = p.x * self.m13 + p.y * self.m23 + p.z * self.m33 + self.m43; + let w = p.x * self.m14 + p.y * self.m24 + p.z * self.m34 + self.m44; + let inv_w = 1.0 / w; + Point3D::new(x * inv_w, y * inv_w, z * inv_w) + } + pub fn to_array(&self) -> [f32; 16] { [ self.m11, self.m12, self.m13, self.m14, diff --git a/src/point.rs b/src/point.rs index ea13515..13a626d 100644 --- a/src/point.rs +++ b/src/point.rs @@ -135,3 +135,62 @@ impl Point2D> { self.cast().unwrap() } } + +#[derive(Clone, Copy, RustcDecodable, RustcEncodable, Eq, Hash, PartialEq)] +pub struct Point3D { + pub x: T, + pub y: T, + pub z: T, +} + +impl Point3D { + #[inline] + pub fn zero() -> Point3D { + Point3D { x: Zero::zero(), y: Zero::zero(), z: Zero::zero() } + } +} + +impl fmt::Debug for Point3D { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "({:?},{:?},{:?})", self.x, self.y, self.z) + } +} + +impl fmt::Display for Point3D { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "({},{},{})", self.x, self.y, self.z) + } +} + +impl Point3D { + #[inline] + pub fn new(x: T, y: T, z: T) -> Point3D { + Point3D {x: x, y: y, z: z} + } +} + +impl> Add for Point3D { + type Output = Point3D; + fn add(self, other: Point3D) -> Point3D { + Point3D::new(self.x + other.x, + self.y + other.y, + self.z + other.z) + } +} + +impl> Sub for Point3D { + type Output = Point3D; + fn sub(self, other: Point3D) -> Point3D { + Point3D::new(self.x - other.x, + self.y - other.y, + self.z - other.z) + } +} + +impl > Neg for Point3D { + type Output = Point3D; + #[inline] + fn neg(self) -> Point3D { + Point3D::new(-self.x, -self.y, -self.z) + } +}