diff --git a/src/matrix.rs b/src/matrix.rs index 5d7f290..475dfcc 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -227,7 +227,7 @@ impl Matrix4 { /// Create a transformation matrix that will cause a vector to point at /// `dir`, using `up` for orientation. pub fn look_at(eye: &Point3, center: &Point3, up: &Vector3) -> Matrix4 { - let f = center.sub_p(eye).normalize(); + let f = (center - eye).normalize(); let s = f.cross(up).normalize(); let u = s.cross(&f); @@ -251,7 +251,18 @@ impl> Matrix4 { pub trait Matrix + 'static>: Array2 + ApproxEq - + Sized { + + Sized // where + // FIXME: blocked by rust-lang/rust#20671 + // + // for<'a, 'b> &'a Self: Add<&'b Self, Output = Self>, + // for<'a, 'b> &'a Self: Sub<&'b Self, Output = Self>, + // for<'a, 'b> &'a Self: Mul<&'b Self, Output = Self>, + // for<'a, 'b> &'a Self: Mul<&'b V, Output = V>, + // + // for<'a> &'a Self: Mul, + // for<'a> &'a Self: Div, + // for<'a> &'a Self: Rem, +{ /// Create a new diagonal matrix using the supplied value. fn from_value(value: S) -> Self; /// Create a matrix from a non-uniform scale @@ -350,117 +361,6 @@ pub trait Matrix + 'static>: Array2 fn is_symmetric(&self) -> bool; } -impl Add for Matrix2 { - type Output = Matrix2; - - #[inline] - fn add(self, other: Matrix2) -> Matrix2 { self.add_m(&other) } -} - -impl Add for Matrix3 { - type Output = Matrix3; - - #[inline] - fn add(self, other: Matrix3) -> Matrix3 { self.add_m(&other) } -} - -impl Add for Matrix4 { - type Output = Matrix4; - - #[inline] - fn add(self, other: Matrix4) -> Matrix4 { self.add_m(&other) } -} - -impl Sub for Matrix2 { - type Output = Matrix2; - - #[inline] - fn sub(self, other: Matrix2) -> Matrix2 { self.sub_m(&other) } -} - -impl Sub for Matrix3 { - type Output = Matrix3; - - #[inline] - fn sub(self, other: Matrix3) -> Matrix3 { self.sub_m(&other) } -} - -impl Sub for Matrix4 { - type Output = Matrix4; - - #[inline] - fn sub(self, other: Matrix4) -> Matrix4 { self.sub_m(&other) } -} - -impl> Neg for Matrix2 { - type Output = Matrix2; - - #[inline] - fn neg(self) -> Matrix2 { - Matrix2::from_cols(self.x.neg(), self.y.neg()) - } -} - -impl> Neg for Matrix3 { - type Output = Matrix3; - - #[inline] - fn neg(self) -> Matrix3 { - Matrix3::from_cols(self.x.neg(), self.y.neg(), self.z.neg()) - } -} - -impl> Neg for Matrix4 { - type Output = Matrix4; - - #[inline] - fn neg(self) -> Matrix4 { - Matrix4::from_cols(self.x.neg(), self.y.neg(), self.z.neg(), self.w.neg()) - } -} - -impl Mul for Matrix2 { - type Output = Matrix2; - - #[inline] - fn mul(self, other: Matrix2) -> Matrix2 { self.mul_m(&other) } -} - -impl Mul for Matrix2 { - type Output = Matrix2; - - #[inline] - fn mul(self, other: S) -> Matrix2 { self.mul_s(other) } -} - -impl Mul for Matrix3 { - type Output = Matrix3; - - #[inline] - fn mul(self, other: Matrix3) -> Matrix3 { self.mul_m(&other) } -} - -impl Mul for Matrix3 { - type Output = Matrix3; - - #[inline] - fn mul(self, other: S) -> Matrix3 { self.mul_s(other) } -} - -impl Mul for Matrix4 { - type Output = Matrix4; - - #[inline] - fn mul(self, other: Matrix4) -> Matrix4 { self.mul_m(&other) } -} - -impl Mul for Matrix4 { - type Output = Matrix4; - - #[inline] - fn mul(self, other: S) -> Matrix4 { self.mul_s(other) } -} - impl Array2, Vector2, S> for Matrix2 { #[inline] fn row(&self, r: usize) -> Vector2 { @@ -522,46 +422,13 @@ impl Matrix> for Matrix2 { S::zero(), value.y) } - #[inline] - fn mul_s(&self, s: S) -> Matrix2 { - Matrix2::from_cols(self[0].mul_s(s), - self[1].mul_s(s)) - } - - #[inline] - fn div_s(&self, s: S) -> Matrix2 { - Matrix2::from_cols(self[0].div_s(s), - self[1].div_s(s)) - } - - #[inline] - fn rem_s(&self, s: S) -> Matrix2 { - Matrix2::from_cols(self[0].rem_s(s), - self[1].rem_s(s)) - } - - #[inline] - fn add_m(&self, m: &Matrix2) -> Matrix2 { - Matrix2::from_cols(self[0].add_v(&m[0]), - self[1].add_v(&m[1])) - } - - #[inline] - fn sub_m(&self, m: &Matrix2) -> Matrix2 { - Matrix2::from_cols(self[0].sub_v(&m[0]), - self[1].sub_v(&m[1])) - } - - #[inline] - fn mul_v(&self, v: &Vector2) -> Vector2 { - Vector2::new(self.row(0).dot(v), - self.row(1).dot(v)) - } - - fn mul_m(&self, other: &Matrix2) -> Matrix2 { - Matrix2::new(self.row(0).dot(&other[0]), self.row(1).dot(&other[0]), - self.row(0).dot(&other[1]), self.row(1).dot(&other[1])) - } + #[inline] fn mul_s(&self, s: S) -> Matrix2 { self * s } + #[inline] fn div_s(&self, s: S) -> Matrix2 { self / s } + #[inline] fn rem_s(&self, s: S) -> Matrix2 { self % s } + #[inline] fn add_m(&self, m: &Matrix2) -> Matrix2 { self + m } + #[inline] fn sub_m(&self, m: &Matrix2) -> Matrix2 { self - m } + fn mul_m(&self, other: &Matrix2) -> Matrix2 { self * other } + #[inline] fn mul_v(&self, v: &Vector2) -> Vector2 { self * v } #[inline] fn mul_self_s(&mut self, s: S) { @@ -654,53 +521,13 @@ impl Matrix> for Matrix3 { S::zero(), S::zero(), value.z) } - #[inline] - fn mul_s(&self, s: S) -> Matrix3 { - Matrix3::from_cols(self[0].mul_s(s), - self[1].mul_s(s), - self[2].mul_s(s)) - } - - #[inline] - fn div_s(&self, s: S) -> Matrix3 { - Matrix3::from_cols(self[0].div_s(s), - self[1].div_s(s), - self[2].div_s(s)) - } - - #[inline] - fn rem_s(&self, s: S) -> Matrix3 { - Matrix3::from_cols(self[0].rem_s(s), - self[1].rem_s(s), - self[2].rem_s(s)) - } - - #[inline] - fn add_m(&self, m: &Matrix3) -> Matrix3 { - Matrix3::from_cols(self[0].add_v(&m[0]), - self[1].add_v(&m[1]), - self[2].add_v(&m[2])) - } - - #[inline] - fn sub_m(&self, m: &Matrix3) -> Matrix3 { - Matrix3::from_cols(self[0].sub_v(&m[0]), - self[1].sub_v(&m[1]), - self[2].sub_v(&m[2])) - } - - #[inline] - fn mul_v(&self, v: &Vector3) -> Vector3 { - Vector3::new(self.row(0).dot(v), - self.row(1).dot(v), - self.row(2).dot(v)) - } - - fn mul_m(&self, other: &Matrix3) -> Matrix3 { - Matrix3::new(self.row(0).dot(&other[0]),self.row(1).dot(&other[0]),self.row(2).dot(&other[0]), - self.row(0).dot(&other[1]),self.row(1).dot(&other[1]),self.row(2).dot(&other[1]), - self.row(0).dot(&other[2]),self.row(1).dot(&other[2]),self.row(2).dot(&other[2])) - } + #[inline] fn mul_s(&self, s: S) -> Matrix3 { self * s } + #[inline] fn div_s(&self, s: S) -> Matrix3 { self / s } + #[inline] fn rem_s(&self, s: S) -> Matrix3 { self % s } + #[inline] fn add_m(&self, m: &Matrix3) -> Matrix3 { self + m } + #[inline] fn sub_m(&self, m: &Matrix3) -> Matrix3 { self - m } + fn mul_m(&self, other: &Matrix3) -> Matrix3 { self * other } + #[inline] fn mul_v(&self, v: &Vector3) -> Vector3 { self * v} #[inline] fn mul_self_s(&mut self, s: S) { @@ -766,9 +593,9 @@ impl Matrix> for Matrix3 { fn invert(&self) -> Option> { let det = self.determinant(); if det.approx_eq(&S::zero()) { None } else { - Some(Matrix3::from_cols(self[1].cross(&self[2]).div_s(det), - self[2].cross(&self[0]).div_s(det), - self[0].cross(&self[1]).div_s(det)).transpose()) + Some(Matrix3::from_cols(&self[1].cross(&self[2]) / det, + &self[2].cross(&self[0]) / det, + &self[0].cross(&self[1]) / det).transpose()) } } @@ -824,60 +651,13 @@ impl Matrix> for Matrix4 { S::zero(), S::zero(), S::zero(), value.w) } - #[inline] - fn mul_s(&self, s: S) -> Matrix4 { - Matrix4::from_cols(self[0].mul_s(s), - self[1].mul_s(s), - self[2].mul_s(s), - self[3].mul_s(s)) - } - - #[inline] - fn div_s(&self, s: S) -> Matrix4 { - Matrix4::from_cols(self[0].div_s(s), - self[1].div_s(s), - self[2].div_s(s), - self[3].div_s(s)) - } - - #[inline] - fn rem_s(&self, s: S) -> Matrix4 { - Matrix4::from_cols(self[0].rem_s(s), - self[1].rem_s(s), - self[2].rem_s(s), - self[3].rem_s(s)) - } - - #[inline] - fn add_m(&self, m: &Matrix4) -> Matrix4 { - Matrix4::from_cols(self[0].add_v(&m[0]), - self[1].add_v(&m[1]), - self[2].add_v(&m[2]), - self[3].add_v(&m[3])) - } - - #[inline] - fn sub_m(&self, m: &Matrix4) -> Matrix4 { - Matrix4::from_cols(self[0].sub_v(&m[0]), - self[1].sub_v(&m[1]), - self[2].sub_v(&m[2]), - self[3].sub_v(&m[3])) - } - - #[inline] - fn mul_v(&self, v: &Vector4) -> Vector4 { - Vector4::new(self.row(0).dot(v), - self.row(1).dot(v), - self.row(2).dot(v), - self.row(3).dot(v)) - } - - fn mul_m(&self, other: &Matrix4) -> Matrix4 { - Matrix4::new(dot_matrix4!(self, other, 0, 0), dot_matrix4!(self, other, 1, 0), dot_matrix4!(self, other, 2, 0), dot_matrix4!(self, other, 3, 0), - dot_matrix4!(self, other, 0, 1), dot_matrix4!(self, other, 1, 1), dot_matrix4!(self, other, 2, 1), dot_matrix4!(self, other, 3, 1), - dot_matrix4!(self, other, 0, 2), dot_matrix4!(self, other, 1, 2), dot_matrix4!(self, other, 2, 2), dot_matrix4!(self, other, 3, 2), - dot_matrix4!(self, other, 0, 3), dot_matrix4!(self, other, 1, 3), dot_matrix4!(self, other, 2, 3), dot_matrix4!(self, other, 3, 3)) - } + #[inline] fn mul_s(&self, s: S) -> Matrix4 { self * s } + #[inline] fn div_s(&self, s: S) -> Matrix4 { self / s } + #[inline] fn rem_s(&self, s: S) -> Matrix4 { self % s } + #[inline] fn add_m(&self, m: &Matrix4) -> Matrix4 { self + m } + #[inline] fn sub_m(&self, m: &Matrix4) -> Matrix4 { self - m } + fn mul_m(&self, other: &Matrix4) -> Matrix4 { self * other } + #[inline] fn mul_v(&self, v: &Vector4) -> Vector4 { self * v } #[inline] fn mul_self_s(&mut self, s: S) { @@ -1062,6 +842,137 @@ impl ApproxEq for Matrix4 { } } +impl> Neg for Matrix2 { + type Output = Matrix2; + + #[inline] + fn neg(self) -> Matrix2 { + Matrix2::from_cols(-self.x, -self.y) + } +} + +impl> Neg for Matrix3 { + type Output = Matrix3; + + #[inline] + fn neg(self) -> Matrix3 { + Matrix3::from_cols(-self.x, -self.y, -self.z) + } +} + +impl> Neg for Matrix4 { + type Output = Matrix4; + + #[inline] + fn neg(self) -> Matrix4 { + Matrix4::from_cols(-self.x, -self.y, -self.z, -self.w) + } +} + +macro_rules! impl_scalar_binary_operator { + ($Binop:ident :: $binop:ident, $MatrixN:ident { $($field:ident),+ }) => { + impl<'a, S: BaseNum> $Binop for &'a $MatrixN { + type Output = $MatrixN; + + #[inline] + fn $binop(self, s: S) -> $MatrixN { + $MatrixN { $($field: self.$field.$binop(s)),+ } + } + } + } +} + +impl_scalar_binary_operator!(Mul::mul, Matrix2 { x, y }); +impl_scalar_binary_operator!(Mul::mul, Matrix3 { x, y, z }); +impl_scalar_binary_operator!(Mul::mul, Matrix4 { x, y, z, w }); +impl_scalar_binary_operator!(Div::div, Matrix2 { x, y }); +impl_scalar_binary_operator!(Div::div, Matrix3 { x, y, z }); +impl_scalar_binary_operator!(Div::div, Matrix4 { x, y, z, w }); +impl_scalar_binary_operator!(Rem::rem, Matrix2 { x, y }); +impl_scalar_binary_operator!(Rem::rem, Matrix3 { x, y, z }); +impl_scalar_binary_operator!(Rem::rem, Matrix4 { x, y, z, w }); + +macro_rules! impl_binary_operator { + ($Binop:ident :: $binop:ident, $MatrixN:ident { $($field:ident),+ }) => { + impl<'a, 'b, S: BaseNum> $Binop<&'a $MatrixN> for &'b $MatrixN { + type Output = $MatrixN; + + #[inline] + fn $binop(self, other: &'a $MatrixN) -> $MatrixN { + $MatrixN { $($field: self.$field.$binop(&other.$field)),+ } + } + } + } +} + +impl_binary_operator!(Add::add, Matrix2 { x, y }); +impl_binary_operator!(Add::add, Matrix3 { x, y, z }); +impl_binary_operator!(Add::add, Matrix4 { x, y, z, w }); +impl_binary_operator!(Sub::sub, Matrix2 { x, y }); +impl_binary_operator!(Sub::sub, Matrix3 { x, y, z }); +impl_binary_operator!(Sub::sub, Matrix4 { x, y, z, w }); + +impl<'a, 'b, S: BaseNum> Mul<&'a Vector2> for &'b Matrix2 { + type Output = Vector2; + + fn mul(self, v: &'a Vector2) -> Vector2 { + Vector2::new(self.row(0).dot(v), + self.row(1).dot(v)) + } +} + +impl<'a, 'b, S: BaseNum> Mul<&'a Vector3> for &'b Matrix3 { + type Output = Vector3; + + fn mul(self, v: &'a Vector3) -> Vector3 { + Vector3::new(self.row(0).dot(v), + self.row(1).dot(v), + self.row(2).dot(v)) + } +} + +impl<'a, 'b, S: BaseNum> Mul<&'a Vector4> for &'b Matrix4 { + type Output = Vector4; + + fn mul(self, v: &'a Vector4) -> Vector4 { + Vector4::new(self.row(0).dot(v), + self.row(1).dot(v), + self.row(2).dot(v), + self.row(3).dot(v)) + } +} + +impl<'a, 'b, S: BaseNum> Mul<&'a Matrix2> for &'b Matrix2 { + type Output = Matrix2; + + fn mul(self, other: &'a Matrix2) -> Matrix2 { + Matrix2::new(self.row(0).dot(&other[0]), self.row(1).dot(&other[0]), + self.row(0).dot(&other[1]), self.row(1).dot(&other[1])) + } +} + +impl<'a, 'b, S: BaseNum> Mul<&'a Matrix3> for &'b Matrix3 { + type Output = Matrix3; + + fn mul(self, other: &'a Matrix3) -> Matrix3 { + Matrix3::new(self.row(0).dot(&other[0]),self.row(1).dot(&other[0]),self.row(2).dot(&other[0]), + self.row(0).dot(&other[1]),self.row(1).dot(&other[1]),self.row(2).dot(&other[1]), + self.row(0).dot(&other[2]),self.row(1).dot(&other[2]),self.row(2).dot(&other[2])) + } +} + +impl<'a, 'b, S: BaseNum> Mul<&'a Matrix4> for &'b Matrix4 { + type Output = Matrix4; + + fn mul(self, other: &'a Matrix4) -> Matrix4 { + Matrix4::new(dot_matrix4!(self, other, 0, 0), dot_matrix4!(self, other, 1, 0), dot_matrix4!(self, other, 2, 0), dot_matrix4!(self, other, 3, 0), + dot_matrix4!(self, other, 0, 1), dot_matrix4!(self, other, 1, 1), dot_matrix4!(self, other, 2, 1), dot_matrix4!(self, other, 3, 1), + dot_matrix4!(self, other, 0, 2), dot_matrix4!(self, other, 1, 2), dot_matrix4!(self, other, 2, 2), dot_matrix4!(self, other, 3, 2), + dot_matrix4!(self, other, 0, 3), dot_matrix4!(self, other, 1, 3), dot_matrix4!(self, other, 2, 3), dot_matrix4!(self, other, 3, 3)) + + } +} + macro_rules! index_operators { ($MatrixN:ident<$S:ident>, $n:expr, $Output:ty, $I:ty) => { impl<$S> Index<$I> for $MatrixN<$S> { diff --git a/tests/matrix.rs b/tests/matrix.rs index d087a02..881d615 100644 --- a/tests/matrix.rs +++ b/tests/matrix.rs @@ -134,7 +134,7 @@ fn test_add_m() { let mut mut_a = matrix2::A; mut_a.add_self_m(&matrix2::B); assert_eq!(mut_a, matrix2::A.add_m(&matrix2::B)); - assert_eq!(mut_a, matrix2::A + matrix2::B); + assert_eq!(mut_a, &matrix2::A + &matrix2::B); // Matrix3 assert_eq!(matrix3::A.add_m(&matrix3::B), @@ -144,7 +144,7 @@ fn test_add_m() { let mut mut_a = matrix3::A; mut_a.add_self_m(&matrix3::B); assert_eq!(mut_a, matrix3::A.add_m(&matrix3::B)); - assert_eq!(mut_a, matrix3::A + matrix3::B); + assert_eq!(mut_a, &matrix3::A + &matrix3::B); // Matrix4 assert_eq!(matrix4::A.add_m(&matrix4::B), @@ -155,7 +155,7 @@ fn test_add_m() { let mut mut_a = matrix4::A; mut_a.add_self_m(&matrix4::B); assert_eq!(mut_a, matrix4::A.add_m(&matrix4::B)); - assert_eq!(mut_a, matrix4::A + matrix4::B); + assert_eq!(mut_a, &matrix4::A + &matrix4::B); } #[test] @@ -167,7 +167,7 @@ fn test_sub_m() { let mut mut_a = matrix2::A; mut_a.sub_self_m(&matrix2::B); assert_eq!(mut_a, matrix2::A.sub_m(&matrix2::B)); - assert_eq!(matrix2::A.sub_m(&matrix2::B), matrix2::A - matrix2::B); + assert_eq!(matrix2::A.sub_m(&matrix2::B), &matrix2::A - &matrix2::B); // Matrix3 assert_eq!(matrix3::A.sub_m(&matrix3::B), @@ -177,7 +177,7 @@ fn test_sub_m() { let mut mut_a = matrix3::A; mut_a.sub_self_m(&matrix3::B); assert_eq!(mut_a, matrix3::A.sub_m(&matrix3::B)); - assert_eq!(matrix3::A.sub_m(&matrix3::B), matrix3::A - matrix3::B); + assert_eq!(matrix3::A.sub_m(&matrix3::B), &matrix3::A - &matrix3::B); // Matrix4 assert_eq!(matrix4::A.sub_m(&matrix4::B), @@ -188,7 +188,7 @@ fn test_sub_m() { let mut mut_a = matrix4::A; mut_a.sub_self_m(&matrix4::B); assert_eq!(mut_a, matrix4::A.sub_m(&matrix4::B)); - assert_eq!(matrix4::A.sub_m(&matrix4::B), matrix4::A - matrix4::B); + assert_eq!(matrix4::A.sub_m(&matrix4::B), &matrix4::A - &matrix4::B); } #[test] @@ -213,9 +213,9 @@ fn test_mul_m() { 120.0f64, 280.0f64, 440.0f64, 600.0f64, 130.0f64, 306.0f64, 482.0f64, 658.0f64)); - assert_eq!(matrix2::A.mul_m(&matrix2::B), matrix2::A * matrix2::B); - assert_eq!(matrix3::A.mul_m(&matrix3::B), matrix3::A * matrix3::B); - assert_eq!(matrix4::A.mul_m(&matrix4::B), matrix4::A * matrix4::B); + assert_eq!(matrix2::A.mul_m(&matrix2::B), &matrix2::A * &matrix2::B); + assert_eq!(matrix3::A.mul_m(&matrix3::B), &matrix3::A * &matrix3::B); + assert_eq!(matrix4::A.mul_m(&matrix4::B), &matrix4::A * &matrix4::B); } #[test]