2013-09-05 03:55:01 +00:00
|
|
|
// 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.
|
|
|
|
|
2013-10-12 23:52:21 +00:00
|
|
|
use angle::Rad;
|
2013-11-01 12:29:01 +00:00
|
|
|
use array::Array;
|
2013-09-17 02:32:07 +00:00
|
|
|
use matrix::Matrix;
|
2013-09-05 03:55:01 +00:00
|
|
|
use matrix::{Mat2, ToMat2};
|
|
|
|
use matrix::{Mat3, ToMat3};
|
2013-11-01 11:34:39 +00:00
|
|
|
use point::{Point, Point2, Point3};
|
2013-09-17 02:32:07 +00:00
|
|
|
use quaternion::{Quat, ToQuat};
|
2013-11-02 15:16:18 +00:00
|
|
|
use ray::Ray;
|
2013-09-17 02:32:07 +00:00
|
|
|
use vector::{Vector, Vec2, Vec3};
|
2013-09-05 03:55:01 +00:00
|
|
|
|
2013-11-01 11:34:39 +00:00
|
|
|
/// A trait for generic rotation
|
|
|
|
pub trait Rotation
|
2013-09-05 03:55:01 +00:00
|
|
|
<
|
2013-11-01 12:29:01 +00:00
|
|
|
S: Primitive,
|
2013-11-01 11:34:39 +00:00
|
|
|
Slice,
|
|
|
|
V: Vector<S,Slice>,
|
2013-11-01 12:29:01 +00:00
|
|
|
P: Point<S,V,Slice>
|
2013-09-05 03:55:01 +00:00
|
|
|
>
|
|
|
|
: Eq
|
|
|
|
+ ApproxEq<S>
|
|
|
|
{
|
2013-11-01 23:42:09 +00:00
|
|
|
fn identity() -> Self;
|
2013-11-01 11:34:39 +00:00
|
|
|
fn rotate_vec(&self, vec: &V) -> V;
|
|
|
|
|
2013-11-02 15:16:18 +00:00
|
|
|
#[inline]
|
|
|
|
fn rotate_point(&self, point: &P) -> P {
|
|
|
|
Point::from_vec( &self.rotate_vec( &point.to_vec() ) )
|
|
|
|
}
|
|
|
|
|
2013-11-01 11:34:39 +00:00
|
|
|
#[inline]
|
|
|
|
fn rotate_ray(&self, ray: &Ray<P,V>) -> Ray<P,V> {
|
2013-11-01 12:29:01 +00:00
|
|
|
Ray::new( //FIXME: use clone derived from Array
|
|
|
|
Array::build(|i| ray.origin.i(i).clone()),
|
|
|
|
self.rotate_vec(&ray.direction) )
|
2013-11-01 11:34:39 +00:00
|
|
|
}
|
|
|
|
|
2013-09-17 02:32:07 +00:00
|
|
|
fn concat(&self, other: &Self) -> Self;
|
|
|
|
fn invert(&self) -> Self;
|
2013-11-01 11:34:39 +00:00
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn concat_self(&mut self, other: &Self) {
|
|
|
|
*self = self.concat(other);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn invert_self(&mut self) {
|
|
|
|
*self = self.invert();
|
|
|
|
}
|
2013-09-05 03:55:01 +00:00
|
|
|
}
|
|
|
|
|
2013-11-01 11:34:39 +00:00
|
|
|
/// A two-dimensional rotation
|
|
|
|
pub trait Rotation2
|
|
|
|
<
|
|
|
|
S
|
|
|
|
>
|
|
|
|
: Rotation<S, [S, ..2], Vec2<S>, Point2<S>>
|
|
|
|
+ ToMat2<S>
|
|
|
|
+ ToBasis2<S>
|
|
|
|
{}
|
|
|
|
|
2013-09-05 03:55:01 +00:00
|
|
|
/// A three-dimensional rotation
|
|
|
|
pub trait Rotation3
|
|
|
|
<
|
|
|
|
S
|
|
|
|
>
|
2013-11-01 11:34:39 +00:00
|
|
|
: Rotation<S, [S, ..3], Vec3<S>, Point3<S>>
|
2013-09-05 03:55:01 +00:00
|
|
|
+ ToMat3<S>
|
2013-10-13 00:00:07 +00:00
|
|
|
+ ToBasis3<S>
|
2013-09-05 03:55:01 +00:00
|
|
|
+ ToQuat<S>
|
2013-11-01 11:34:39 +00:00
|
|
|
{}
|
|
|
|
|
2013-09-05 03:55:01 +00:00
|
|
|
|
|
|
|
/// A two-dimensional rotation matrix.
|
|
|
|
///
|
|
|
|
/// The matrix is guaranteed to be orthogonal, so some operations can be
|
|
|
|
/// implemented more efficiently than the implementations for `math::Mat2`. To
|
|
|
|
/// enforce orthogonality at the type level the operations have been restricted
|
|
|
|
/// to a subeset of those implemented on `Mat2`.
|
|
|
|
#[deriving(Eq, Clone)]
|
2013-10-13 00:00:07 +00:00
|
|
|
pub struct Basis2<S> {
|
2013-09-05 03:55:01 +00:00
|
|
|
priv mat: Mat2<S>
|
|
|
|
}
|
|
|
|
|
2013-10-13 00:00:07 +00:00
|
|
|
impl<S: Float> Basis2<S> {
|
2013-09-17 02:32:07 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn as_mat2<'a>(&'a self) -> &'a Mat2<S> { &'a self.mat }
|
|
|
|
}
|
|
|
|
|
2013-10-13 00:00:07 +00:00
|
|
|
pub trait ToBasis2<S: Float> {
|
|
|
|
fn to_rot2(&self) -> Basis2<S>;
|
2013-09-05 03:55:01 +00:00
|
|
|
}
|
|
|
|
|
2013-10-13 00:00:07 +00:00
|
|
|
impl<S: Float> ToBasis2<S> for Basis2<S> {
|
2013-09-17 02:32:07 +00:00
|
|
|
#[inline]
|
2013-10-13 00:00:07 +00:00
|
|
|
fn to_rot2(&self) -> Basis2<S> { self.clone() }
|
2013-09-17 02:32:07 +00:00
|
|
|
}
|
|
|
|
|
2013-10-13 00:00:07 +00:00
|
|
|
impl<S: Float> ToMat2<S> for Basis2<S> {
|
2013-09-17 02:32:07 +00:00
|
|
|
#[inline]
|
|
|
|
fn to_mat2(&self) -> Mat2<S> { self.mat.clone() }
|
|
|
|
}
|
|
|
|
|
2013-11-01 11:34:39 +00:00
|
|
|
impl<S: Float> Rotation<S, [S, ..2], Vec2<S>, Point2<S>> for Basis2<S> {
|
2013-11-01 23:42:09 +00:00
|
|
|
#[inline]
|
|
|
|
fn identity() -> Basis2<S> { Basis2{ mat: Mat2::identity() } }
|
|
|
|
|
2013-09-17 02:32:07 +00:00
|
|
|
#[inline]
|
2013-11-01 11:34:39 +00:00
|
|
|
fn rotate_vec(&self, vec: &Vec2<S>) -> Vec2<S> { self.mat.mul_v(vec) }
|
2013-09-17 02:32:07 +00:00
|
|
|
|
|
|
|
#[inline]
|
2013-10-13 00:00:07 +00:00
|
|
|
fn concat(&self, other: &Basis2<S>) -> Basis2<S> { Basis2 { mat: self.mat.mul_m(&other.mat) } }
|
2013-09-17 02:32:07 +00:00
|
|
|
|
|
|
|
#[inline]
|
2013-10-13 00:00:07 +00:00
|
|
|
fn concat_self(&mut self, other: &Basis2<S>) { self.mat.mul_self_m(&other.mat); }
|
2013-09-17 02:32:07 +00:00
|
|
|
|
|
|
|
// TODO: we know the matrix is orthogonal, so this could be re-written
|
|
|
|
// to be faster
|
|
|
|
#[inline]
|
2013-10-13 00:00:07 +00:00
|
|
|
fn invert(&self) -> Basis2<S> { Basis2 { mat: self.mat.invert().unwrap() } }
|
2013-09-17 02:32:07 +00:00
|
|
|
|
|
|
|
// TODO: we know the matrix is orthogonal, so this could be re-written
|
|
|
|
// to be faster
|
|
|
|
#[inline]
|
|
|
|
fn invert_self(&mut self) { self.mat.invert_self(); }
|
|
|
|
}
|
|
|
|
|
2013-10-13 00:00:07 +00:00
|
|
|
impl<S: Float> ApproxEq<S> for Basis2<S> {
|
2013-09-17 02:32:07 +00:00
|
|
|
#[inline]
|
|
|
|
fn approx_epsilon() -> S {
|
|
|
|
// TODO: fix this after static methods are fixed in rustc
|
|
|
|
fail!(~"Doesn't work!");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2013-10-13 00:00:07 +00:00
|
|
|
fn approx_eq(&self, other: &Basis2<S>) -> bool {
|
2013-09-17 02:32:07 +00:00
|
|
|
self.mat.approx_eq(&other.mat)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2013-10-13 00:00:07 +00:00
|
|
|
fn approx_eq_eps(&self, other: &Basis2<S>, approx_epsilon: &S) -> bool {
|
2013-09-17 02:32:07 +00:00
|
|
|
self.mat.approx_eq_eps(&other.mat, approx_epsilon)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-01 11:34:39 +00:00
|
|
|
impl<S: Float> Rotation2<S> for Basis2<S> {}
|
|
|
|
|
2013-09-05 03:55:01 +00:00
|
|
|
/// A three-dimensional rotation matrix.
|
|
|
|
///
|
|
|
|
/// The matrix is guaranteed to be orthogonal, so some operations, specifically
|
|
|
|
/// inversion, can be implemented more efficiently than the implementations for
|
2013-09-17 02:32:07 +00:00
|
|
|
/// `math::Mat3`. To ensure orthogonality is maintained, the operations have
|
2013-09-05 03:55:01 +00:00
|
|
|
/// been restricted to a subeset of those implemented on `Mat3`.
|
|
|
|
#[deriving(Eq, Clone)]
|
2013-10-13 00:00:07 +00:00
|
|
|
pub struct Basis3<S> {
|
2013-09-05 03:55:01 +00:00
|
|
|
priv mat: Mat3<S>
|
|
|
|
}
|
|
|
|
|
2013-10-13 00:00:07 +00:00
|
|
|
impl<S: Float> Basis3<S> {
|
2013-09-17 02:32:07 +00:00
|
|
|
#[inline]
|
2013-10-13 00:00:07 +00:00
|
|
|
pub fn look_at(dir: &Vec3<S>, up: &Vec3<S>) -> Basis3<S> {
|
|
|
|
Basis3 { mat: Mat3::look_at(dir, up) }
|
2013-09-17 02:32:07 +00:00
|
|
|
}
|
|
|
|
|
2013-09-30 04:30:40 +00:00
|
|
|
/// Create a rotation matrix from a rotation around the `x` axis (pitch).
|
2013-10-13 00:00:07 +00:00
|
|
|
pub fn from_angle_x(theta: Rad<S>) -> Basis3<S> {
|
|
|
|
Basis3 { mat: Mat3::from_angle_x(theta) }
|
2013-09-30 04:30:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Create a rotation matrix from a rotation around the `y` axis (yaw).
|
2013-10-13 00:00:07 +00:00
|
|
|
pub fn from_angle_y(theta: Rad<S>) -> Basis3<S> {
|
|
|
|
Basis3 { mat: Mat3::from_angle_y(theta) }
|
2013-09-30 04:30:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Create a rotation matrix from a rotation around the `z` axis (roll).
|
2013-10-13 00:00:07 +00:00
|
|
|
pub fn from_angle_z(theta: Rad<S>) -> Basis3<S> {
|
|
|
|
Basis3 { mat: Mat3::from_angle_z(theta) }
|
2013-09-30 04:30:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Create a rotation matrix from a set of euler angles.
|
|
|
|
///
|
|
|
|
/// # Parameters
|
|
|
|
///
|
|
|
|
/// - `x`: the angular rotation around the `x` axis (pitch).
|
|
|
|
/// - `y`: the angular rotation around the `y` axis (yaw).
|
|
|
|
/// - `z`: the angular rotation around the `z` axis (roll).
|
2013-10-13 00:00:07 +00:00
|
|
|
pub fn from_euler(x: Rad<S>, y: Rad<S>, z: Rad<S>) -> Basis3<S> {
|
|
|
|
Basis3 { mat: Mat3::from_euler(x, y ,z) }
|
2013-09-30 04:30:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Create a rotation matrix from a rotation around an arbitrary axis.
|
2013-10-13 00:00:07 +00:00
|
|
|
pub fn from_axis_angle(axis: &Vec3<S>, angle: Rad<S>) -> Basis3<S> {
|
|
|
|
Basis3 { mat: Mat3::from_axis_angle(axis, angle) }
|
2013-09-30 04:30:40 +00:00
|
|
|
}
|
|
|
|
|
2013-09-17 02:32:07 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn as_mat3<'a>(&'a self) -> &'a Mat3<S> { &'a self.mat }
|
|
|
|
}
|
|
|
|
|
2013-10-13 00:00:07 +00:00
|
|
|
pub trait ToBasis3<S: Float> {
|
|
|
|
fn to_rot3(&self) -> Basis3<S>;
|
2013-09-05 03:55:01 +00:00
|
|
|
}
|
|
|
|
|
2013-10-13 00:00:07 +00:00
|
|
|
impl<S: Float> ToBasis3<S> for Basis3<S> {
|
2013-09-17 02:32:07 +00:00
|
|
|
#[inline]
|
2013-10-13 00:00:07 +00:00
|
|
|
fn to_rot3(&self) -> Basis3<S> { self.clone() }
|
2013-09-17 02:32:07 +00:00
|
|
|
}
|
|
|
|
|
2013-10-13 00:00:07 +00:00
|
|
|
impl<S: Float> ToMat3<S> for Basis3<S> {
|
2013-09-17 02:32:07 +00:00
|
|
|
#[inline]
|
|
|
|
fn to_mat3(&self) -> Mat3<S> { self.mat.clone() }
|
|
|
|
}
|
|
|
|
|
2013-10-13 00:00:07 +00:00
|
|
|
impl<S: Float> ToQuat<S> for Basis3<S> {
|
2013-09-17 02:32:07 +00:00
|
|
|
#[inline]
|
|
|
|
fn to_quat(&self) -> Quat<S> { self.mat.to_quat() }
|
|
|
|
}
|
|
|
|
|
2013-11-01 11:34:39 +00:00
|
|
|
impl<S: Float> Rotation<S, [S, ..3], Vec3<S>, Point3<S>> for Basis3<S> {
|
2013-11-01 23:42:09 +00:00
|
|
|
#[inline]
|
|
|
|
fn identity() -> Basis3<S> { Basis3{ mat: Mat3::identity() } }
|
|
|
|
|
2013-09-17 02:32:07 +00:00
|
|
|
#[inline]
|
2013-11-01 11:34:39 +00:00
|
|
|
fn rotate_vec(&self, vec: &Vec3<S>) -> Vec3<S> { self.mat.mul_v(vec) }
|
2013-09-17 02:32:07 +00:00
|
|
|
|
|
|
|
#[inline]
|
2013-10-13 00:00:07 +00:00
|
|
|
fn concat(&self, other: &Basis3<S>) -> Basis3<S> { Basis3 { mat: self.mat.mul_m(&other.mat) } }
|
2013-09-17 02:32:07 +00:00
|
|
|
|
|
|
|
#[inline]
|
2013-10-13 00:00:07 +00:00
|
|
|
fn concat_self(&mut self, other: &Basis3<S>) { self.mat.mul_self_m(&other.mat); }
|
2013-09-17 02:32:07 +00:00
|
|
|
|
|
|
|
// TODO: we know the matrix is orthogonal, so this could be re-written
|
|
|
|
// to be faster
|
|
|
|
#[inline]
|
2013-10-13 00:00:07 +00:00
|
|
|
fn invert(&self) -> Basis3<S> { Basis3 { mat: self.mat.invert().unwrap() } }
|
2013-09-17 02:32:07 +00:00
|
|
|
|
|
|
|
// TODO: we know the matrix is orthogonal, so this could be re-written
|
|
|
|
// to be faster
|
|
|
|
#[inline]
|
|
|
|
fn invert_self(&mut self) { self.mat.invert_self(); }
|
|
|
|
}
|
|
|
|
|
2013-10-13 00:00:07 +00:00
|
|
|
impl<S: Float> ApproxEq<S> for Basis3<S> {
|
2013-09-17 02:32:07 +00:00
|
|
|
#[inline]
|
|
|
|
fn approx_epsilon() -> S {
|
|
|
|
// TODO: fix this after static methods are fixed in rustc
|
|
|
|
fail!(~"Doesn't work!");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2013-10-13 00:00:07 +00:00
|
|
|
fn approx_eq(&self, other: &Basis3<S>) -> bool {
|
2013-09-17 02:32:07 +00:00
|
|
|
self.mat.approx_eq(&other.mat)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2013-10-13 00:00:07 +00:00
|
|
|
fn approx_eq_eps(&self, other: &Basis3<S>, approx_epsilon: &S) -> bool {
|
2013-09-17 02:32:07 +00:00
|
|
|
self.mat.approx_eq_eps(&other.mat, approx_epsilon)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-01 11:34:39 +00:00
|
|
|
impl<S: Float> Rotation3<S> for Basis3<S> {}
|
|
|
|
|
2013-09-17 02:32:07 +00:00
|
|
|
// Quaternion Rotation impls
|
|
|
|
|
2013-10-13 00:00:07 +00:00
|
|
|
impl<S: Float> ToBasis3<S> for Quat<S> {
|
2013-09-17 02:32:07 +00:00
|
|
|
#[inline]
|
2013-10-13 00:00:07 +00:00
|
|
|
fn to_rot3(&self) -> Basis3<S> { Basis3 { mat: self.to_mat3() } }
|
2013-09-17 02:32:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<S: Float> ToQuat<S> for Quat<S> {
|
|
|
|
#[inline]
|
|
|
|
fn to_quat(&self) -> Quat<S> { self.clone() }
|
|
|
|
}
|
|
|
|
|
2013-11-01 11:34:39 +00:00
|
|
|
impl<S: Float> Rotation<S, [S, ..3], Vec3<S>, Point3<S>> for Quat<S> {
|
2013-11-01 23:42:09 +00:00
|
|
|
#[inline]
|
|
|
|
fn identity() -> Quat<S> { Quat::identity() }
|
|
|
|
|
2013-09-17 02:32:07 +00:00
|
|
|
#[inline]
|
2013-11-01 11:34:39 +00:00
|
|
|
fn rotate_vec(&self, vec: &Vec3<S>) -> Vec3<S> { self.mul_v(vec) }
|
2013-09-17 02:32:07 +00:00
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn concat(&self, other: &Quat<S>) -> Quat<S> { self.mul_q(other) }
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn concat_self(&mut self, other: &Quat<S>) { self.mul_self_q(other); }
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn invert(&self) -> Quat<S> { self.conjugate().div_s(self.magnitude2()) }
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn invert_self(&mut self) { *self = self.invert() }
|
|
|
|
}
|
2013-11-01 11:34:39 +00:00
|
|
|
|
2013-11-01 23:42:09 +00:00
|
|
|
impl<S: Float> Rotation3<S> for Quat<S> {}
|