Merge pull request #216 from tomaka/into

Replace most To* traits by Into
This commit is contained in:
Dzmitry Malyshau 2015-05-08 10:16:00 -04:00
commit 6e560fbd03
9 changed files with 192 additions and 239 deletions

View file

@ -40,39 +40,19 @@ pub struct Deg<S> { pub s: S }
/// Create a new angle, in degrees
#[inline] pub fn deg<S: BaseFloat>(s: S) -> Deg<S> { Deg { s: s } }
/// Represents types that can be converted to radians.
pub trait ToRad<S: BaseFloat> {
/// Convert this value to radians.
fn to_rad(&self) -> Rad<S>;
}
/// Represents types that can be converted to degrees.
pub trait ToDeg<S: BaseFloat> {
/// Convert this value to degrees.
fn to_deg(&self) -> Deg<S>;
}
impl<S: BaseFloat> ToRad<S> for Rad<S> {
impl<S> From<Rad<S>> for Deg<S> where S: BaseFloat {
#[inline]
fn to_rad(&self) -> Rad<S> { self.clone() }
}
impl<S: BaseFloat> ToRad<S> for Deg<S> {
#[inline]
fn to_rad(&self) -> Rad<S> {
rad(self.s * cast(f64::consts::PI / 180.0).unwrap())
fn from(r: Rad<S>) -> Deg<S> {
deg(r.s * cast(180.0 / f64::consts::PI).unwrap())
}
}
impl<S: BaseFloat> ToDeg<S> for Rad<S> {
impl<S> From<Deg<S>> for Rad<S> where S: BaseFloat {
#[inline]
fn to_deg(&self) -> Deg<S> {
deg(self.s * cast(180.0 / f64::consts::PI).unwrap())
fn from(d: Deg<S>) -> Rad<S> {
rad(d.s * cast(f64::consts::PI / 180.0).unwrap())
}
}
impl<S: BaseFloat> ToDeg<S> for Deg<S> {
#[inline]
fn to_deg(&self) -> Deg<S> { self.clone() }
}
/// Private utility functions for converting to/from scalars
trait ScalarConv<S> {
@ -102,8 +82,8 @@ pub trait Angle
+ PartialEq + PartialOrd
+ ApproxEq<S>
+ Neg<Output=Self>
+ ToRad<S>
+ ToDeg<S>
+ Into<Rad<S>>
+ Into<Deg<S>>
+ ScalarConv<S>
+ fmt::Debug
{
@ -279,13 +259,13 @@ impl<S: BaseFloat> One for Deg<S> {
const PI_2: f64 = f64::consts::PI * 2f64;
impl<S: BaseFloat>
Angle<S> for Rad<S> {
#[inline] fn from<A: Angle<S>>(theta: A) -> Rad<S> { theta.to_rad() }
#[inline] fn from<A: Angle<S>>(theta: A) -> Rad<S> { theta.into() }
#[inline] fn full_turn() -> Rad<S> { rad(cast(PI_2).unwrap()) }
}
impl<S: BaseFloat>
Angle<S> for Deg<S> {
#[inline] fn from<A: Angle<S>>(theta: A) -> Deg<S> { theta.to_deg() }
#[inline] fn from<A: Angle<S>>(theta: A) -> Deg<S> { theta.into() }
#[inline] fn full_turn() -> Deg<S> { deg(cast(360i32).unwrap()) }
}

View file

@ -29,7 +29,7 @@ use approx::ApproxEq;
use array::{Array1, Array2, FixedArray};
use num::{BaseFloat, BaseNum};
use point::{Point, Point3};
use quaternion::{Quaternion, ToQuaternion};
use quaternion::Quaternion;
use vector::{Vector, EuclideanVector};
use vector::{Vector2, Vector3, Vector4};
@ -1326,94 +1326,76 @@ 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(),
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(),
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(),
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())
}
}
impl<S: BaseFloat> ToQuaternion<S> for Matrix3<S> {
impl<S: BaseFloat> From<Matrix3<S>> for Quaternion<S> {
/// Convert the matrix to a quaternion
fn to_quaternion(&self) -> Quaternion<S> {
fn from(mat: Matrix3<S>) -> Quaternion<S> {
// http://www.cs.ucr.edu/~vbz/resources/quatut.pdf
let trace = self.trace();
let trace = mat.trace();
let half: S = cast(0.5f64).unwrap();
if trace >= zero::<S>() {
let s = (one::<S>() + trace).sqrt();
let w = half * s;
let s = half / s;
let x = (self[1][2] - self[2][1]) * s;
let y = (self[2][0] - self[0][2]) * s;
let z = (self[0][1] - self[1][0]) * s;
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)
} else if (self[0][0] > self[1][1]) && (self[0][0] > self[2][2]) {
let s = (half + (self[0][0] - self[1][1] - self[2][2])).sqrt();
} 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;
let x = (self[0][1] - self[1][0]) * s;
let y = (self[2][0] - self[0][2]) * s;
let z = (self[1][2] - self[2][1]) * s;
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)
} else if self[1][1] > self[2][2] {
let s = (half + (self[1][1] - self[0][0] - self[2][2])).sqrt();
} 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;
let x = (self[0][1] - self[1][0]) * s;
let y = (self[1][2] - self[2][1]) * s;
let z = (self[2][0] - self[0][2]) * s;
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 {
let s = (half + (self[2][2] - self[0][0] - self[1][1])).sqrt();
let s = (half + (mat[2][2] - mat[0][0] - mat[1][1])).sqrt();
let w = half * s;
let s = half / s;
let x = (self[2][0] - self[0][2]) * s;
let y = (self[1][2] - self[2][1]) * s;
let z = (self[0][1] - self[1][0]) * s;
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)
}
}

View file

@ -16,9 +16,9 @@
use rust_num::{zero, one};
use rust_num::traits::cast;
use angle::{Angle, tan, cot};
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>;
}
@ -81,7 +81,8 @@ pub struct PerspectiveFov<S, A> {
impl<S: BaseFloat, A: Angle<S>> PerspectiveFov<S, A> {
pub fn to_perspective(&self) -> Perspective<S> {
let angle = self.fovy.div_s(cast(2i8).unwrap());
let ymax = self.near * tan(angle.to_rad());
let angle: Rad<_> = angle.into();
let ymax = self.near * tan(angle);
let xmax = ymax * self.aspect;
Perspective {
@ -98,25 +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 = cot(self.fovy.div_s(cast(2i8).unwrap()).to_rad());
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();
@ -128,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,
@ -157,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,
@ -220,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,10 +25,10 @@ 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};
use rotation::{Rotation, Rotation3, Basis3};
use vector::{Vector3, Vector, EuclideanVector};
@ -37,12 +37,6 @@ use vector::{Vector3, Vector, EuclideanVector};
#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable)]
pub struct Quaternion<S> { pub s: S, pub v: Vector3<S> }
/// Represents types which can be expressed as a quaternion.
pub trait ToQuaternion<S: BaseFloat> {
/// Convert this value to a quaternion.
fn to_quaternion(&self) -> Quaternion<S>;
}
impl<S: Copy + BaseFloat> Array1<S> for Quaternion<S> {
#[inline]
fn map<F>(&mut self, mut op: F) -> Quaternion<S> where F: FnMut(S) -> S {
@ -310,24 +304,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 +329,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>(),
@ -382,14 +376,9 @@ impl<S: BaseFloat> fmt::Debug for Quaternion<S> {
// Quaternion Rotation impls
impl<S: BaseFloat> ToBasis3<S> for Quaternion<S> {
impl<S: BaseFloat> From<Quaternion<S>> for Basis3<S> {
#[inline]
fn to_rot3(&self) -> Basis3<S> { Basis3::from_quaternion(self) }
}
impl<S: BaseFloat> ToQuaternion<S> for Quaternion<S> {
#[inline]
fn to_quaternion(&self) -> Quaternion<S> { self.clone() }
fn from(quat: Quaternion<S>) -> Basis3<S> { Basis3::from_quaternion(&quat) }
}
impl<S: BaseFloat + 'static> Rotation<S, Vector3<S>, Point3<S>> for Quaternion<S> {
@ -398,7 +387,7 @@ impl<S: BaseFloat + 'static> Rotation<S, Vector3<S>, Point3<S>> for Quaternion<S
#[inline]
fn look_at(dir: &Vector3<S>, up: &Vector3<S>) -> Quaternion<S> {
Matrix3::look_at(dir, up).to_quaternion()
Matrix3::look_at(dir, up).into()
}
#[inline]

View file

@ -16,11 +16,11 @@
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};
use quaternion::Quaternion;
use ray::Ray;
use vector::{Vector, Vector2, Vector3};
@ -75,8 +75,8 @@ 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>
+ ToBasis2<S> {
+ Into<Matrix2<S>>
+ Into<Basis2<S>> {
/// Create a rotation by a given angle. Thus is a redundant case of both
/// from_axis_angle() and from_euler() for 2D space.
fn from_angle(theta: Rad<S>) -> Self;
@ -84,9 +84,9 @@ 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>
+ ToBasis3<S>
+ ToQuaternion<S>{
+ Into<Matrix3<S>>
+ Into<Basis3<S>>
+ Into<Quaternion<S>> {
/// Create a rotation using an angle around a given axis.
fn from_axis_angle(axis: &Vector3<S>, angle: Rad<S>) -> Self;
@ -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:
@ -166,26 +167,16 @@ pub struct Basis2<S> {
mat: Matrix2<S>
}
impl<S: BaseFloat> Basis2<S> {
/// Coerce to a `Matrix2`
impl<S: BaseFloat> AsRef<Matrix2<S>> for Basis2<S> {
#[inline]
pub fn as_matrix2<'a>(&'a self) -> &'a Matrix2<S> { &self.mat }
fn as_ref(&self) -> &Matrix2<S> {
&self.mat
}
}
/// Represents types which can be converted to a rotation matrix.
pub trait ToBasis2<S: BaseFloat> {
/// Convert this type to a rotation matrix.
fn to_rot2(&self) -> Basis2<S>;
}
impl<S: BaseFloat> ToBasis2<S> for Basis2<S> {
impl<S: BaseFloat> From<Basis2<S>> for Matrix2<S> {
#[inline]
fn to_rot2(&self) -> Basis2<S> { self.clone() }
}
impl<S: BaseFloat> ToMatrix2<S> for Basis2<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,33 +239,25 @@ 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`
impl<S> AsRef<Matrix3<S>> for Basis3<S> {
#[inline]
pub fn as_matrix3<'a>(&'a self) -> &'a Matrix3<S> { &self.mat }
fn as_ref(&self) -> &Matrix3<S> {
&self.mat
}
}
/// Represents types which can be converted to a rotation matrix.
pub trait ToBasis3<S: BaseFloat> {
/// Convert this type to a rotation matrix.
fn to_rot3(&self) -> Basis3<S>;
}
impl<S: BaseFloat> ToBasis3<S> for Basis3<S> {
impl<S: BaseFloat> From<Basis3<S>> for Matrix3<S> {
#[inline]
fn to_rot3(&self) -> Basis3<S> { self.clone() }
fn from(b: Basis3<S>) -> Matrix3<S> { b.mat }
}
impl<S: BaseFloat> ToMatrix3<S> for Basis3<S> {
impl<S: BaseFloat + 'static> From<Basis3<S>> for Quaternion<S> {
#[inline]
fn to_matrix3(&self) -> Matrix3<S> { self.mat.clone() }
}
impl<S: BaseFloat + 'static> ToQuaternion<S> for Basis3<S> {
#[inline]
fn to_quaternion(&self) -> Quaternion<S> { self.mat.to_quaternion() }
fn from(b: Basis3<S>) -> Quaternion<S> { b.mat.into() }
}
impl<S: BaseFloat + 'static> Rotation<S, Vector3<S>, Point3<S>> for Basis3<S> {
@ -289,7 +272,7 @@ impl<S: BaseFloat + 'static> Rotation<S, Vector3<S>, Point3<S>> for Basis3<S> {
#[inline]
fn between_vectors(a: &Vector3<S>, b: &Vector3<S>) -> Basis3<S> {
let q: Quaternion<S> = Rotation::between_vectors(a, b);
q.to_rot3()
q.into()
}
#[inline]

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

@ -16,16 +16,25 @@
extern crate cgmath;
use cgmath::{Angle, Rad, Deg, rad, deg};
use cgmath::{ToRad, ToDeg};
use cgmath::ApproxEq;
#[test]
fn conv() {
assert!(deg(-5.0f64).to_rad().to_deg().approx_eq(&deg(-5.0f64)));
assert!(deg(30.0f64).to_rad().to_deg().approx_eq(&deg(30.0f64)));
let angle: Rad<_> = deg(-5.0f64).into();
let angle: Deg<_> = angle.into();
assert!(angle.approx_eq(&deg(-5.0f64)));
assert!(rad(-5.0f64).to_deg().to_rad().approx_eq(&rad(-5.0f64)));
assert!(rad(30.0f64).to_deg().to_rad().approx_eq(&rad(30.0f64)));
let angle: Rad<_> = deg(30.0f64).into();
let angle: Deg<_> = angle.into();
assert!(angle.approx_eq(&deg(30.0f64)));
let angle: Deg<_> = rad(-5.0f64).into();
let angle: Rad<_> = angle.into();
assert!(angle.approx_eq(&rad(-5.0f64)));
let angle: Deg<_> = rad(30.0f64).into();
let angle: Rad<_> = angle.into();
assert!(angle.approx_eq(&rad(30.0f64)));
}
#[test]

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);
}

View file

@ -21,23 +21,27 @@ mod rotation {
use super::cgmath::*;
pub fn a2<R: Rotation2<f64>>() -> R {
Rotation2::from_angle(deg(30.0).to_rad())
Rotation2::from_angle(deg(30.0).into())
}
pub fn a3<R: Rotation3<f64>>() -> R {
let axis = Vector3::new(1.0, 1.0, 0.0).normalize();
Rotation3::from_axis_angle(&axis, deg(30.0).to_rad())
Rotation3::from_axis_angle(&axis, deg(30.0).into())
}
}
#[test]
fn test_invert_basis2() {
let a: Basis2<_> = rotation::a2();
assert!(a.concat(&a.invert()).as_matrix2().is_identity());
let a = a.concat(&a.invert());
let a: &Matrix2<_> = a.as_ref();
assert!(a.is_identity());
}
#[test]
fn test_invert_basis3() {
let a: Basis3<_> = rotation::a3();
assert!(a.concat(&a.invert()).as_matrix3().is_identity());
let a = a.concat(&a.invert());
let a: &Matrix3<_> = a.as_ref();
assert!(a.is_identity());
}