Replace ToMatrix* by Into

This commit is contained in:
Pierre Krieger 2015-05-06 10:27:52 +02:00
parent e5822e3864
commit 8ab8d7551d
6 changed files with 115 additions and 128 deletions

View file

@ -1326,53 +1326,35 @@ impl<S: BaseFloat> ApproxEq<S> for Matrix4<S> {
// Conversion traits
/// Represents types which can be converted to a Matrix2
pub trait ToMatrix2<S: BaseNum> {
/// Convert this value to a Matrix2
fn to_matrix2(&self) -> Matrix2<S>;
}
/// Represents types which can be converted to a Matrix3
pub trait ToMatrix3<S: BaseNum> {
/// Convert this value to a Matrix3
fn to_matrix3(&self) -> Matrix3<S>;
}
/// Represents types which can be converted to a Matrix4
pub trait ToMatrix4<S: BaseNum> {
/// Convert this value to a Matrix4
fn to_matrix4(&self) -> Matrix4<S>;
}
impl<S: BaseFloat> ToMatrix3<S> for Matrix2<S> {
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.
fn to_matrix3(&self) -> Matrix3<S> {
Matrix3::new(self[0][0], self[0][1], zero(),
self[1][0], self[1][1], zero(),
zero(), zero(), one())
fn from(m: Matrix2<S>) -> Matrix3<S> {
Matrix3::new(m[0][0], m[0][1], zero(),
m[1][0], m[1][1], zero(),
zero(), zero(), one())
}
}
impl<S: BaseFloat> ToMatrix4<S> for Matrix2<S> {
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.
fn to_matrix4(&self) -> Matrix4<S> {
Matrix4::new(self[0][0], self[0][1], zero(), zero(),
self[1][0], self[1][1], zero(), zero(),
zero(), zero(), one(), zero(),
zero(), zero(), zero(), one())
fn from(m: Matrix2<S>) -> Matrix4<S> {
Matrix4::new(m[0][0], m[0][1], zero(), zero(),
m[1][0], m[1][1], zero(), zero(),
zero(), zero(), one(), zero(),
zero(), zero(), zero(), one())
}
}
impl<S: BaseFloat> ToMatrix4<S> for Matrix3<S> {
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.
fn to_matrix4(&self) -> Matrix4<S> {
Matrix4::new(self[0][0], self[0][1], self[0][2], zero(),
self[1][0], self[1][1], self[1][2], zero(),
self[2][0], self[2][1], self[2][2], zero(),
zero(), zero(), zero(), one())
fn from(m: Matrix3<S>) -> Matrix4<S> {
Matrix4::new(m[0][0], m[0][1], m[0][2], zero(),
m[1][0], m[1][1], m[1][2], zero(),
m[2][0], m[2][1], m[2][2], zero(),
zero(), zero(), zero(), one())
}
}

View file

@ -18,7 +18,7 @@ use rust_num::traits::cast;
use angle::{Angle, Rad, tan, cot};
use frustum::Frustum;
use matrix::{Matrix4, ToMatrix4};
use matrix::Matrix4;
use num::BaseFloat;
use plane::Plane;
@ -32,7 +32,7 @@ pub fn perspective<S: BaseFloat + 'static, A: Angle<S>>(fovy: A, aspect: S, near
aspect: aspect,
near: near,
far: far,
}.to_matrix4()
}.into()
}
/// Create a perspective matrix from a view frustrum.
@ -47,7 +47,7 @@ pub fn frustum<S: BaseFloat + 'static>(left: S, right: S, bottom: S, top: S, nea
top: top,
near: near,
far: far,
}.to_matrix4()
}.into()
}
/// Create an orthographic projection matrix.
@ -62,10 +62,10 @@ pub fn ortho<S: BaseFloat + 'static>(left: S, right: S, bottom: S, top: S, near:
top: top,
near: near,
far: far,
}.to_matrix4()
}.into()
}
pub trait Projection<S>: ToMatrix4<S> {
pub trait Projection<S>: Into<Matrix4<S>> {
fn to_frustum(&self) -> Frustum<S>;
}
@ -99,26 +99,26 @@ impl<S: BaseFloat, A: Angle<S>> PerspectiveFov<S, A> {
impl<S: BaseFloat + 'static, A: Angle<S>> Projection<S> for PerspectiveFov<S, A> {
fn to_frustum(&self) -> Frustum<S> {
// TODO: Could this be faster?
Frustum::from_matrix4(self.to_matrix4()).unwrap()
Frustum::from_matrix4(self.clone().into()).unwrap()
}
}
impl<S: BaseFloat, A: Angle<S>> ToMatrix4<S> for PerspectiveFov<S, A> {
fn to_matrix4(&self) -> Matrix4<S> {
impl<S: BaseFloat, A: Angle<S>> From<PerspectiveFov<S, A>> for Matrix4<S> {
fn from(persp: PerspectiveFov<S, A>) -> Matrix4<S> {
let half_turn: A = Angle::turn_div_2();
assert!(self.fovy > zero(), "The vertical field of view cannot be below zero, found: {:?}", self.fovy);
assert!(self.fovy < half_turn, "The vertical field of view cannot be greater than a half turn, found: {:?}", self.fovy);
assert!(self.aspect > zero(), "The aspect ratio cannot be below zero, found: {:?}", self.aspect);
assert!(self.near > zero(), "The near plane distance cannot be below zero, found: {:?}", self.near);
assert!(self.far > zero(), "The far plane distance cannot be below zero, found: {:?}", self.far);
assert!(self.far > self.near, "The far plane cannot be closer than the near plane, found: far: {:?}, near: {:?}", self.far, self.near);
assert!(persp.fovy > zero(), "The vertical field of view cannot be below zero, found: {:?}", persp.fovy);
assert!(persp.fovy < half_turn, "The vertical field of view cannot be greater than a half turn, found: {:?}", persp.fovy);
assert!(persp.aspect > zero(), "The aspect ratio cannot be below zero, found: {:?}", persp.aspect);
assert!(persp.near > zero(), "The near plane distance cannot be below zero, found: {:?}", persp.near);
assert!(persp.far > zero(), "The far plane distance cannot be below zero, found: {:?}", persp.far);
assert!(persp.far > persp.near, "The far plane cannot be closer than the near plane, found: far: {:?}, near: {:?}", persp.far, persp.near);
let f: Rad<_> = self.fovy.div_s(cast(2i8).unwrap()).into();
let f: Rad<_> = persp.fovy.div_s(cast(2i8).unwrap()).into();
let f = cot(f);
let two: S = cast(2i8).unwrap();
let c0r0 = f / self.aspect;
let c0r0 = f / persp.aspect;
let c0r1 = zero();
let c0r2 = zero();
let c0r3 = zero();
@ -130,12 +130,12 @@ impl<S: BaseFloat, A: Angle<S>> ToMatrix4<S> for PerspectiveFov<S, A> {
let c2r0 = zero();
let c2r1 = zero();
let c2r2 = (self.far + self.near) / (self.near - self.far);
let c2r2 = (persp.far + persp.near) / (persp.near - persp.far);
let c2r3 = -one::<S>();
let c3r0 = zero();
let c3r1 = zero();
let c3r2 = (two * self.far * self.near) / (self.near - self.far);
let c3r2 = (two * persp.far * persp.near) / (persp.near - persp.far);
let c3r3 = zero();
Matrix4::new(c0r0, c0r1, c0r2, c0r3,
@ -159,36 +159,36 @@ pub struct Perspective<S> {
impl<S: BaseFloat + 'static> Projection<S> for Perspective<S> {
fn to_frustum(&self) -> Frustum<S> {
// TODO: Could this be faster?
Frustum::from_matrix4(self.to_matrix4()).unwrap()
Frustum::from_matrix4(self.clone().into()).unwrap()
}
}
impl<S: BaseFloat + 'static> ToMatrix4<S> for Perspective<S> {
fn to_matrix4(&self) -> Matrix4<S> {
assert!(self.left <= self.right, "`left` cannot be greater than `right`, found: left: {:?} right: {:?}", self.left, self.right);
assert!(self.bottom <= self.top, "`bottom` cannot be greater than `top`, found: bottom: {:?} top: {:?}", self.bottom, self.top);
assert!(self.near <= self.far, "`near` cannot be greater than `far`, found: near: {:?} far: {:?}", self.near, self.far);
impl<S: BaseFloat + 'static> From<Perspective<S>> for Matrix4<S> {
fn from(persp: Perspective<S>) -> Matrix4<S> {
assert!(persp.left <= persp.right, "`left` cannot be greater than `right`, found: left: {:?} right: {:?}", persp.left, persp.right);
assert!(persp.bottom <= persp.top, "`bottom` cannot be greater than `top`, found: bottom: {:?} top: {:?}", persp.bottom, persp.top);
assert!(persp.near <= persp.far, "`near` cannot be greater than `far`, found: near: {:?} far: {:?}", persp.near, persp.far);
let two: S = cast(2i8).unwrap();
let c0r0 = (two * self.near) / (self.right - self.left);
let c0r0 = (two * persp.near) / (persp.right - persp.left);
let c0r1 = zero();
let c0r2 = zero();
let c0r3 = zero();
let c1r0 = zero();
let c1r1 = (two * self.near) / (self.top - self.bottom);
let c1r1 = (two * persp.near) / (persp.top - persp.bottom);
let c1r2 = zero();
let c1r3 = zero();
let c2r0 = (self.right + self.left) / (self.right - self.left);
let c2r1 = (self.top + self.bottom) / (self.top - self.bottom);
let c2r2 = -(self.far + self.near) / (self.far - self.near);
let c2r0 = (persp.right + persp.left) / (persp.right - persp.left);
let c2r1 = (persp.top + persp.bottom) / (persp.top - persp.bottom);
let c2r2 = -(persp.far + persp.near) / (persp.far - persp.near);
let c2r3 = -one::<S>();
let c3r0 = zero();
let c3r1 = zero();
let c3r2 = -(two * self.far * self.near) / (self.far - self.near);
let c3r2 = -(two * persp.far * persp.near) / (persp.far - persp.near);
let c3r3 = zero();
Matrix4::new(c0r0, c0r1, c0r2, c0r3,
@ -222,28 +222,28 @@ impl<S: BaseFloat> Projection<S> for Ortho<S> {
}
}
impl<S: BaseFloat> ToMatrix4<S> for Ortho<S> {
fn to_matrix4(&self) -> Matrix4<S> {
impl<S: BaseFloat> From<Ortho<S>> for Matrix4<S> {
fn from(ortho: Ortho<S>) -> Matrix4<S> {
let two: S = cast(2i8).unwrap();
let c0r0 = two / (self.right - self.left);
let c0r0 = two / (ortho.right - ortho.left);
let c0r1 = zero();
let c0r2 = zero();
let c0r3 = zero();
let c1r0 = zero();
let c1r1 = two / (self.top - self.bottom);
let c1r1 = two / (ortho.top - ortho.bottom);
let c1r2 = zero();
let c1r3 = zero();
let c2r0 = zero();
let c2r1 = zero();
let c2r2 = -two / (self.far - self.near);
let c2r2 = -two / (ortho.far - ortho.near);
let c2r3 = zero();
let c3r0 = -(self.right + self.left) / (self.right - self.left);
let c3r1 = -(self.top + self.bottom) / (self.top - self.bottom);
let c3r2 = -(self.far + self.near) / (self.far - self.near);
let c3r0 = -(ortho.right + ortho.left) / (ortho.right - ortho.left);
let c3r1 = -(ortho.top + ortho.bottom) / (ortho.top - ortho.bottom);
let c3r2 = -(ortho.far + ortho.near) / (ortho.far - ortho.near);
let c3r3 = one::<S>();
Matrix4::new(c0r0, c0r1, c0r2, c0r3,

View file

@ -25,7 +25,7 @@ use rust_num::traits::cast;
use angle::{Angle, Rad, acos, sin, sin_cos, rad};
use approx::ApproxEq;
use array::Array1;
use matrix::{Matrix3, ToMatrix3, ToMatrix4, Matrix4};
use matrix::{Matrix3, Matrix4};
use num::BaseFloat;
use point::Point3;
use rotation::{Rotation, Rotation3, Basis3, ToBasis3};
@ -310,24 +310,24 @@ impl<S: BaseFloat> Quaternion<S> {
}
}
impl<S: BaseFloat> ToMatrix3<S> for Quaternion<S> {
impl<S: BaseFloat> From<Quaternion<S>> for Matrix3<S> {
/// Convert the quaternion to a 3 x 3 rotation matrix
fn to_matrix3(&self) -> Matrix3<S> {
let x2 = self.v.x + self.v.x;
let y2 = self.v.y + self.v.y;
let z2 = self.v.z + self.v.z;
fn from(quat: Quaternion<S>) -> Matrix3<S> {
let x2 = quat.v.x + quat.v.x;
let y2 = quat.v.y + quat.v.y;
let z2 = quat.v.z + quat.v.z;
let xx2 = x2 * self.v.x;
let xy2 = x2 * self.v.y;
let xz2 = x2 * self.v.z;
let xx2 = x2 * quat.v.x;
let xy2 = x2 * quat.v.y;
let xz2 = x2 * quat.v.z;
let yy2 = y2 * self.v.y;
let yz2 = y2 * self.v.z;
let zz2 = z2 * self.v.z;
let yy2 = y2 * quat.v.y;
let yz2 = y2 * quat.v.z;
let zz2 = z2 * quat.v.z;
let sy2 = y2 * self.s;
let sz2 = z2 * self.s;
let sx2 = x2 * self.s;
let sy2 = y2 * quat.s;
let sz2 = z2 * quat.s;
let sx2 = x2 * quat.s;
Matrix3::new(one::<S>() - yy2 - zz2, xy2 + sz2, xz2 - sy2,
xy2 - sz2, one::<S>() - xx2 - zz2, yz2 + sx2,
@ -335,24 +335,24 @@ impl<S: BaseFloat> ToMatrix3<S> for Quaternion<S> {
}
}
impl<S: BaseFloat> ToMatrix4<S> for Quaternion<S> {
impl<S: BaseFloat> From<Quaternion<S>> for Matrix4<S> {
/// Convert the quaternion to a 4 x 4 rotation matrix
fn to_matrix4(&self) -> Matrix4<S> {
let x2 = self.v.x + self.v.x;
let y2 = self.v.y + self.v.y;
let z2 = self.v.z + self.v.z;
fn from(quat: Quaternion<S>) -> Matrix4<S> {
let x2 = quat.v.x + quat.v.x;
let y2 = quat.v.y + quat.v.y;
let z2 = quat.v.z + quat.v.z;
let xx2 = x2 * self.v.x;
let xy2 = x2 * self.v.y;
let xz2 = x2 * self.v.z;
let xx2 = x2 * quat.v.x;
let xy2 = x2 * quat.v.y;
let xz2 = x2 * quat.v.z;
let yy2 = y2 * self.v.y;
let yz2 = y2 * self.v.z;
let zz2 = z2 * self.v.z;
let yy2 = y2 * quat.v.y;
let yz2 = y2 * quat.v.z;
let zz2 = z2 * quat.v.z;
let sy2 = y2 * self.s;
let sz2 = z2 * self.s;
let sx2 = x2 * self.s;
let sy2 = y2 * quat.s;
let sz2 = z2 * quat.s;
let sx2 = x2 * quat.s;
Matrix4::new(one::<S>() - yy2 - zz2, xy2 + sz2, xz2 - sy2, zero::<S>(),
xy2 - sz2, one::<S>() - xx2 - zz2, yz2 + sx2, zero::<S>(),

View file

@ -16,8 +16,8 @@
use angle::{Rad, acos};
use approx::ApproxEq;
use matrix::Matrix;
use matrix::{Matrix2, ToMatrix2};
use matrix::{Matrix3, ToMatrix3};
use matrix::Matrix2;
use matrix::Matrix3;
use num::{BaseNum, BaseFloat};
use point::{Point, Point2, Point3};
use quaternion::{Quaternion, ToQuaternion};
@ -75,7 +75,7 @@ pub trait Rotation<S: BaseNum, V: Vector<S>, P: Point<S, V>>: PartialEq + Approx
/// A two-dimensional rotation.
pub trait Rotation2<S>: Rotation<S, Vector2<S>, Point2<S>>
+ ToMatrix2<S>
+ Into<Matrix2<S>>
+ ToBasis2<S> {
/// Create a rotation by a given angle. Thus is a redundant case of both
/// from_axis_angle() and from_euler() for 2D space.
@ -84,7 +84,7 @@ pub trait Rotation2<S>: Rotation<S, Vector2<S>, Point2<S>>
/// A three-dimensional rotation.
pub trait Rotation3<S: BaseNum>: Rotation<S, Vector3<S>, Point3<S>>
+ ToMatrix3<S>
+ Into<Matrix3<S>>
+ ToBasis3<S>
+ ToQuaternion<S>{
/// Create a rotation using an angle around a given axis.
@ -135,7 +135,7 @@ pub trait Rotation3<S: BaseNum>: Rotation<S, Vector3<S>, Point3<S>>
/// ```no_run
/// use cgmath::rad;
/// use cgmath::Vector2;
/// use cgmath::{Matrix, ToMatrix2};
/// use cgmath::{Matrix, Matrix2};
/// use cgmath::{Rotation, Rotation2, Basis2};
/// use cgmath::ApproxEq;
/// use std::f64;
@ -153,7 +153,8 @@ pub trait Rotation3<S: BaseNum>: Rotation<S, Vector3<S>, Point3<S>>
/// assert!(unit_y.approx_eq(&Vector2::unit_y()));
///
/// // This is exactly equivalent to using the raw matrix itself:
/// let unit_y2 = rot.to_matrix2().mul_v(&unit_x);
/// let unit_y2: Matrix2<_> = rot.into();
/// let unit_y2 = unit_y2.mul_v(&unit_x);
/// assert_eq!(unit_y2, unit_y);
///
/// // Note that we can also concatenate rotations:
@ -183,9 +184,9 @@ impl<S: BaseFloat> ToBasis2<S> for Basis2<S> {
fn to_rot2(&self) -> Basis2<S> { self.clone() }
}
impl<S: BaseFloat> ToMatrix2<S> for Basis2<S> {
impl<S: BaseFloat> From<Basis2<S>> for Matrix2<S> {
#[inline]
fn to_matrix2(&self) -> Matrix2<S> { self.mat.clone() }
fn from(b: Basis2<S>) -> Matrix2<S> { b.mat }
}
impl<S: BaseFloat + 'static> Rotation<S, Vector2<S>, Point2<S>> for Basis2<S> {
@ -248,7 +249,7 @@ impl<S: BaseFloat> Basis3<S> {
/// Create a new rotation matrix from a quaternion.
#[inline]
pub fn from_quaternion(quaternion: &Quaternion<S>) -> Basis3<S> {
Basis3 { mat: quaternion.to_matrix3() }
Basis3 { mat: quaternion.clone().into() }
}
/// Coerce to a `Matrix3`
@ -267,9 +268,9 @@ impl<S: BaseFloat> ToBasis3<S> for Basis3<S> {
fn to_rot3(&self) -> Basis3<S> { self.clone() }
}
impl<S: BaseFloat> ToMatrix3<S> for Basis3<S> {
impl<S: BaseFloat> From<Basis3<S>> for Matrix3<S> {
#[inline]
fn to_matrix3(&self) -> Matrix3<S> { self.mat.clone() }
fn from(b: Basis3<S>) -> Matrix3<S> { b.mat }
}
impl<S: BaseFloat + 'static> ToQuaternion<S> for Basis3<S> {

View file

@ -146,16 +146,17 @@ impl<
}
}
pub trait Transform2<S>: Transform<S, Vector2<S>, Point2<S>> + ToMatrix3<S> {}
pub trait Transform3<S>: Transform<S, Vector3<S>, Point3<S>> + ToMatrix4<S> {}
pub trait Transform2<S>: Transform<S, Vector2<S>, Point2<S>> + Into<Matrix3<S>> {}
pub trait Transform3<S>: Transform<S, Vector3<S>, Point3<S>> + Into<Matrix4<S>> {}
impl<
S: BaseFloat + 'static,
R: Rotation2<S>,
> ToMatrix3<S> for Decomposed<S, Vector2<S>, R> {
fn to_matrix3(&self) -> Matrix3<S> {
let mut m = self.rot.to_matrix2().mul_s(self.scale.clone()).to_matrix3();
m.z = self.disp.extend(one());
> From<Decomposed<S, Vector2<S>, R>> for Matrix3<S> {
fn from(dec: Decomposed<S, Vector2<S>, R>) -> Matrix3<S> {
let m: Matrix2<_> = dec.rot.into();
let mut m: Matrix3<_> = m.mul_s(dec.scale).into();
m.z = dec.disp.extend(one());
m
}
}
@ -163,10 +164,11 @@ impl<
impl<
S: BaseFloat + 'static,
R: Rotation3<S>,
> ToMatrix4<S> for Decomposed<S, Vector3<S>, R> {
fn to_matrix4(&self) -> Matrix4<S> {
let mut m = self.rot.to_matrix3().mul_s(self.scale.clone()).to_matrix4();
m.w = self.disp.extend(one());
> From<Decomposed<S, Vector3<S>, R>> for Matrix4<S> {
fn from(dec: Decomposed<S, Vector3<S>, R>) -> Matrix4<S> {
let m: Matrix3<_> = dec.rot.into();
let mut m: Matrix4<_> = m.mul_s(dec.scale).into();
m.w = dec.disp.extend(one());
m
}
}
@ -229,8 +231,8 @@ impl<S: BaseFloat + 'static> Transform<S, Vector3<S>, Point3<S>> for AffineMatri
}
}
impl<S: BaseNum> ToMatrix4<S> for AffineMatrix3<S> {
#[inline] fn to_matrix4(&self) -> Matrix4<S> { self.mat.clone() }
impl<S: BaseNum> From<AffineMatrix3<S>> for Matrix4<S> {
#[inline] fn from(aff: AffineMatrix3<S>) -> Matrix4<S> { aff.mat }
}
impl<S: BaseFloat + 'static> Transform3<S> for AffineMatrix3<S> {}

View file

@ -15,7 +15,7 @@
extern crate cgmath;
use cgmath::{ToMatrix4, ToMatrix3};
use cgmath::{Matrix4, Matrix3};
use cgmath::Quaternion;
use cgmath::{Rad, rad, ApproxEq};
@ -28,8 +28,10 @@ fn to_matrix4()
{
let quaternion = Quaternion::new(2f32, 3f32, 4f32, 5f32);
let matrix_short = quaternion.to_matrix4();
let matrix_long = quaternion.to_matrix3().to_matrix4();
let matrix_short: Matrix4<_> = quaternion.into();
let matrix_long: Matrix3<_> = quaternion.into();
let matrix_long: Matrix4<_> = matrix_long.into();
assert!(matrix_short == matrix_long);
}