From 047b183eb61df156581d55e86bd01835555be059 Mon Sep 17 00:00:00 2001 From: Glenn Watson Date: Wed, 27 May 2015 11:34:21 +1000 Subject: [PATCH] Add methods to create various matrix types. --- src/matrix.rs | 91 +++++++++++++++++++++++++++++++++++++++++---- src/side_offsets.rs | 2 +- 2 files changed, 85 insertions(+), 8 deletions(-) diff --git a/src/matrix.rs b/src/matrix.rs index 5dc87b9..79c8a4e 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -11,10 +11,9 @@ use approxeq::ApproxEq; use point::Point2D; use num::{One, Zero}; -use num_lib::NumCast; -use std::ops::{Add, Mul, Div, Neg, Sub}; +use num_lib::{Float, NumCast}; -pub fn Matrix4 + Clone + ApproxEq + Mul + One + Zero>( +pub fn Matrix4( m11: T, m12: T, m13: T, m14: T, m21: T, m22: T, m23: T, m24: T, m31: T, m32: T, m33: T, m34: T, @@ -36,7 +35,10 @@ pub struct Matrix4 { pub m41: T, pub m42: T, pub m43: T, pub m44: T, } -impl + Copy + Clone + ApproxEq + Mul + One + Zero> Matrix4 { +impl + + Float> Matrix4 { pub fn approx_eq(&self, other: &Matrix4) -> bool { self.m11.approx_eq(&other.m11) && self.m12.approx_eq(&other.m12) && self.m13.approx_eq(&other.m13) && self.m14.approx_eq(&other.m14) && @@ -106,10 +108,85 @@ impl + Copy + Clone + ApproxEq + Mul + One + return self.mul(&matrix); } + + /// Create a 3d translation matrix + pub fn create_translation(x: T, y: T, z: T) -> Matrix4 { + let (_0, _1): (T, T) = (Zero::zero(), One::one()); + Matrix4(_1.clone(), _0.clone(), _0.clone(), _0.clone(), + _0.clone(), _1.clone(), _0.clone(), _0.clone(), + _0.clone(), _0.clone(), _1.clone(), _0.clone(), + x, y, z, _1.clone()) + } + + /// Create a 3d scale matrix + pub fn create_scale(x: T, y: T, z: T) -> Matrix4 { + let (_0, _1): (T, T) = (Zero::zero(), One::one()); + Matrix4( x, _0.clone(), _0.clone(), _0.clone(), + _0.clone(), y, _0.clone(), _0.clone(), + _0.clone(), _0.clone(), z, _0.clone(), + _0.clone(), _0.clone(), _0.clone(), _1.clone()) + } + + /// Create a 3d rotation matrix from an angle / axis. + /// The supplied axis must be normalized. + pub fn create_rotation(x: T, y: T, z: T, theta: T) -> Matrix4 { + let _0: T = Zero::zero(); + let _1: T = One::one(); + let _2: T = NumCast::from(2).unwrap(); + let _half: T = NumCast::from(0.5).unwrap(); + + let xx = x * x; + let yy = y * y; + let zz = z * z; + + let half_theta = theta * _half; + let sc = half_theta.sin() * half_theta.cos(); + let sq = half_theta.sin() * half_theta.sin(); + + Matrix4( + _1.clone() - _2.clone() * (yy + zz) * sq, + _2.clone() * (x * y * sq - z * sc), + _2.clone() * (x * z * sq + y * sc), + _0.clone(), + + _2.clone() * (x * y * sq + z * sc), + _1.clone() - _2.clone() * (xx + zz) * sq, + _2.clone() * (y * z * sq - x * sc), + _0.clone(), + + _2.clone() * (x * z * sq - y * sc), + _2.clone() * (y * z * sq + x * sc), + _1.clone() - _2.clone() * (xx + yy) * sq, + _0.clone(), + + _0.clone(), + _0.clone(), + _0.clone(), + _1.clone() + ) + } + + /// Create a 2d skew matrix + pub fn create_skew(sx: T, sy: T) -> Matrix4 { + let (_0, _1): (T, T) = (Zero::zero(), One::one()); + Matrix4(_1.clone(), sx, _0.clone(), _0.clone(), + sy, _1.clone(), _0.clone(), _0.clone(), + _0.clone(), _0.clone(), _1.clone(), _0.clone(), + _0.clone(), _0.clone(), _0.clone(), _1.clone()) + } + + /// Create a simple perspective projection matrix + pub fn create_perspective(d: T) -> Matrix4 { + let (_0, _1): (T, T) = (Zero::zero(), One::one()); + Matrix4(_1.clone(), _0.clone(), _0.clone(), _0.clone(), + _0.clone(), _1.clone(), _0.clone(), _0.clone(), + _0.clone(), _0.clone(), _1.clone(), -_1.clone() / d, + _0.clone(), _0.clone(), _0.clone(), _1.clone()) + } } -pub fn ortho + Copy + Clone + Div + ApproxEq + Mul + Neg + NumCast + One + - Sub + Zero> +// TODO(gw): Move ortho and identity into static functions of the Matrix type. +pub fn ortho (left: T, right: T, bottom: T, @@ -131,7 +208,7 @@ pub fn ortho + Copy + Clone + Div + ApproxEq tx, ty, tz, _1.clone()) } -pub fn identity + Clone + ApproxEq + Mul + One + Zero>() -> Matrix4 { +pub fn identity() -> Matrix4 { let (_0, _1): (T, T) = (Zero::zero(), One::one()); Matrix4(_1.clone(), _0.clone(), _0.clone(), _0.clone(), _0.clone(), _1.clone(), _0.clone(), _0.clone(), diff --git a/src/side_offsets.rs b/src/side_offsets.rs index cbed9ed..3b5a86c 100644 --- a/src/side_offsets.rs +++ b/src/side_offsets.rs @@ -15,7 +15,7 @@ use std::ops::Add; /// A group of side offsets, which correspond to top/left/bottom/right for borders, padding, /// and margins in CSS. -#[derive(Clone, Copy, PartialEq)] +#[derive(Clone, Copy, PartialEq, Debug)] pub struct SideOffsets2D { pub top: T, pub right: T,