Remove Quaternion trait

This commit is contained in:
Brendan Zabarauskas 2012-12-28 13:47:34 +10:00
parent f4b6bf5572
commit 5c9d882efe
2 changed files with 103 additions and 196 deletions

View file

@ -22,170 +22,6 @@ use numeric::types::number::Number;
use mat::{Mat3, Mat4}; use mat::{Mat3, Mat4};
use vec::Vec3; use vec::Vec3;
/**
* The base quaternion trait
*
* # Type parameters
*
* * `T` - The type of the components. Should be a floating point type.
* * `V3` - The 3-dimensional vector type that will containin the imaginary
* components of the quaternion.
*/
pub trait Quaternion<T,V3>: Index<uint, T> Eq Neg<self> {
/**
* # Return value
*
* The multiplicative identity, ie: `q = 1 + 0i + 0j + 0i`
*/
static pure fn identity() -> self;
/**
* # Return value
*
* The additive identity, ie: `q = 0 + 0i + 0j + 0i`
*/
static pure fn zero() -> self;
/**
* # Return value
*
* The result of multiplying the quaternion a scalar
*/
pure fn mul_t(&self, value: T) -> self;
/**
* # Return value
*
* The result of dividing the quaternion a scalar
*/
pure fn div_t(&self, value: T) -> self;
/**
* # Return value
*
* The result of multiplying the quaternion by a vector
*/
pure fn mul_v(&self, vec: &V3) -> V3;
/**
* # Return value
*
* The sum of this quaternion and `other`
*/
pure fn add_q(&self, other: &self) -> self;
/**
* # Return value
*
* The sum of this quaternion and `other`
*/
pure fn sub_q(&self, other: &self) -> self;
/**
* # Return value
*
* The the result of multipliplying the quaternion by `other`
*/
pure fn mul_q(&self, other: &self) -> self;
/**
* # Return value
*
* The dot product of the quaternion and `other`
*/
pure fn dot(&self, other: &self) -> T;
/**
* # Return value
*
* The conjugate of the quaternion
*/
pure fn conjugate(&self) -> self;
/**
* # Return value
*
* The multiplicative inverse of the quaternion
*/
pure fn inverse(&self) -> self;
/**
* # Return value
*
* The squared magnitude of the quaternion. This is useful for
* magnitude comparisons where the exact magnitude does not need to be
* calculated.
*/
pure fn magnitude2(&self) -> T;
/**
* # Return value
*
* The magnitude of the quaternion
*
* # Performance notes
*
* For instances where the exact magnitude of the quaternion does not need
* to be known, for example for quaternion-quaternion magnitude comparisons,
* it is advisable to use the `magnitude2` method instead.
*/
pure fn magnitude(&self) -> T;
/**
* # Return value
*
* The normalized quaternion
*/
pure fn normalize(&self) -> self;
/**
* Normalised linear interpolation
*
* # Return value
*
* The intoperlated quaternion
*/
pure fn nlerp(&self, other: &self, amount: T) -> self;
/**
* Perform a spherical linear interpolation between the quaternion and
* `other`.
*
* # Return value
*
* The intoperlated quaternion
*
* # Performance notes
*
* This is more accurate than `nlerp` but is also more
* computationally intensive.
*/
pure fn slerp(&self, other: &self, amount: T) -> self;
/**
* Convert the quaternion to a 3 x 3 rotation matrix
*/
pure fn to_mat3(&self) -> Mat3<T>;
/**
* Convert the quaternion to a 4 x 4 transformation matrix
*/
pure fn to_mat4(&self) -> Mat4<T>;
/**
* # Return value
*
* A pointer to the first component of the quaternion
*/
pure fn to_ptr(&self) -> *T;
}
/** /**
* A quaternion in scalar/vector form * A quaternion in scalar/vector form
* *
@ -262,35 +98,12 @@ pub impl<T:Copy Float> Quat<T> {
Number::zero(), Number::zero(),
Number::zero()) Number::zero())
} }
}
pub impl<T:Copy> Quat<T>: Index<uint, T> {
#[inline(always)]
pure fn index(&self, i: uint) -> T {
unsafe { do buf_as_slice(
transmute::<*Quat<T>, *T>(
to_unsafe_ptr(self)), 4) |slice| { slice[i] }
}
}
}
pub impl<T:Copy Float> Quat<T>: Quaternion<T, Vec3<T>> {
#[inline(always)]
static pure fn identity() -> Quat<T> {
Quat::new(Number::from(1),
Number::from(0),
Number::from(0),
Number::from(0))
}
#[inline(always)]
static pure fn zero() -> Quat<T> {
Quat::new(Number::from(0),
Number::from(0),
Number::from(0),
Number::from(0))
}
/**
* # Return value
*
* The result of multiplying the quaternion a scalar
*/
#[inline(always)] #[inline(always)]
pure fn mul_t(&self, value: T) -> Quat<T> { pure fn mul_t(&self, value: T) -> Quat<T> {
Quat::new(self[0] * value, Quat::new(self[0] * value,
@ -299,6 +112,11 @@ pub impl<T:Copy Float> Quat<T>: Quaternion<T, Vec3<T>> {
self[3] * value) self[3] * value)
} }
/**
* # Return value
*
* The result of dividing the quaternion a scalar
*/
#[inline(always)] #[inline(always)]
pure fn div_t(&self, value: T) -> Quat<T> { pure fn div_t(&self, value: T) -> Quat<T> {
Quat::new(self[0] / value, Quat::new(self[0] / value,
@ -306,13 +124,23 @@ pub impl<T:Copy Float> Quat<T>: Quaternion<T, Vec3<T>> {
self[2] / value, self[2] / value,
self[3] / value) self[3] / value)
} }
/**
* # Return value
*
* The result of multiplying the quaternion by a vector
*/
#[inline(always)] #[inline(always)]
pure fn mul_v(&self, vec: &Vec3<T>) -> Vec3<T> { pure fn mul_v(&self, vec: &Vec3<T>) -> Vec3<T> {
let tmp = self.v.cross(vec).add_v(&vec.mul_t(self.s)); let tmp = self.v.cross(vec).add_v(&vec.mul_t(self.s));
self.v.cross(&tmp).mul_t(Number::from(2)).add_v(vec) self.v.cross(&tmp).mul_t(Number::from(2)).add_v(vec)
} }
/**
* # Return value
*
* The sum of this quaternion and `other`
*/
#[inline(always)] #[inline(always)]
pure fn add_q(&self, other: &Quat<T>) -> Quat<T> { pure fn add_q(&self, other: &Quat<T>) -> Quat<T> {
Quat::new(self[0] + other[0], Quat::new(self[0] + other[0],
@ -321,6 +149,11 @@ pub impl<T:Copy Float> Quat<T>: Quaternion<T, Vec3<T>> {
self[3] + other[3]) self[3] + other[3])
} }
/**
* # Return value
*
* The sum of this quaternion and `other`
*/
#[inline(always)] #[inline(always)]
pure fn sub_q(&self, other: &Quat<T>) -> Quat<T> { pure fn sub_q(&self, other: &Quat<T>) -> Quat<T> {
Quat::new(self[0] - other[0], Quat::new(self[0] - other[0],
@ -329,6 +162,11 @@ pub impl<T:Copy Float> Quat<T>: Quaternion<T, Vec3<T>> {
self[3] - other[3]) self[3] - other[3])
} }
/**
* # Return value
*
* The the result of multipliplying the quaternion by `other`
*/
#[inline(always)] #[inline(always)]
pure fn mul_q(&self, other: &Quat<T>) -> Quat<T> { pure fn mul_q(&self, other: &Quat<T>) -> Quat<T> {
Quat::new(self.s * other.s - self.v.x * other.v.x - self.v.y * other.v.y - self.v.z * other.v.z, Quat::new(self.s * other.s - self.v.x * other.v.x - self.v.y * other.v.y - self.v.z * other.v.z,
@ -337,31 +175,69 @@ pub impl<T:Copy Float> Quat<T>: Quaternion<T, Vec3<T>> {
self.s * other.v.z + self.v.z * other.s + self.v.x * other.v.y - self.v.y * other.v.x) self.s * other.v.z + self.v.z * other.s + self.v.x * other.v.y - self.v.y * other.v.x)
} }
/**
* # Return value
*
* The dot product of the quaternion and `other`
*/
#[inline(always)] #[inline(always)]
pure fn dot(&self, other: &Quat<T>) -> T { pure fn dot(&self, other: &Quat<T>) -> T {
self.s * other.s + self.v.dot(&other.v) self.s * other.s + self.v.dot(&other.v)
} }
/**
* # Return value
*
* The conjugate of the quaternion
*/
#[inline(always)] #[inline(always)]
pure fn conjugate(&self) -> Quat<T> { pure fn conjugate(&self) -> Quat<T> {
Quat::from_sv(self.s, -self.v) Quat::from_sv(self.s, -self.v)
} }
/**
* # Return value
*
* The multiplicative inverse of the quaternion
*/
#[inline(always)] #[inline(always)]
pure fn inverse(&self) -> Quat<T> { pure fn inverse(&self) -> Quat<T> {
self.conjugate().div_t(self.magnitude2()) self.conjugate().div_t(self.magnitude2())
} }
/**
* # Return value
*
* The squared magnitude of the quaternion. This is useful for
* magnitude comparisons where the exact magnitude does not need to be
* calculated.
*/
#[inline(always)] #[inline(always)]
pure fn magnitude2(&self) -> T { pure fn magnitude2(&self) -> T {
self.s * self.s + self.v.length2() self.s * self.s + self.v.length2()
} }
/**
* # Return value
*
* The magnitude of the quaternion
*
* # Performance notes
*
* For instances where the exact magnitude of the quaternion does not need
* to be known, for example for quaternion-quaternion magnitude comparisons,
* it is advisable to use the `magnitude2` method instead.
*/
#[inline(always)] #[inline(always)]
pure fn magnitude(&self) -> T { pure fn magnitude(&self) -> T {
self.magnitude2().sqrt() self.magnitude2().sqrt()
} }
/**
* # Return value
*
* The normalized quaternion
*/
#[inline(always)] #[inline(always)]
pure fn normalize(&self) -> Quat<T> { pure fn normalize(&self) -> Quat<T> {
let mut n: T = Number::from(1); let mut n: T = Number::from(1);
@ -369,6 +245,13 @@ pub impl<T:Copy Float> Quat<T>: Quaternion<T, Vec3<T>> {
return self.mul_t(n); return self.mul_t(n);
} }
/**
* Normalised linear interpolation
*
* # Return value
*
* The intoperlated quaternion
*/
#[inline(always)] #[inline(always)]
pure fn nlerp(&self, other: &Quat<T>, amount: T) -> Quat<T> { pure fn nlerp(&self, other: &Quat<T>, amount: T) -> Quat<T> {
let _1: T = Number::from(1); let _1: T = Number::from(1);
@ -378,8 +261,12 @@ pub impl<T:Copy Float> Quat<T>: Quaternion<T, Vec3<T>> {
/** /**
* Spherical Linear Intoperlation * Spherical Linear Intoperlation
* *
* Both quaternions should be normalized first, or else strange things will * Perform a spherical linear interpolation between the quaternion and
* will happen... * `other`. Both quaternions should be normalized first.
*
* # Return value
*
* The intoperlated quaternion
* *
* # Performance notes * # Performance notes
* *
@ -414,6 +301,9 @@ pub impl<T:Copy Float> Quat<T>: Quaternion<T, Vec3<T>> {
} }
} }
/**
* Convert the quaternion to a 3 x 3 rotation matrix
*/
#[inline(always)] #[inline(always)]
pure fn to_mat3(&self) -> Mat3<T> { pure fn to_mat3(&self) -> Mat3<T> {
let x2 = self.v.x + self.v.x; let x2 = self.v.x + self.v.x;
@ -439,11 +329,19 @@ pub impl<T:Copy Float> Quat<T>: Quaternion<T, Vec3<T>> {
xz2 + sy2, yz2 - sx2, _1 - xx2 - yy2) xz2 + sy2, yz2 - sx2, _1 - xx2 - yy2)
} }
/**
* Convert the quaternion to a 4 x 4 transformation matrix
*/
#[inline(always)] #[inline(always)]
pure fn to_mat4(&self) -> Mat4<T> { pure fn to_mat4(&self) -> Mat4<T> {
self.to_mat3().to_mat4() self.to_mat3().to_mat4()
} }
/**
* # Return value
*
* A pointer to the first component of the quaternion
*/
#[inline(always)] #[inline(always)]
pure fn to_ptr(&self) -> *T { pure fn to_ptr(&self) -> *T {
unsafe { unsafe {
@ -454,6 +352,16 @@ pub impl<T:Copy Float> Quat<T>: Quaternion<T, Vec3<T>> {
} }
} }
pub impl<T:Copy> Quat<T>: Index<uint, T> {
#[inline(always)]
pure fn index(&self, i: uint) -> T {
unsafe { do buf_as_slice(
transmute::<*Quat<T>, *T>(
to_unsafe_ptr(self)), 4) |slice| { slice[i] }
}
}
}
pub impl<T:Copy Float> Quat<T>: Neg<Quat<T>> { pub impl<T:Copy Float> Quat<T>: Neg<Quat<T>> {
#[inline(always)] #[inline(always)]
pure fn neg(&self) -> Quat<T> { pure fn neg(&self) -> Quat<T> {

View file

@ -32,7 +32,6 @@ fn test_quat() {
fn test_quat_2() { fn test_quat_2() {
let v = Vec3::new(1.0, 0.0, 0.0); let v = Vec3::new(1.0, 0.0, 0.0);
// let q: Quat<float> = Quaternion::from_axis_angle(&Vec3::new(0.0, 0.0, -1.0), Degrees(-90.0));
let q = Quat::from_axis_angle(&Vec3::new(0.0, 0.0, -1.0), Degrees(-45.0)); let q = Quat::from_axis_angle(&Vec3::new(0.0, 0.0, -1.0), Degrees(-45.0));
// http://www.wolframalpha.com/input/?i={1,0}+rotate+-45+degrees // http://www.wolframalpha.com/input/?i={1,0}+rotate+-45+degrees