diff --git a/src/cgmath/quaternion.rs b/src/cgmath/quaternion.rs index 32792fc..44d7260 100644 --- a/src/cgmath/quaternion.rs +++ b/src/cgmath/quaternion.rs @@ -19,7 +19,7 @@ use std::num::{zero, one, cast, sqrt}; use angle::{Angle, Rad, acos, cos, sin, sin_cos}; use approx::ApproxEq; use array::{Array, build}; -use matrix::{Mat3, ToMat3}; +use matrix::{Mat3, ToMat3, ToMat4, Mat4}; use vector::{Vec3, Vector, EuclideanVector}; /// A quaternion in scalar/vector form @@ -291,6 +291,33 @@ ToMat3 for Quat { } } +impl> +ToMat4 for Quat { + /// Convert the quaternion to a 4 x 4 rotation matrix + fn to_mat4(&self) -> Mat4 { + let x2 = self.v.x + self.v.x; + let y2 = self.v.y + self.v.y; + let z2 = self.v.z + self.v.z; + + let xx2 = x2 * self.v.x; + let xy2 = x2 * self.v.y; + let xz2 = x2 * self.v.z; + + let yy2 = y2 * self.v.y; + let yz2 = y2 * self.v.z; + let zz2 = z2 * self.v.z; + + let sy2 = y2 * self.s; + let sz2 = z2 * self.s; + let sx2 = x2 * self.s; + + Mat4::new(one::() - yy2 - zz2, xy2 + sz2, xz2 - sy2, zero::(), + xy2 - sz2, one::() - xx2 - zz2, yz2 + sx2, zero::(), + xz2 + sy2, yz2 - sx2, one::() - xx2 - yy2, zero::(), + zero::(), zero::(), zero::(), one::()) + } +} + impl> Neg> for Quat { #[inline] diff --git a/src/cgmath/transform.rs b/src/cgmath/transform.rs index 9e759e2..d262b6e 100644 --- a/src/cgmath/transform.rs +++ b/src/cgmath/transform.rs @@ -15,6 +15,8 @@ use std::{fmt,num}; +use std::num::one; + use approx::ApproxEq; use matrix::{Matrix, Mat4, ToMat4}; use point::{Point, Point3}; @@ -215,14 +217,24 @@ Transform3 for AffineMatrix3 {} /// displacement vector and scale amount. pub struct Transform3D( Decomposed,Quat> ); -impl Transform3D { +impl> Transform3D { #[inline] pub fn new(scale: S, rot: Quat, disp: Vec3) -> Transform3D { Transform3D( Decomposed { scale: scale, rot: rot, disp: disp }) } + + #[inline] + pub fn translate(x: S, y: S, z: S) -> Transform3D { + Transform3D( Decomposed { scale: one(), rot: Quat::zero(), disp: Vec3::new(x, y, z) }) + } + #[inline] pub fn get<'a>(&'a self) -> &'a Decomposed,Quat> { let &Transform3D(ref d) = self; d } } + +impl> ToMat4 for Transform3D { + fn to_mat4(&self) -> Mat4 { self.get().to_mat4() } +} diff --git a/src/test/quaternion.rs b/src/test/quaternion.rs new file mode 100644 index 0000000..e6d90cc --- /dev/null +++ b/src/test/quaternion.rs @@ -0,0 +1,28 @@ +// Copyright 2013 The CGMath Developers. For a full listing of the authors, +// refer to the AUTHORS 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. + +use cgmath::matrix::{ToMat4, ToMat3}; +use cgmath::quaternion::Quat; + +#[test] +fn to_mat4() +{ + let quat = Quat::new(2f32, 3f32, 4f32, 5f32); + + let mat_short = quat.to_mat4(); + let mat_long = quat.to_mat3().to_mat4(); + + assert!(mat_short == mat_long); +} diff --git a/src/test/test.rs b/src/test/test.rs index 8a23c9b..ce88552 100644 --- a/src/test/test.rs +++ b/src/test/test.rs @@ -20,7 +20,7 @@ extern mod cgmath; // pub mod array; pub mod matrix; -// pub mod quaternion; +pub mod quaternion; pub mod vector; pub mod angle;