diff --git a/src/cgmath/rotation.rs b/src/cgmath/rotation.rs new file mode 100644 index 0000000..830a64f --- /dev/null +++ b/src/cgmath/rotation.rs @@ -0,0 +1,147 @@ +// 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 angle::Angle; +use array::Array; +use matrix::{Mat2, ToMat2}; +use matrix::{Mat3, ToMat3}; +use point::{Point2, Point3}; +use quaternion::ToQuat; +use ray::{Ray2, Ray3}; +use vector::{Vec2, Vec3}; + +/// A two-dimensional rotation +pub trait Rotation2 +< + S +> +: Eq ++ ApproxEq ++ Neg ++ Add ++ Sub ++ ToMat2 ++ ToRot2 +{ + fn rotate_point2(&self, point: Point2) -> Point2; + fn rotate_vec2(&self, vec: &Vec2) -> Vec2; + fn rotate_ray2(&self, ray: &Ray2) -> Ray2; +} + +/// A three-dimensional rotation +pub trait Rotation3 +< + S +> +: Eq ++ ApproxEq ++ Neg ++ Add ++ Sub ++ ToMat3 ++ ToRot3 ++ ToQuat +{ + fn rotate_point3(&self, point: &Point3) -> Point3; + fn rotate_vec3(&self, vec: &Vec3) -> Vec3; + fn rotate_ray3(&self, ray: &Ray3) -> Ray3; +} + +/// 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)] +pub struct Rot2 { + priv mat: Mat2 +} + +pub trait ToRot2 { + fn to_rot2(&self) -> Rot2; +} + +/// 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 +/// `math::Mat3`. To enforce orthogonality at the type level the operations have +/// been restricted to a subeset of those implemented on `Mat3`. +#[deriving(Eq, Clone)] +pub struct Rot3 { + priv mat: Mat3 +} + +pub trait ToRot3 { + fn to_rot3(&self) -> Rot3; +} + +/// Euler angles +/// +/// Whilst Euler angles are easier to visualise, and more intuitive to specify, +/// they are not reccomended for general use because they are prone to gimble +/// lock. +/// +/// # Fields +/// +/// - `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) +#[deriving(Eq, Clone)] +pub struct Euler { x: A, y: A, z: A } + +array!(impl Euler -> [A, ..3]) + +pub trait ToEuler { + fn to_euler(&self) -> Euler; +} + +impl> Euler { + #[inline] + pub fn new(x: A, y: A, z: A) -> Euler { + Euler { x: x, y: y, z: z } + } +} + +/// A rotation about an arbitrary axis +#[deriving(Eq, Clone)] +pub struct AxisAngle { + axis: Vec3, + angle: A, +} + +/// An angle around the X axis (pitch). +#[deriving(Eq, Ord, Clone)] +pub struct AngleX(A); + +/// An angle around the X axis (yaw). +#[deriving(Eq, Ord, Clone)] +pub struct AngleY(A); + +/// An angle around the Z axis (roll). +#[deriving(Eq, Ord, Clone)] +pub struct AngleZ(A); + +impl> Neg> for AngleX { #[inline] fn neg(&self) -> AngleX { AngleX(-**self) } } +impl> Neg> for AngleY { #[inline] fn neg(&self) -> AngleY { AngleY(-**self) } } +impl> Neg> for AngleZ { #[inline] fn neg(&self) -> AngleZ { AngleZ(-**self) } } + +impl> Add, AngleX> for AngleX { #[inline] fn add(&self, other: &AngleX) -> AngleX { AngleX((**self).add_a(*other.clone())) } } +impl> Add, AngleY> for AngleY { #[inline] fn add(&self, other: &AngleY) -> AngleY { AngleY((**self).add_a(*other.clone())) } } +impl> Add, AngleZ> for AngleZ { #[inline] fn add(&self, other: &AngleZ) -> AngleZ { AngleZ((**self).add_a(*other.clone())) } } +impl> Sub, AngleX> for AngleX { #[inline] fn sub(&self, other: &AngleX) -> AngleX { AngleX((**self).sub_a(*other.clone())) } } +impl> Sub, AngleY> for AngleY { #[inline] fn sub(&self, other: &AngleY) -> AngleY { AngleY((**self).sub_a(*other.clone())) } } +impl> Sub, AngleZ> for AngleZ { #[inline] fn sub(&self, other: &AngleZ) -> AngleZ { AngleZ((**self).sub_a(*other.clone())) } }