cgmath/src/matrix.rs

1239 lines
42 KiB
Rust
Raw Normal View History

2014-05-26 17:10:04 +00:00
// Copyright 2013-2014 The CGMath Developers. For a full listing of the authors,
2015-03-14 02:49:46 +00:00
// refer to the Cargo.toml file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
2013-09-03 06:37:06 +00:00
//! Column major, square matrix types and traits.
use std::fmt;
use std::mem;
2015-01-03 21:29:26 +00:00
use std::ops::*;
2015-03-15 02:53:57 +00:00
use rand::{Rand, Rng};
use rust_num::{Zero, One};
2015-04-25 03:28:31 +00:00
use rust_num::traits::cast;
2015-04-05 01:19:11 +00:00
use angle::{Rad, sin, cos, sin_cos};
2014-01-09 00:26:50 +00:00
use approx::ApproxEq;
use array::{Array1, Array2};
2015-04-05 01:19:11 +00:00
use num::{BaseFloat, BaseNum};
use point::{Point, Point3};
2015-05-06 08:38:15 +00:00
use quaternion::Quaternion;
2013-09-18 01:37:06 +00:00
use vector::{Vector, EuclideanVector};
use vector::{Vector2, Vector3, Vector4};
2013-09-03 06:37:06 +00:00
/// A 2 x 2, column major matrix
2015-02-08 18:25:42 +00:00
#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable)]
pub struct Matrix2<S> { pub x: Vector2<S>, pub y: Vector2<S> }
2013-09-03 06:37:06 +00:00
/// A 3 x 3, column major matrix
2015-02-08 18:25:42 +00:00
#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable)]
pub struct Matrix3<S> { pub x: Vector3<S>, pub y: Vector3<S>, pub z: Vector3<S> }
2013-09-03 06:37:06 +00:00
/// A 4 x 4, column major matrix
2015-02-08 18:25:42 +00:00
#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable)]
pub struct Matrix4<S> { pub x: Vector4<S>, pub y: Vector4<S>, pub z: Vector4<S>, pub w: Vector4<S> }
2015-04-05 00:15:00 +00:00
impl<S> Matrix2<S> {
/// Create a new matrix, providing values for each index.
#[inline]
pub fn new(c0r0: S, c0r1: S,
c1r0: S, c1r1: S) -> Matrix2<S> {
Matrix2::from_cols(Vector2::new(c0r0, c0r1),
2014-04-14 01:41:29 +00:00
Vector2::new(c1r0, c1r1))
}
/// Create a new matrix, providing columns.
#[inline]
pub fn from_cols(c0: Vector2<S>, c1: Vector2<S>) -> Matrix2<S> {
Matrix2 { x: c0, y: c1 }
}
2015-04-05 00:15:00 +00:00
}
2013-09-02 01:49:05 +00:00
2015-04-05 01:19:11 +00:00
impl<S: BaseFloat> Matrix2<S> {
/// Create a transformation matrix that will cause a vector to point at
/// `dir`, using `up` for orientation.
pub fn look_at(dir: &Vector2<S>, up: &Vector2<S>) -> Matrix2<S> {
//TODO: verify look_at 2D
Matrix2::from_cols(up.clone(), dir.clone()).transpose()
}
2013-09-03 08:03:18 +00:00
#[inline]
pub fn from_angle(theta: Rad<S>) -> Matrix2<S> {
let cos_theta = cos(theta.clone());
let sin_theta = sin(theta.clone());
2013-09-03 08:03:18 +00:00
Matrix2::new(cos_theta.clone(), sin_theta.clone(),
-sin_theta.clone(), cos_theta.clone())
2013-09-03 08:03:18 +00:00
}
}
2015-04-05 00:15:00 +00:00
impl<S: Copy + Neg<Output = S>> Matrix2<S> {
/// Negate this `Matrix2` in-place.
#[inline]
pub fn neg_self(&mut self) {
2015-10-04 01:58:53 +00:00
self[0].neg_self();
self[1].neg_self();
2015-04-05 00:15:00 +00:00
}
}
2015-04-05 01:19:11 +00:00
impl<S> Matrix3<S> {
/// Create a new matrix, providing values for each index.
#[inline]
pub fn new(c0r0:S, c0r1:S, c0r2:S,
c1r0:S, c1r1:S, c1r2:S,
c2r0:S, c2r1:S, c2r2:S) -> Matrix3<S> {
Matrix3::from_cols(Vector3::new(c0r0, c0r1, c0r2),
2014-04-14 01:41:29 +00:00
Vector3::new(c1r0, c1r1, c1r2),
Vector3::new(c2r0, c2r1, c2r2))
}
/// Create a new matrix, providing columns.
#[inline]
pub fn from_cols(c0: Vector3<S>, c1: Vector3<S>, c2: Vector3<S>) -> Matrix3<S> {
Matrix3 { x: c0, y: c1, z: c2 }
}
2015-04-05 01:19:11 +00:00
}
2013-09-02 01:49:05 +00:00
2015-04-05 01:19:11 +00:00
impl<S: BaseFloat> Matrix3<S> {
/// Create a transformation matrix that will cause a vector to point at
/// `dir`, using `up` for orientation.
pub fn look_at(dir: &Vector3<S>, up: &Vector3<S>) -> Matrix3<S> {
let dir = dir.normalize();
let side = up.cross(&dir).normalize();
let up = dir.cross(&side).normalize();
Matrix3::from_cols(side, up, dir).transpose()
}
/// Create a matrix from a rotation around the `x` axis (pitch).
pub fn from_angle_x(theta: Rad<S>) -> Matrix3<S> {
// http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations
let (s, c) = sin_cos(theta);
Matrix3::new(S::one(), S::zero(), S::zero(),
S::zero(), c.clone(), s.clone(),
S::zero(), -s.clone(), c.clone())
}
/// Create a matrix from a rotation around the `y` axis (yaw).
pub fn from_angle_y(theta: Rad<S>) -> Matrix3<S> {
// http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations
let (s, c) = sin_cos(theta);
Matrix3::new(c.clone(), S::zero(), -s.clone(),
S::zero(), S::one(), S::zero(),
s.clone(), S::zero(), c.clone())
}
/// Create a matrix from a rotation around the `z` axis (roll).
pub fn from_angle_z(theta: Rad<S>) -> Matrix3<S> {
// http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations
let (s, c) = sin_cos(theta);
Matrix3::new( c.clone(), s.clone(), S::zero(),
-s.clone(), c.clone(), S::zero(),
S::zero(), S::zero(), S::one())
}
/// Create a matrix from a set of euler angles.
///
/// # Parameters
///
/// - `x`: the angular rotation around the `x` axis (pitch).
/// - `y`: the angular rotation around the `y` axis (yaw).
/// - `z`: the angular rotation around the `z` axis (roll).
pub fn from_euler(x: Rad<S>, y: Rad<S>, z: Rad<S>) -> Matrix3<S> {
// http://en.wikipedia.org/wiki/Rotation_matrix#General_rotations
let (sx, cx) = sin_cos(x);
let (sy, cy) = sin_cos(y);
let (sz, cz) = sin_cos(z);
2014-04-14 01:41:29 +00:00
Matrix3::new( cy * cz, cy * sz, -sy,
-cx * sz + sx * sy * cz, cx * cz + sx * sy * sz, sx * cy,
sx * sz + cx * sy * cz, -sx * cz + cx * sy * sz, cx * cy)
}
/// Create a matrix from a rotation around an arbitrary axis
pub fn from_axis_angle(axis: &Vector3<S>, angle: Rad<S>) -> Matrix3<S> {
let (s, c) = sin_cos(angle);
let _1subc = S::one() - c;
Matrix3::new(_1subc * axis.x * axis.x + c,
2014-04-14 01:41:29 +00:00
_1subc * axis.x * axis.y + s * axis.z,
_1subc * axis.x * axis.z - s * axis.y,
2014-04-14 01:41:29 +00:00
_1subc * axis.x * axis.y - s * axis.z,
_1subc * axis.y * axis.y + c,
_1subc * axis.y * axis.z + s * axis.x,
2014-04-14 01:41:29 +00:00
_1subc * axis.x * axis.z + s * axis.y,
_1subc * axis.y * axis.z - s * axis.x,
_1subc * axis.z * axis.z + c)
}
}
2015-04-05 00:15:00 +00:00
impl<S: Copy + Neg<Output = S>> Matrix3<S> {
/// Negate this `Matrix3` in-place.
#[inline]
pub fn neg_self(&mut self) {
2015-10-04 01:58:53 +00:00
self[0].neg_self();
self[1].neg_self();
self[2].neg_self();
2015-04-05 00:15:00 +00:00
}
}
2015-04-05 01:19:11 +00:00
impl<S> Matrix4<S> {
/// Create a new matrix, providing values for each index.
#[inline]
pub fn new(c0r0: S, c0r1: S, c0r2: S, c0r3: S,
c1r0: S, c1r1: S, c1r2: S, c1r3: S,
c2r0: S, c2r1: S, c2r2: S, c2r3: S,
c3r0: S, c3r1: S, c3r2: S, c3r3: S) -> Matrix4<S> {
Matrix4::from_cols(Vector4::new(c0r0, c0r1, c0r2, c0r3),
2014-04-14 01:41:29 +00:00
Vector4::new(c1r0, c1r1, c1r2, c1r3),
Vector4::new(c2r0, c2r1, c2r2, c2r3),
Vector4::new(c3r0, c3r1, c3r2, c3r3))
}
/// Create a new matrix, providing columns.
#[inline]
pub fn from_cols(c0: Vector4<S>, c1: Vector4<S>, c2: Vector4<S>, c3: Vector4<S>) -> Matrix4<S> {
Matrix4 { x: c0, y: c1, z: c2, w: c3 }
}
2015-04-05 01:19:11 +00:00
}
2013-09-02 01:49:05 +00:00
2015-04-05 01:19:11 +00:00
impl<S: BaseNum> Matrix4<S> {
/// Create a translation matrix from a Vector3
#[inline]
pub fn from_translation(v: &Vector3<S>) -> Matrix4<S> {
Matrix4::new(S::one(), S::zero(), S::zero(), S::zero(),
S::zero(), S::one(), S::zero(), S::zero(),
S::zero(), S::zero(), S::one(), S::zero(),
v.x, v.y, v.z, S::one())
}
}
2015-04-05 00:15:00 +00:00
impl<S: BaseFloat> Matrix4<S> {
/// Create a transformation matrix that will cause a vector to point at
/// `dir`, using `up` for orientation.
pub fn look_at(eye: &Point3<S>, center: &Point3<S>, up: &Vector3<S>) -> Matrix4<S> {
let f = (center - eye).normalize();
2013-12-07 03:36:11 +00:00
let s = f.cross(up).normalize();
let u = s.cross(&f);
Matrix4::new(s.x.clone(), u.x.clone(), -f.x.clone(), S::zero(),
s.y.clone(), u.y.clone(), -f.y.clone(), S::zero(),
s.z.clone(), u.z.clone(), -f.z.clone(), S::zero(),
-eye.dot(&s), -eye.dot(&u), eye.dot(&f), S::one())
}
}
2015-04-05 00:15:00 +00:00
impl<S: Copy + Neg<Output = S>> Matrix4<S> {
/// Negate this `Matrix4` in-place.
#[inline]
pub fn neg_self(&mut self) {
2015-10-04 01:58:53 +00:00
self[0].neg_self();
self[1].neg_self();
self[2].neg_self();
self[3].neg_self();
2015-04-05 00:15:00 +00:00
}
}
pub trait Matrix<S: BaseFloat, V: Vector<Scalar = S>> where
Self: Array2<Element = S, Column = V, Row = V>,
Self: ApproxEq<Epsilon = S> + Sized,
// 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<S, Output = Self>,
// for<'a> &'a Self: Div<S, Output = Self>,
// for<'a> &'a Self: Rem<S, Output = Self>,
{
/// Create a new diagonal matrix using the supplied value.
fn from_value(value: S) -> Self;
/// Create a matrix from a non-uniform scale
fn from_diagonal(value: &V) -> Self;
/// Create a matrix with all elements equal to zero.
#[inline]
fn zero() -> Self { Self::from_value(S::zero()) }
/// Create a matrix where the each element of the diagonal is equal to one.
#[inline]
fn one() -> Self { Self::from_value(S::one()) }
/// Multiply this matrix by a scalar, returning the new matrix.
#[must_use]
fn mul_s(&self, s: S) -> Self;
/// Divide this matrix by a scalar, returning the new matrix.
#[must_use]
fn div_s(&self, s: S) -> Self;
/// Take the remainder of this matrix by a scalar, returning the new
/// matrix.
#[must_use]
fn rem_s(&self, s: S) -> Self;
2013-09-04 04:40:24 +00:00
/// Add this matrix with another matrix, returning the new metrix.
#[must_use]
fn add_m(&self, m: &Self) -> Self;
/// Subtract another matrix from this matrix, returning the new matrix.
#[must_use]
fn sub_m(&self, m: &Self) -> Self;
2013-09-04 04:40:24 +00:00
/// Multiplay a vector by this matrix, returning a new vector.
fn mul_v(&self, v: &V) -> V;
2013-09-04 04:40:24 +00:00
/// Multiply this matrix by another matrix, returning the new matrix.
#[must_use]
fn mul_m(&self, m: &Self) -> Self;
/// Multiply this matrix by a scalar, in-place.
fn mul_self_s(&mut self, s: S);
/// Divide this matrix by a scalar, in-place.
fn div_self_s(&mut self, s: S);
/// Take the remainder of this matrix, in-place.
fn rem_self_s(&mut self, s: S);
/// Add this matrix with another matrix, in-place.
fn add_self_m(&mut self, m: &Self);
/// Subtract another matrix from this matrix, in-place.
fn sub_self_m(&mut self, m: &Self);
/// Multiply this matrix by another matrix, in-place.
#[inline]
fn mul_self_m(&mut self, m: &Self) { *self = self.mul_m(m); }
/// Transpose this matrix, returning a new matrix.
#[must_use]
fn transpose(&self) -> Self;
/// Transpose this matrix in-place.
fn transpose_self(&mut self);
/// Take the determinant of this matrix.
fn determinant(&self) -> S;
/// Return a vector containing the diagonal of this matrix.
fn diagonal(&self) -> V;
/// Return the trace of this matrix. That is, the sum of the diagonal.
#[inline]
fn trace(&self) -> S { self.diagonal().sum() }
/// Invert this matrix, returning a new matrix. `m.mul_m(m.invert())` is
/// the identity matrix. Returns `None` if this matrix is not invertible
/// (has a determinant of zero).
#[must_use]
fn invert(&self) -> Option<Self>;
/// Invert this matrix in-place.
#[inline]
fn invert_self(&mut self) {
*self = self.invert().expect("Attempted to invert a matrix with zero determinant.");
}
/// Test if this matrix is invertible.
#[inline]
fn is_invertible(&self) -> bool { !self.determinant().approx_eq(&S::zero()) }
/// Test if this matrix is the identity matrix. That is, it is diagonal
/// and every element in the diagonal is one.
#[inline]
fn is_one(&self) -> bool { self.approx_eq(&Self::one()) }
/// Test if this is a diagonal matrix. That is, every element outside of
/// the diagonal is 0.
fn is_diagonal(&self) -> bool;
/// Test if this matrix is symmetric. That is, it is equal to its
/// transpose.
fn is_symmetric(&self) -> bool;
}
impl<S: Copy + 'static> Array2 for Matrix2<S> {
type Element = S;
type Column = Vector2<S>;
type Row = Vector2<S>;
#[inline]
2015-01-09 23:16:39 +00:00
fn row(&self, r: usize) -> Vector2<S> {
Vector2::new(self[0][r],
self[1][r])
}
#[inline]
2015-01-09 23:16:39 +00:00
fn swap_rows(&mut self, a: usize, b: usize) {
2015-10-04 01:58:53 +00:00
self[0].swap_elems(a, b);
self[1].swap_elems(a, b);
}
}
impl<S: Copy + 'static> Array2 for Matrix3<S> {
type Element = S;
type Column = Vector3<S>;
type Row = Vector3<S>;
#[inline]
2015-01-09 23:16:39 +00:00
fn row(&self, r: usize) -> Vector3<S> {
Vector3::new(self[0][r],
self[1][r],
self[2][r])
}
#[inline]
2015-01-09 23:16:39 +00:00
fn swap_rows(&mut self, a: usize, b: usize) {
2015-10-04 01:58:53 +00:00
self[0].swap_elems(a, b);
self[1].swap_elems(a, b);
self[2].swap_elems(a, b);
}
}
impl<S: Copy + 'static> Array2 for Matrix4<S> {
type Element = S;
type Column = Vector4<S>;
type Row = Vector4<S>;
#[inline]
2015-01-09 23:16:39 +00:00
fn row(&self, r: usize) -> Vector4<S> {
Vector4::new(self[0][r],
self[1][r],
self[2][r],
self[3][r])
}
#[inline]
2015-01-09 23:16:39 +00:00
fn swap_rows(&mut self, a: usize, b: usize) {
2015-10-04 01:58:53 +00:00
self[0].swap_elems(a, b);
self[1].swap_elems(a, b);
self[2].swap_elems(a, b);
self[3].swap_elems(a, b);
}
}
2015-04-05 01:19:11 +00:00
impl<S: BaseFloat> Matrix<S, Vector2<S>> for Matrix2<S> {
#[inline]
fn from_value(value: S) -> Matrix2<S> {
Matrix2::new(value, S::zero(),
S::zero(), value)
}
#[inline]
fn from_diagonal(value: &Vector2<S>) -> Matrix2<S> {
Matrix2::new(value.x, S::zero(),
S::zero(), value.y)
}
#[inline] fn mul_s(&self, s: S) -> Matrix2<S> { self * s }
#[inline] fn div_s(&self, s: S) -> Matrix2<S> { self / s }
#[inline] fn rem_s(&self, s: S) -> Matrix2<S> { self % s }
#[inline] fn add_m(&self, m: &Matrix2<S>) -> Matrix2<S> { self + m }
#[inline] fn sub_m(&self, m: &Matrix2<S>) -> Matrix2<S> { self - m }
fn mul_m(&self, other: &Matrix2<S>) -> Matrix2<S> { self * other }
#[inline] fn mul_v(&self, v: &Vector2<S>) -> Vector2<S> { self * v }
2013-09-04 04:40:24 +00:00
#[inline]
fn mul_self_s(&mut self, s: S) {
2015-10-04 01:58:53 +00:00
self[0].mul_self_s(s);
self[1].mul_self_s(s);
}
#[inline]
fn div_self_s(&mut self, s: S) {
2015-10-04 01:58:53 +00:00
self[0].div_self_s(s);
self[1].div_self_s(s);
}
#[inline]
fn rem_self_s(&mut self, s: S) {
2015-10-04 01:58:53 +00:00
self[0].rem_self_s(s);
self[1].rem_self_s(s);
}
#[inline]
fn add_self_m(&mut self, m: &Matrix2<S>) {
2015-10-04 01:58:53 +00:00
self[0].add_self_v(&m[0]);
self[1].add_self_v(&m[1]);
}
#[inline]
fn sub_self_m(&mut self, m: &Matrix2<S>) {
2015-10-04 01:58:53 +00:00
self[0].sub_self_v(&m[0]);
self[1].sub_self_v(&m[1]);
}
fn transpose(&self) -> Matrix2<S> {
Matrix2::new(self[0][0], self[1][0],
self[0][1], self[1][1])
}
#[inline]
fn transpose_self(&mut self) {
self.swap_elems((0, 1), (1, 0));
}
#[inline]
2013-08-28 03:56:48 +00:00
fn determinant(&self) -> S {
self[0][0] * self[1][1] - self[1][0] * self[0][1]
}
#[inline]
fn diagonal(&self) -> Vector2<S> {
Vector2::new(self[0][0],
self[1][1])
}
#[inline]
fn invert(&self) -> Option<Matrix2<S>> {
2013-08-28 03:56:48 +00:00
let det = self.determinant();
if det.approx_eq(&S::zero()) {
2013-08-28 03:56:48 +00:00
None
} else {
Some(Matrix2::new( self[1][1] / det, -self[0][1] / det,
-self[1][0] / det, self[0][0] / det))
2013-08-28 03:56:48 +00:00
}
}
#[inline]
fn is_diagonal(&self) -> bool {
2015-10-04 01:58:53 +00:00
self[0][1].approx_eq(&S::zero()) &&
self[1][0].approx_eq(&S::zero())
}
#[inline]
fn is_symmetric(&self) -> bool {
2015-10-04 01:58:53 +00:00
self[0][1].approx_eq(&self[1][0]) &&
self[1][0].approx_eq(&self[0][1])
}
}
2015-04-05 01:19:11 +00:00
impl<S: BaseFloat> Matrix<S, Vector3<S>> for Matrix3<S> {
#[inline]
fn from_value(value: S) -> Matrix3<S> {
Matrix3::new(value, S::zero(), S::zero(),
S::zero(), value, S::zero(),
S::zero(), S::zero(), value)
}
#[inline]
fn from_diagonal(value: &Vector3<S>) -> Matrix3<S> {
Matrix3::new(value.x, S::zero(), S::zero(),
S::zero(), value.y, S::zero(),
S::zero(), S::zero(), value.z)
}
#[inline] fn mul_s(&self, s: S) -> Matrix3<S> { self * s }
#[inline] fn div_s(&self, s: S) -> Matrix3<S> { self / s }
#[inline] fn rem_s(&self, s: S) -> Matrix3<S> { self % s }
#[inline] fn add_m(&self, m: &Matrix3<S>) -> Matrix3<S> { self + m }
#[inline] fn sub_m(&self, m: &Matrix3<S>) -> Matrix3<S> { self - m }
fn mul_m(&self, other: &Matrix3<S>) -> Matrix3<S> { self * other }
#[inline] fn mul_v(&self, v: &Vector3<S>) -> Vector3<S> { self * v}
2013-09-04 04:40:24 +00:00
#[inline]
fn mul_self_s(&mut self, s: S) {
2015-10-04 01:58:53 +00:00
self[0].mul_self_s(s);
self[1].mul_self_s(s);
self[2].mul_self_s(s);
}
#[inline]
fn div_self_s(&mut self, s: S) {
2015-10-04 01:58:53 +00:00
self[0].div_self_s(s);
self[1].div_self_s(s);
self[2].div_self_s(s);
}
#[inline]
fn rem_self_s(&mut self, s: S) {
2015-10-04 01:58:53 +00:00
self[0].rem_self_s(s);
self[1].rem_self_s(s);
self[2].rem_self_s(s);
}
#[inline]
fn add_self_m(&mut self, m: &Matrix3<S>) {
2015-10-04 01:58:53 +00:00
self[0].add_self_v(&m[0]);
self[1].add_self_v(&m[1]);
self[2].add_self_v(&m[2]);
}
#[inline]
fn sub_self_m(&mut self, m: &Matrix3<S>) {
2015-10-04 01:58:53 +00:00
self[0].sub_self_v(&m[0]);
self[1].sub_self_v(&m[1]);
self[2].sub_self_v(&m[2]);
}
fn transpose(&self) -> Matrix3<S> {
Matrix3::new(self[0][0], self[1][0], self[2][0],
self[0][1], self[1][1], self[2][1],
self[0][2], self[1][2], self[2][2])
}
#[inline]
fn transpose_self(&mut self) {
self.swap_elems((0, 1), (1, 0));
self.swap_elems((0, 2), (2, 0));
self.swap_elems((1, 2), (2, 1));
}
2013-08-28 03:56:48 +00:00
fn determinant(&self) -> S {
self[0][0] * (self[1][1] * self[2][2] - self[2][1] * self[1][2]) -
self[1][0] * (self[0][1] * self[2][2] - self[2][1] * self[0][2]) +
self[2][0] * (self[0][1] * self[1][2] - self[1][1] * self[0][2])
}
#[inline]
fn diagonal(&self) -> Vector3<S> {
Vector3::new(self[0][0],
self[1][1],
self[2][2])
}
fn invert(&self) -> Option<Matrix3<S>> {
2013-08-28 03:56:48 +00:00
let det = self.determinant();
if det.approx_eq(&S::zero()) { None } else {
Some(Matrix3::from_cols(&self[1].cross(&self[2]) / det,
&self[2].cross(&self[0]) / det,
&self[0].cross(&self[1]) / det).transpose())
2013-08-28 03:56:48 +00:00
}
}
fn is_diagonal(&self) -> bool {
2015-10-04 01:58:53 +00:00
self[0][1].approx_eq(&S::zero()) &&
self[0][2].approx_eq(&S::zero()) &&
2015-10-04 01:58:53 +00:00
self[1][0].approx_eq(&S::zero()) &&
self[1][2].approx_eq(&S::zero()) &&
2015-10-04 01:58:53 +00:00
self[2][0].approx_eq(&S::zero()) &&
self[2][1].approx_eq(&S::zero())
}
fn is_symmetric(&self) -> bool {
2015-10-04 01:58:53 +00:00
self[0][1].approx_eq(&self[1][0]) &&
self[0][2].approx_eq(&self[2][0]) &&
2015-10-04 01:58:53 +00:00
self[1][0].approx_eq(&self[0][1]) &&
self[1][2].approx_eq(&self[2][1]) &&
2015-10-04 01:58:53 +00:00
self[2][0].approx_eq(&self[0][2]) &&
self[2][1].approx_eq(&self[1][2])
}
}
2015-04-05 01:19:11 +00:00
impl<S: BaseFloat> Matrix<S, Vector4<S>> for Matrix4<S> {
#[inline]
fn from_value(value: S) -> Matrix4<S> {
Matrix4::new(value, S::zero(), S::zero(), S::zero(),
S::zero(), value, S::zero(), S::zero(),
S::zero(), S::zero(), value, S::zero(),
S::zero(), S::zero(), S::zero(), value)
}
#[inline]
fn from_diagonal(value: &Vector4<S>) -> Matrix4<S> {
Matrix4::new(value.x, S::zero(), S::zero(), S::zero(),
S::zero(), value.y, S::zero(), S::zero(),
S::zero(), S::zero(), value.z, S::zero(),
S::zero(), S::zero(), S::zero(), value.w)
}
#[inline] fn mul_s(&self, s: S) -> Matrix4<S> { self * s }
#[inline] fn div_s(&self, s: S) -> Matrix4<S> { self / s }
#[inline] fn rem_s(&self, s: S) -> Matrix4<S> { self % s }
#[inline] fn add_m(&self, m: &Matrix4<S>) -> Matrix4<S> { self + m }
#[inline] fn sub_m(&self, m: &Matrix4<S>) -> Matrix4<S> { self - m }
fn mul_m(&self, other: &Matrix4<S>) -> Matrix4<S> { self * other }
#[inline] fn mul_v(&self, v: &Vector4<S>) -> Vector4<S> { self * v }
2013-09-04 04:40:24 +00:00
#[inline]
fn mul_self_s(&mut self, s: S) {
2015-10-04 01:58:53 +00:00
self[0].mul_self_s(s);
self[1].mul_self_s(s);
self[2].mul_self_s(s);
self[3].mul_self_s(s);
}
#[inline]
fn div_self_s(&mut self, s: S) {
2015-10-04 01:58:53 +00:00
self[0].div_self_s(s);
self[1].div_self_s(s);
self[2].div_self_s(s);
self[3].div_self_s(s);
}
#[inline]
fn rem_self_s(&mut self, s: S) {
2015-10-04 01:58:53 +00:00
self[0].rem_self_s(s);
self[1].rem_self_s(s);
self[2].rem_self_s(s);
self[3].rem_self_s(s);
}
#[inline]
fn add_self_m(&mut self, m: &Matrix4<S>) {
2015-10-04 01:58:53 +00:00
self[0].add_self_v(&m[0]);
self[1].add_self_v(&m[1]);
self[2].add_self_v(&m[2]);
self[3].add_self_v(&m[3]);
}
#[inline]
fn sub_self_m(&mut self, m: &Matrix4<S>) {
2015-10-04 01:58:53 +00:00
self[0].sub_self_v(&m[0]);
self[1].sub_self_v(&m[1]);
self[2].sub_self_v(&m[2]);
self[3].sub_self_v(&m[3]);
}
fn transpose(&self) -> Matrix4<S> {
Matrix4::new(self[0][0], self[1][0], self[2][0], self[3][0],
self[0][1], self[1][1], self[2][1], self[3][1],
self[0][2], self[1][2], self[2][2], self[3][2],
self[0][3], self[1][3], self[2][3], self[3][3])
}
fn transpose_self(&mut self) {
self.swap_elems((0, 1), (1, 0));
self.swap_elems((0, 2), (2, 0));
self.swap_elems((0, 3), (3, 0));
self.swap_elems((1, 2), (2, 1));
self.swap_elems((1, 3), (3, 1));
self.swap_elems((2, 3), (3, 2));
}
2013-08-28 03:56:48 +00:00
fn determinant(&self) -> S {
let m0 = Matrix3::new(self[1][1], self[2][1], self[3][1],
self[1][2], self[2][2], self[3][2],
self[1][3], self[2][3], self[3][3]);
let m1 = Matrix3::new(self[0][1], self[2][1], self[3][1],
self[0][2], self[2][2], self[3][2],
self[0][3], self[2][3], self[3][3]);
let m2 = Matrix3::new(self[0][1], self[1][1], self[3][1],
self[0][2], self[1][2], self[3][2],
self[0][3], self[1][3], self[3][3]);
let m3 = Matrix3::new(self[0][1], self[1][1], self[2][1],
self[0][2], self[1][2], self[2][2],
self[0][3], self[1][3], self[2][3]);
self[0][0] * m0.determinant() -
self[1][0] * m1.determinant() +
self[2][0] * m2.determinant() -
self[3][0] * m3.determinant()
}
#[inline]
fn diagonal(&self) -> Vector4<S> {
Vector4::new(self[0][0],
self[1][1],
self[2][2],
self[3][3])
}
fn invert(&self) -> Option<Matrix4<S>> {
let det = self.determinant();
2015-09-30 10:39:10 +00:00
if det.approx_eq(&S::zero()) { None } else {
let inv_det = S::one() / det;
let t = self.transpose();
2015-03-01 18:28:38 +00:00
let cf = |i, j| {
let mat = match i {
2015-09-30 10:39:10 +00:00
0 => Matrix3::from_cols(t.y.truncate_n(j), t.z.truncate_n(j), t.w.truncate_n(j)),
1 => Matrix3::from_cols(t.x.truncate_n(j), t.z.truncate_n(j), t.w.truncate_n(j)),
2 => Matrix3::from_cols(t.x.truncate_n(j), t.y.truncate_n(j), t.w.truncate_n(j)),
3 => Matrix3::from_cols(t.x.truncate_n(j), t.y.truncate_n(j), t.z.truncate_n(j)),
_ => panic!("out of range"),
};
let sign = if (i + j) & 1 == 1 { -S::one() } else { S::one() };
mat.determinant() * sign * inv_det
};
Some(Matrix4::new(cf(0, 0), cf(0, 1), cf(0, 2), cf(0, 3),
cf(1, 0), cf(1, 1), cf(1, 2), cf(1, 3),
cf(2, 0), cf(2, 1), cf(2, 2), cf(2, 3),
cf(3, 0), cf(3, 1), cf(3, 2), cf(3, 3)))
2013-08-28 03:56:48 +00:00
}
}
fn is_diagonal(&self) -> bool {
2015-10-04 01:58:53 +00:00
self[0][1].approx_eq(&S::zero()) &&
self[0][2].approx_eq(&S::zero()) &&
self[0][3].approx_eq(&S::zero()) &&
2015-10-04 01:58:53 +00:00
self[1][0].approx_eq(&S::zero()) &&
self[1][2].approx_eq(&S::zero()) &&
self[1][3].approx_eq(&S::zero()) &&
2015-10-04 01:58:53 +00:00
self[2][0].approx_eq(&S::zero()) &&
self[2][1].approx_eq(&S::zero()) &&
self[2][3].approx_eq(&S::zero()) &&
2015-10-04 01:58:53 +00:00
self[3][0].approx_eq(&S::zero()) &&
self[3][1].approx_eq(&S::zero()) &&
self[3][2].approx_eq(&S::zero())
}
fn is_symmetric(&self) -> bool {
2015-10-04 01:58:53 +00:00
self[0][1].approx_eq(&self[1][0]) &&
self[0][2].approx_eq(&self[2][0]) &&
self[0][3].approx_eq(&self[3][0]) &&
2015-10-04 01:58:53 +00:00
self[1][0].approx_eq(&self[0][1]) &&
self[1][2].approx_eq(&self[2][1]) &&
self[1][3].approx_eq(&self[3][1]) &&
2015-10-04 01:58:53 +00:00
self[2][0].approx_eq(&self[0][2]) &&
self[2][1].approx_eq(&self[1][2]) &&
self[2][3].approx_eq(&self[3][2]) &&
2015-10-04 01:58:53 +00:00
self[3][0].approx_eq(&self[0][3]) &&
self[3][1].approx_eq(&self[1][3]) &&
self[3][2].approx_eq(&self[2][3])
}
}
impl<S: BaseFloat> ApproxEq for Matrix2<S> {
type Epsilon = S;
#[inline]
fn approx_eq_eps(&self, other: &Matrix2<S>, epsilon: &S) -> bool {
self[0].approx_eq_eps(&other[0], epsilon) &&
self[1].approx_eq_eps(&other[1], epsilon)
}
}
impl<S: BaseFloat> ApproxEq for Matrix3<S> {
type Epsilon = S;
#[inline]
fn approx_eq_eps(&self, other: &Matrix3<S>, epsilon: &S) -> bool {
self[0].approx_eq_eps(&other[0], epsilon) &&
self[1].approx_eq_eps(&other[1], epsilon) &&
self[2].approx_eq_eps(&other[2], epsilon)
}
}
impl<S: BaseFloat> ApproxEq for Matrix4<S> {
type Epsilon = S;
#[inline]
fn approx_eq_eps(&self, other: &Matrix4<S>, epsilon: &S) -> bool {
self[0].approx_eq_eps(&other[0], epsilon) &&
self[1].approx_eq_eps(&other[1], epsilon) &&
self[2].approx_eq_eps(&other[2], epsilon) &&
self[3].approx_eq_eps(&other[3], epsilon)
}
}
impl<S: Neg<Output = S>> Neg for Matrix2<S> {
type Output = Matrix2<S>;
#[inline]
fn neg(self) -> Matrix2<S> {
Matrix2::from_cols(-self.x, -self.y)
}
}
impl<S: Neg<Output = S>> Neg for Matrix3<S> {
type Output = Matrix3<S>;
#[inline]
fn neg(self) -> Matrix3<S> {
Matrix3::from_cols(-self.x, -self.y, -self.z)
}
}
impl<S: Neg<Output = S>> Neg for Matrix4<S> {
type Output = Matrix4<S>;
#[inline]
fn neg(self) -> Matrix4<S> {
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<S> for &'a $MatrixN<S> {
type Output = $MatrixN<S>;
#[inline]
fn $binop(self, s: S) -> $MatrixN<S> {
$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<S>> for &'b $MatrixN<S> {
type Output = $MatrixN<S>;
#[inline]
fn $binop(self, other: &'a $MatrixN<S>) -> $MatrixN<S> {
$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<S>> for &'b Matrix2<S> {
type Output = Vector2<S>;
fn mul(self, v: &'a Vector2<S>) -> Vector2<S> {
Vector2::new(self.row(0).dot(v),
self.row(1).dot(v))
}
}
impl<'a, 'b, S: BaseNum> Mul<&'a Vector3<S>> for &'b Matrix3<S> {
type Output = Vector3<S>;
fn mul(self, v: &'a Vector3<S>) -> Vector3<S> {
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<S>> for &'b Matrix4<S> {
type Output = Vector4<S>;
fn mul(self, v: &'a Vector4<S>) -> Vector4<S> {
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<S>> for &'b Matrix2<S> {
type Output = Matrix2<S>;
fn mul(self, other: &'a Matrix2<S>) -> Matrix2<S> {
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<S>> for &'b Matrix3<S> {
type Output = Matrix3<S>;
fn mul(self, other: &'a Matrix3<S>) -> Matrix3<S> {
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<S>> for &'b Matrix4<S> {
type Output = Matrix4<S>;
fn mul(self, other: &'a Matrix4<S>) -> Matrix4<S> {
2015-09-30 10:06:17 +00:00
// Using self.row(0).dot(other[0]) like the other matrix multiplies
// causes the LLVM to miss identical loads and multiplies. This optimization
// causes the code to be auto vectorized properly increasing the performance
// around ~4 times.
macro_rules! dot_matrix4 {
($A:expr, $B:expr, $I:expr, $J:expr) => {
($A[0][$I]) * ($B[$J][0]) +
($A[1][$I]) * ($B[$J][1]) +
($A[2][$I]) * ($B[$J][2]) +
($A[3][$I]) * ($B[$J][3])
};
};
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 {
2015-09-20 21:56:03 +00:00
($MatrixN:ident<$S:ident>, $n:expr, $Output:ty, $I:ty) => {
impl<$S> Index<$I> for $MatrixN<$S> {
type Output = $Output;
#[inline]
2015-09-20 21:56:03 +00:00
fn index<'a>(&'a self, i: $I) -> &'a $Output {
let v: &[[$S; $n]; $n] = self.as_ref();
From::from(&v[i])
}
}
2015-09-20 21:56:03 +00:00
impl<$S> IndexMut<$I> for $MatrixN<$S> {
#[inline]
2015-09-20 21:56:03 +00:00
fn index_mut<'a>(&'a mut self, i: $I) -> &'a mut $Output {
let v: &mut [[$S; $n]; $n] = self.as_mut();
From::from(&mut v[i])
}
}
2015-09-20 21:56:03 +00:00
}
}
2015-09-20 21:56:03 +00:00
index_operators!(Matrix2<S>, 2, Vector2<S>, usize);
index_operators!(Matrix3<S>, 3, Vector3<S>, usize);
index_operators!(Matrix4<S>, 4, Vector4<S>, usize);
// index_operators!(Matrix2<S>, 2, [Vector2<S>], Range<usize>);
// index_operators!(Matrix3<S>, 3, [Vector3<S>], Range<usize>);
// index_operators!(Matrix4<S>, 4, [Vector4<S>], Range<usize>);
// index_operators!(Matrix2<S>, 2, [Vector2<S>], RangeTo<usize>);
// index_operators!(Matrix3<S>, 3, [Vector3<S>], RangeTo<usize>);
// index_operators!(Matrix4<S>, 4, [Vector4<S>], RangeTo<usize>);
// index_operators!(Matrix2<S>, 2, [Vector2<S>], RangeFrom<usize>);
// index_operators!(Matrix3<S>, 3, [Vector3<S>], RangeFrom<usize>);
// index_operators!(Matrix4<S>, 4, [Vector4<S>], RangeFrom<usize>);
// index_operators!(Matrix2<S>, 2, [Vector2<S>], RangeFull);
// index_operators!(Matrix3<S>, 3, [Vector3<S>], RangeFull);
// index_operators!(Matrix4<S>, 4, [Vector4<S>], RangeFull);
macro_rules! fixed_array_conversions {
($MatrixN:ident <$S:ident> { $($field:ident : $index:expr),+ }, $n:expr) => {
impl<$S> Into<[[$S; $n]; $n]> for $MatrixN<$S> {
#[inline]
fn into(self) -> [[$S; $n]; $n] {
match self { $MatrixN { $($field),+ } => [$($field.into()),+] }
}
}
impl<$S> AsRef<[[$S; $n]; $n]> for $MatrixN<$S> {
#[inline]
fn as_ref(&self) -> &[[$S; $n]; $n] {
unsafe { mem::transmute(self) }
}
}
impl<$S> AsMut<[[$S; $n]; $n]> for $MatrixN<$S> {
#[inline]
fn as_mut(&mut self) -> &mut [[$S; $n]; $n] {
unsafe { mem::transmute(self) }
}
}
impl<$S: Copy> From<[[$S; $n]; $n]> for $MatrixN<$S> {
#[inline]
fn from(m: [[$S; $n]; $n]) -> $MatrixN<$S> {
// We need to use a copy here because we can't pattern match on arrays yet
$MatrixN { $($field: From::from(m[$index])),+ }
}
}
impl<'a, $S> From<&'a [[$S; $n]; $n]> for &'a $MatrixN<$S> {
#[inline]
fn from(m: &'a [[$S; $n]; $n]) -> &'a $MatrixN<$S> {
unsafe { mem::transmute(m) }
}
}
impl<'a, $S> From<&'a mut [[$S; $n]; $n]> for &'a mut $MatrixN<$S> {
#[inline]
fn from(m: &'a mut [[$S; $n]; $n]) -> &'a mut $MatrixN<$S> {
unsafe { mem::transmute(m) }
}
}
// impl<$S> Into<[$S; ($n * $n)]> for $MatrixN<$S> {
// #[inline]
// fn into(self) -> [[$S; $n]; $n] {
// // TODO: Not sure how to implement this...
// unimplemented!()
// }
// }
impl<$S> AsRef<[$S; ($n * $n)]> for $MatrixN<$S> {
#[inline]
fn as_ref(&self) -> &[$S; ($n * $n)] {
unsafe { mem::transmute(self) }
}
}
impl<$S> AsMut<[$S; ($n * $n)]> for $MatrixN<$S> {
#[inline]
fn as_mut(&mut self) -> &mut [$S; ($n * $n)] {
unsafe { mem::transmute(self) }
}
}
// impl<$S> From<[$S; ($n * $n)]> for $MatrixN<$S> {
// #[inline]
// fn from(m: [$S; ($n * $n)]) -> $MatrixN<$S> {
// // TODO: Not sure how to implement this...
// unimplemented!()
// }
// }
impl<'a, $S> From<&'a [$S; ($n * $n)]> for &'a $MatrixN<$S> {
#[inline]
fn from(m: &'a [$S; ($n * $n)]) -> &'a $MatrixN<$S> {
unsafe { mem::transmute(m) }
}
}
impl<'a, $S> From<&'a mut [$S; ($n * $n)]> for &'a mut $MatrixN<$S> {
#[inline]
fn from(m: &'a mut [$S; ($n * $n)]) -> &'a mut $MatrixN<$S> {
unsafe { mem::transmute(m) }
}
}
}
}
fixed_array_conversions!(Matrix2<S> { x:0, y:1 }, 2);
fixed_array_conversions!(Matrix3<S> { x:0, y:1, z:2 }, 3);
fixed_array_conversions!(Matrix4<S> { x:0, y:1, z:2, w:3 }, 4);
2015-05-06 08:27:52 +00:00
impl<S: BaseFloat> From<Matrix2<S>> for Matrix3<S> {
/// Clone the elements of a 2-dimensional matrix into the top-left corner
/// of a 3-dimensional identity matrix.
2015-05-06 08:27:52 +00:00
fn from(m: Matrix2<S>) -> Matrix3<S> {
Matrix3::new(m[0][0], m[0][1], S::zero(),
m[1][0], m[1][1], S::zero(),
S::zero(), S::zero(), S::one())
2013-09-07 05:04:33 +00:00
}
}
2015-05-06 08:27:52 +00:00
impl<S: BaseFloat> From<Matrix2<S>> for Matrix4<S> {
/// Clone the elements of a 2-dimensional matrix into the top-left corner
/// of a 4-dimensional identity matrix.
2015-05-06 08:27:52 +00:00
fn from(m: Matrix2<S>) -> Matrix4<S> {
Matrix4::new(m[0][0], m[0][1], S::zero(), S::zero(),
m[1][0], m[1][1], S::zero(), S::zero(),
S::zero(), S::zero(), S::one(), S::zero(),
S::zero(), S::zero(), S::zero(), S::one())
2013-09-07 05:04:33 +00:00
}
}
2015-05-06 08:27:52 +00:00
impl<S: BaseFloat> From<Matrix3<S>> for Matrix4<S> {
/// Clone the elements of a 3-dimensional matrix into the top-left corner
/// of a 4-dimensional identity matrix.
2015-05-06 08:27:52 +00:00
fn from(m: Matrix3<S>) -> Matrix4<S> {
Matrix4::new(m[0][0], m[0][1], m[0][2], S::zero(),
m[1][0], m[1][1], m[1][2], S::zero(),
m[2][0], m[2][1], m[2][2], S::zero(),
S::zero(), S::zero(), S::zero(), S::one())
2013-09-07 05:04:33 +00:00
}
}
2015-05-06 08:38:15 +00:00
impl<S: BaseFloat> From<Matrix3<S>> for Quaternion<S> {
/// Convert the matrix to a quaternion
2015-05-06 08:38:15 +00:00
fn from(mat: Matrix3<S>) -> Quaternion<S> {
// http://www.cs.ucr.edu/~vbz/resources/quatut.pdf
2015-05-06 08:38:15 +00:00
let trace = mat.trace();
2014-06-26 04:26:15 +00:00
let half: S = cast(0.5f64).unwrap();
if trace >= S::zero() {
let s = (S::one() + trace).sqrt();
let w = half * s;
let s = half / s;
2015-05-06 08:38:15 +00:00
let x = (mat[1][2] - mat[2][1]) * s;
let y = (mat[2][0] - mat[0][2]) * s;
let z = (mat[0][1] - mat[1][0]) * s;
Quaternion::new(w, x, y, z)
2015-05-06 08:38:15 +00:00
} else if (mat[0][0] > mat[1][1]) && (mat[0][0] > mat[2][2]) {
let s = (half + (mat[0][0] - mat[1][1] - mat[2][2])).sqrt();
let w = half * s;
let s = half / s;
2015-05-06 08:38:15 +00:00
let x = (mat[0][1] - mat[1][0]) * s;
let y = (mat[2][0] - mat[0][2]) * s;
let z = (mat[1][2] - mat[2][1]) * s;
Quaternion::new(w, x, y, z)
2015-05-06 08:38:15 +00:00
} else if mat[1][1] > mat[2][2] {
let s = (half + (mat[1][1] - mat[0][0] - mat[2][2])).sqrt();
let w = half * s;
let s = half / s;
2015-05-06 08:38:15 +00:00
let x = (mat[0][1] - mat[1][0]) * s;
let y = (mat[1][2] - mat[2][1]) * s;
let z = (mat[2][0] - mat[0][2]) * s;
Quaternion::new(w, x, y, z)
} else {
2015-05-06 08:38:15 +00:00
let s = (half + (mat[2][2] - mat[0][0] - mat[1][1])).sqrt();
let w = half * s;
let s = half / s;
2015-05-06 08:38:15 +00:00
let x = (mat[2][0] - mat[0][2]) * s;
let y = (mat[1][2] - mat[2][1]) * s;
let z = (mat[0][1] - mat[1][0]) * s;
Quaternion::new(w, x, y, z)
2013-09-18 10:52:07 +00:00
}
}
}
2015-02-08 18:19:32 +00:00
impl<S: BaseNum> fmt::Debug for Matrix2<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2015-01-09 22:06:45 +00:00
write!(f, "[[{:?}, {:?}], [{:?}, {:?}]]",
self[0][0], self[0][1],
self[1][0], self[1][1])
}
}
2015-02-08 18:19:32 +00:00
impl<S: BaseNum> fmt::Debug for Matrix3<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2015-01-09 22:06:45 +00:00
write!(f, "[[{:?}, {:?}, {:?}], [{:?}, {:?}, {:?}], [{:?}, {:?}, {:?}]]",
self[0][0], self[0][1], self[0][2],
self[1][0], self[1][1], self[1][2],
self[2][0], self[2][1], self[2][2])
}
}
2015-02-08 18:19:32 +00:00
impl<S: BaseNum> fmt::Debug for Matrix4<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2015-01-09 22:06:45 +00:00
write!(f, "[[{:?}, {:?}, {:?}, {:?}], [{:?}, {:?}, {:?}, {:?}], [{:?}, {:?}, {:?}, {:?}], [{:?}, {:?}, {:?}, {:?}]]",
self[0][0], self[0][1], self[0][2], self[0][3],
self[1][0], self[1][1], self[1][2], self[1][3],
self[2][0], self[2][1], self[2][2], self[2][3],
self[3][0], self[3][1], self[3][2], self[3][3])
}
}
2015-03-15 02:53:57 +00:00
impl<S: BaseFloat + Rand> Rand for Matrix2<S> {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> Matrix2<S> {
Matrix2{ x: rng.gen(), y: rng.gen() }
}
}
impl<S: BaseFloat + Rand> Rand for Matrix3<S> {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> Matrix3<S> {
Matrix3{ x: rng.gen(), y: rng.gen(), z: rng.gen() }
}
}
impl<S: BaseFloat + Rand> Rand for Matrix4<S> {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> Matrix4<S> {
Matrix4{ x: rng.gen(), y: rng.gen(), z: rng.gen(), w: rng.gen() }
}
}