Change quaternion type from four scalars (wxyz), to a scalar and vec3 (sv)

This commit is contained in:
Brendan Zabarauskas 2012-11-21 14:01:21 +10:00
parent 8a9668c39c
commit 2463a3244c
2 changed files with 39 additions and 50 deletions

View file

@ -55,17 +55,17 @@ pub trait ToQuat<T> {
pub struct Quat<T> { w: T, x: T, y: T, z: T } pub struct Quat<T> { s: T, v: Vec3<T> }
pub impl<T:Copy> Quat<T> { pub impl<T> Quat<T> {
#[inline(always)] #[inline(always)]
static pure fn new(w: T, x: T, y: T, z: T) -> Quat<T> { static pure fn new(s: T, vx: T, vy: T, vz: T) -> Quat<T> {
Quat { w: move w, x: move x, y: move y, z: move z } Quat::from_sv(move s, move Vec3::new(move vx, move vy, move vz))
} }
#[inline(always)] #[inline(always)]
static pure fn from_sv(s: T, v: &Vec3<T>) -> Quat<T> { static pure fn from_sv(s: T, v: Vec3<T>) -> Quat<T> {
Quat::new(move s, v.x, v.y, v.z) Quat { s: move s, v: move v }
} }
} }
@ -96,7 +96,7 @@ pub impl<T:Copy Num NumCast Trig Exp Extent Ord AngleConv> Quat<T>: Quaternion<T
#[inline(always)] #[inline(always)]
pure fn neg() -> Quat<T> { pure fn neg() -> Quat<T> {
Quat::new(-self[0], -self[1], -self[2], -self[3]) Quat::from_sv(-self.s, -self.v)
} }
#[inline(always)] #[inline(always)]
@ -117,9 +117,8 @@ pub impl<T:Copy Num NumCast Trig Exp Extent Ord AngleConv> Quat<T>: Quaternion<T
#[inline(always)] #[inline(always)]
pure fn mul_v(vec: &Vec3<T>) -> Vec3<T> { pure fn mul_v(vec: &Vec3<T>) -> Vec3<T> {
let base = Vec3{ x:self.x, y:self.y, z:self.z }; let tmp = self.v.cross(vec).add_v(&vec.mul_t(self.s));
let tmp = base.cross(vec).add_v(&vec.mul_t(self.w)); self.v.cross(&tmp).mul_t(cast(2)).add_v(vec)
base.cross(&tmp).mul_t(cast(2)).add_v(vec)
} }
#[inline(always)] #[inline(always)]
@ -140,38 +139,30 @@ pub impl<T:Copy Num NumCast Trig Exp Extent Ord AngleConv> Quat<T>: Quaternion<T
#[inline(always)] #[inline(always)]
pure fn mul_q(other: &Quat<T>) -> Quat<T> { pure fn mul_q(other: &Quat<T>) -> Quat<T> {
Quat::new(self.w * other.w - self.x * other.x - self.y * other.y - self.z * other.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,
self.w * other.x + self.x * other.w + self.y * other.z - self.z * other.y, self.s * other.v.x + self.v.x * other.s + self.v.y * other.v.z - self.v.z * other.v.y,
self.w * other.y + self.y * other.w + self.z * other.x - self.x * other.z, self.s * other.v.y + self.v.y * other.s + self.v.z * other.v.x - self.v.x * other.v.z,
self.w * other.z + self.z * other.w + self.x * other.y - self.y * other.x) self.s * other.v.z + self.v.z * other.s + self.v.x * other.v.y - self.v.y * other.v.x)
} }
#[inline(always)] #[inline(always)]
pure fn dot(other: &Quat<T>) -> T { pure fn dot(other: &Quat<T>) -> T {
self.w * other.w + self.s * other.s + self.v.dot(&other.v)
self.x * other.x +
self.y * other.y +
self.z * other.z
} }
#[inline(always)] #[inline(always)]
pure fn conjugate() -> Quat<T> { pure fn conjugate() -> Quat<T> {
Quat::new(self.w, -self.x, -self.y, -self.z) Quat::from_sv(self.s, -self.v)
} }
#[inline(always)] #[inline(always)]
pure fn inverse() -> Quat<T> { pure fn inverse() -> Quat<T> {
let mut n: T = cast(1); self.conjugate().div_t(self.length2())
n /= self.length2();
self.conjugate().mul_t(n)
} }
#[inline(always)] #[inline(always)]
pure fn length2() -> T { pure fn length2() -> T {
self.w * self.w + self.s * self.s + self.v.length2()
self.x * self.x +
self.y * self.y +
self.z * self.z
} }
#[inline(always)] #[inline(always)]
@ -229,32 +220,32 @@ pub impl<T:Copy Num NumCast Trig Exp Extent Ord AngleConv> Quat<T>: Quaternion<T
#[inline(always)] #[inline(always)]
pub pure fn from_axis_angle(axis: Vec3<T>, theta: T) -> Quat<T> { pub pure fn from_axis_angle(axis: Vec3<T>, theta: T) -> Quat<T> {
let half = radians(&theta) / cast(2); let half = radians(&theta) / cast(2);
Quat::from_sv(cos(&half), &axis.mul_t(sin(&half))) Quat::from_sv(cos(&half), axis.mul_t(sin(&half)))
} }
#[inline(always)] #[inline(always)]
pure fn to_Mat3() -> Mat3<T> { pure fn to_Mat3() -> Mat3<T> {
let x2 = self.x + self.x; let x2 = self.v.x + self.v.x;
let y2 = self.y + self.y; let y2 = self.v.y + self.v.y;
let z2 = self.z + self.z; let z2 = self.v.z + self.v.z;
let xx2 = x2 * self.x; let xx2 = x2 * self.v.x;
let xy2 = x2 * self.y; let xy2 = x2 * self.v.y;
let xz2 = x2 * self.z; let xz2 = x2 * self.v.z;
let yy2 = y2 * self.y; let yy2 = y2 * self.v.y;
let yz2 = y2 * self.z; let yz2 = y2 * self.v.z;
let zz2 = z2 * self.z; let zz2 = z2 * self.v.z;
let wy2 = y2 * self.w; let sy2 = y2 * self.s;
let wz2 = z2 * self.w; let sz2 = z2 * self.s;
let wx2 = x2 * self.w; let sx2 = x2 * self.s;
let _1: T = cast(1); let _1: T = cast(1);
Mat3::new(_1 - yy2 - zz2, xy2 - wz2, xz2 + wy2, Mat3::new(_1 - yy2 - zz2, xy2 - sz2, xz2 + sy2,
xy2 + wz2, _1 - xx2 - zz2, yz2 - wx2, xy2 + sz2, _1 - xx2 - zz2, yz2 - sx2,
xz2 - wy2, yz2 + wx2, _1 - xx2 - yy2) xz2 - sy2, yz2 + sx2, _1 - xx2 - yy2)
} }
#[inline(always)] #[inline(always)]

View file

@ -6,20 +6,18 @@ use vec::*;
#[test] #[test]
fn test_Quat() { fn test_Quat() {
let a = Quat { w: 1f, x: 2f, y: 3f, z: 4f }; let a = Quat { s: 1f, v: Vec3 { x: 2f, y: 3f, z: 4f } };
// let b = Quat { data: [ 5f, 6f, 7f, 8f ] };
// let f1 = 1.5f;
// let f2 = 0.5f;
assert a == Quat::from_sv(1f, Vec3::new(2f, 3f, 4f));
assert a == Quat::new(1f, 2f, 3f, 4f); assert a == Quat::new(1f, 2f, 3f, 4f);
// assert Quat::zero() == Quat::new(0f, 0f, 0f, 0f); // assert Quat::zero() == Quat::new(0f, 0f, 0f, 0f);
// assert Quat::identity() == Quat::new(1f, 0f, 0f, 0f); // assert Quat::identity() == Quat::new(1f, 0f, 0f, 0f);
assert a.w == 1f; assert a.s == 1f;
assert a.x == 2f; assert a.v.x == 2f;
assert a.y == 3f; assert a.v.y == 3f;
assert a.z == 4f; assert a.v.z == 4f;
assert a[0] == 1f; assert a[0] == 1f;
assert a[1] == 2f; assert a[1] == 2f;
assert a[2] == 3f; assert a[2] == 3f;