2014-01-25 15:54:54 +00:00
|
|
|
// Copyright 2014 The CGMath Developers. For a full listing of the authors,
|
2015-03-14 02:49:46 +00:00
|
|
|
// refer to the Cargo.toml file at the top-level directory of this distribution.
|
2013-09-05 03:55:01 +00:00
|
|
|
//
|
|
|
|
// 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.
|
|
|
|
|
2014-01-30 00:24:34 +00:00
|
|
|
use angle::{Rad, acos};
|
2014-01-09 00:26:50 +00:00
|
|
|
use approx::ApproxEq;
|
2013-09-17 02:32:07 +00:00
|
|
|
use matrix::Matrix;
|
2015-05-06 08:27:52 +00:00
|
|
|
use matrix::Matrix2;
|
|
|
|
use matrix::Matrix3;
|
2014-05-26 17:10:04 +00:00
|
|
|
use num::{BaseNum, BaseFloat};
|
2013-11-01 11:34:39 +00:00
|
|
|
use point::{Point, Point2, Point3};
|
2014-04-14 01:30:24 +00:00
|
|
|
use quaternion::{Quaternion, ToQuaternion};
|
2013-11-02 15:16:18 +00:00
|
|
|
use ray::Ray;
|
2014-04-14 01:30:24 +00:00
|
|
|
use vector::{Vector, Vector2, Vector3};
|
2013-09-05 03:55:01 +00:00
|
|
|
|
2014-05-25 11:10:44 +00:00
|
|
|
/// A trait for a generic rotation. A rotation is a transformation that
|
|
|
|
/// creates a circular motion, and preserves at least one point in the space.
|
2015-01-03 21:29:26 +00:00
|
|
|
pub trait Rotation<S: BaseNum, V: Vector<S>, P: Point<S, V>>: PartialEq + ApproxEq<S> + Sized {
|
2014-05-25 11:10:44 +00:00
|
|
|
/// Create the identity transform (causes no transformation).
|
2013-11-01 23:42:09 +00:00
|
|
|
fn identity() -> Self;
|
2014-01-30 00:24:34 +00:00
|
|
|
|
|
|
|
/// Create a rotation to a given direction with an 'up' vector
|
2014-01-25 15:54:54 +00:00
|
|
|
fn look_at(dir: &V, up: &V) -> Self;
|
2014-05-25 11:10:44 +00:00
|
|
|
|
2014-01-30 00:24:34 +00:00
|
|
|
/// Create a shortest rotation to transform vector 'a' into 'b'.
|
|
|
|
/// Both given vectors are assumed to have unit length.
|
2014-04-14 01:30:24 +00:00
|
|
|
fn between_vectors(a: &V, b: &V) -> Self;
|
2014-01-25 15:54:54 +00:00
|
|
|
|
2014-05-25 11:10:44 +00:00
|
|
|
/// Rotate a vector using this rotation.
|
2014-04-14 01:30:24 +00:00
|
|
|
fn rotate_vector(&self, vec: &V) -> V;
|
2013-11-01 11:34:39 +00:00
|
|
|
|
2014-05-25 11:10:44 +00:00
|
|
|
/// Rotate a point using this rotation, by converting it to its
|
|
|
|
/// representation as a vector.
|
2013-11-02 15:16:18 +00:00
|
|
|
#[inline]
|
2013-11-09 01:15:51 +00:00
|
|
|
fn rotate_point(&self, point: &P) -> P {
|
2014-04-14 01:30:24 +00:00
|
|
|
Point::from_vec( &self.rotate_vector( &point.to_vec() ) )
|
2013-11-02 15:16:18 +00:00
|
|
|
}
|
|
|
|
|
2014-05-25 11:10:44 +00:00
|
|
|
/// Rotate a ray using this rotation.
|
2013-11-01 11:34:39 +00:00
|
|
|
#[inline]
|
2015-03-29 21:35:47 +00:00
|
|
|
fn rotate_ray(&self, ray: &Ray<S, P, V>) -> Ray<S, P,V> {
|
2014-05-28 01:59:03 +00:00
|
|
|
Ray::new(ray.origin.clone(), self.rotate_vector(&ray.direction))
|
2013-11-01 11:34:39 +00:00
|
|
|
}
|
|
|
|
|
2014-05-25 11:10:44 +00:00
|
|
|
/// Create a new rotation which combines both this rotation, and another.
|
2013-09-17 02:32:07 +00:00
|
|
|
fn concat(&self, other: &Self) -> Self;
|
2014-05-25 11:10:44 +00:00
|
|
|
|
|
|
|
/// Create a new rotation which "un-does" this rotation. That is,
|
|
|
|
/// `r.concat(r.invert())` is the identity.
|
2013-09-17 02:32:07 +00:00
|
|
|
fn invert(&self) -> Self;
|
2013-11-01 11:34:39 +00:00
|
|
|
|
2014-05-25 11:10:44 +00:00
|
|
|
/// Modify this rotation in-place by combining it with another.
|
2013-11-01 11:34:39 +00:00
|
|
|
#[inline]
|
|
|
|
fn concat_self(&mut self, other: &Self) {
|
2014-11-25 04:04:34 +00:00
|
|
|
*self = Rotation::concat(self, other);
|
2013-11-01 11:34:39 +00:00
|
|
|
}
|
2014-05-25 11:10:44 +00:00
|
|
|
|
|
|
|
/// Invert this rotation in-place.
|
2013-11-01 11:34:39 +00:00
|
|
|
#[inline]
|
2013-11-09 01:15:51 +00:00
|
|
|
fn invert_self(&mut self) {
|
2013-11-01 11:34:39 +00:00
|
|
|
*self = self.invert();
|
|
|
|
}
|
2013-09-05 03:55:01 +00:00
|
|
|
}
|
|
|
|
|
2014-05-25 11:10:44 +00:00
|
|
|
/// A two-dimensional rotation.
|
2014-05-28 01:59:03 +00:00
|
|
|
pub trait Rotation2<S>: Rotation<S, Vector2<S>, Point2<S>>
|
2015-05-06 08:27:52 +00:00
|
|
|
+ Into<Matrix2<S>>
|
2014-05-28 01:59:03 +00:00
|
|
|
+ ToBasis2<S> {
|
2014-05-25 11:10:44 +00:00
|
|
|
/// Create a rotation by a given angle. Thus is a redundant case of both
|
|
|
|
/// from_axis_angle() and from_euler() for 2D space.
|
2014-01-30 00:24:34 +00:00
|
|
|
fn from_angle(theta: Rad<S>) -> Self;
|
|
|
|
}
|
2013-11-01 11:34:39 +00:00
|
|
|
|
2014-05-25 11:10:44 +00:00
|
|
|
/// A three-dimensional rotation.
|
2014-05-28 01:59:03 +00:00
|
|
|
pub trait Rotation3<S: BaseNum>: Rotation<S, Vector3<S>, Point3<S>>
|
2015-05-06 08:27:52 +00:00
|
|
|
+ Into<Matrix3<S>>
|
2014-05-28 01:59:03 +00:00
|
|
|
+ ToBasis3<S>
|
|
|
|
+ ToQuaternion<S>{
|
2014-05-25 11:10:44 +00:00
|
|
|
/// Create a rotation using an angle around a given axis.
|
2014-04-14 01:30:24 +00:00
|
|
|
fn from_axis_angle(axis: &Vector3<S>, angle: Rad<S>) -> Self;
|
2014-01-30 00:24:34 +00:00
|
|
|
|
|
|
|
/// Create a rotation 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).
|
|
|
|
fn from_euler(x: Rad<S>, y: Rad<S>, z: Rad<S>) -> Self;
|
|
|
|
|
2014-05-25 11:10:44 +00:00
|
|
|
/// Create a rotation from an angle around the `x` axis (pitch).
|
2014-01-30 00:24:34 +00:00
|
|
|
#[inline]
|
|
|
|
fn from_angle_x(theta: Rad<S>) -> Self {
|
2014-04-14 01:30:24 +00:00
|
|
|
Rotation3::from_axis_angle( &Vector3::unit_x(), theta )
|
2014-01-30 00:24:34 +00:00
|
|
|
}
|
|
|
|
|
2014-05-25 11:10:44 +00:00
|
|
|
/// Create a rotation from an angle around the `y` axis (yaw).
|
2014-01-30 00:24:34 +00:00
|
|
|
#[inline]
|
|
|
|
fn from_angle_y(theta: Rad<S>) -> Self {
|
2014-04-14 01:30:24 +00:00
|
|
|
Rotation3::from_axis_angle( &Vector3::unit_y(), theta )
|
2014-01-30 00:24:34 +00:00
|
|
|
}
|
|
|
|
|
2014-05-25 11:10:44 +00:00
|
|
|
/// Create a rotation from an angle around the `z` axis (roll).
|
2014-01-30 00:24:34 +00:00
|
|
|
#[inline]
|
|
|
|
fn from_angle_z(theta: Rad<S>) -> Self {
|
2014-04-14 01:30:24 +00:00
|
|
|
Rotation3::from_axis_angle( &Vector3::unit_z(), theta )
|
2014-01-30 00:24:34 +00:00
|
|
|
}
|
|
|
|
}
|
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
|
2014-04-14 01:30:24 +00:00
|
|
|
/// implemented more efficiently than the implementations for `math::Matrix2`. To
|
2013-09-05 03:55:01 +00:00
|
|
|
/// enforce orthogonality at the type level the operations have been restricted
|
2014-04-14 01:30:24 +00:00
|
|
|
/// to a subset of those implemented on `Matrix2`.
|
2014-07-24 03:25:42 +00:00
|
|
|
///
|
|
|
|
/// ## Example
|
2014-08-16 04:51:09 +00:00
|
|
|
///
|
2014-07-24 03:25:42 +00:00
|
|
|
/// Suppose we want to rotate a vector that lies in the x-y plane by some
|
|
|
|
/// angle. We can accomplish this quite easily with a two-dimensional rotation
|
|
|
|
/// matrix:
|
|
|
|
///
|
2015-03-14 21:56:36 +00:00
|
|
|
/// ```no_run
|
2014-08-16 04:51:09 +00:00
|
|
|
/// use cgmath::rad;
|
|
|
|
/// use cgmath::Vector2;
|
2015-05-06 08:27:52 +00:00
|
|
|
/// use cgmath::{Matrix, Matrix2};
|
2014-08-16 04:51:09 +00:00
|
|
|
/// use cgmath::{Rotation, Rotation2, Basis2};
|
|
|
|
/// use cgmath::ApproxEq;
|
2014-11-25 04:24:04 +00:00
|
|
|
/// use std::f64;
|
2014-07-24 03:25:42 +00:00
|
|
|
///
|
|
|
|
/// // For simplicity, we will rotate the unit x vector to the unit y vector --
|
|
|
|
/// // so the angle is 90 degrees, or π/2.
|
|
|
|
/// let unit_x: Vector2<f64> = Vector2::unit_x();
|
2014-11-25 04:24:04 +00:00
|
|
|
/// let rot: Basis2<f64> = Rotation2::from_angle(rad(0.5f64 * f64::consts::PI));
|
2014-07-24 03:25:42 +00:00
|
|
|
///
|
|
|
|
/// // Rotate the vector using the two-dimensional rotation matrix:
|
|
|
|
/// let unit_y = rot.rotate_vector(&unit_x);
|
|
|
|
///
|
|
|
|
/// // Since sin(π/2) may not be exactly zero due to rounding errors, we can
|
|
|
|
/// // use cgmath's approx_eq() feature to show that it is close enough.
|
2014-08-06 05:28:03 +00:00
|
|
|
/// assert!(unit_y.approx_eq(&Vector2::unit_y()));
|
2014-07-24 03:25:42 +00:00
|
|
|
///
|
|
|
|
/// // This is exactly equivalent to using the raw matrix itself:
|
2015-05-06 08:27:52 +00:00
|
|
|
/// let unit_y2: Matrix2<_> = rot.into();
|
|
|
|
/// let unit_y2 = unit_y2.mul_v(&unit_x);
|
2014-07-24 03:25:42 +00:00
|
|
|
/// assert_eq!(unit_y2, unit_y);
|
|
|
|
///
|
|
|
|
/// // Note that we can also concatenate rotations:
|
2014-11-25 04:24:04 +00:00
|
|
|
/// let rot_half: Basis2<f64> = Rotation2::from_angle(rad(0.25f64 * f64::consts::PI));
|
2014-07-24 03:25:42 +00:00
|
|
|
/// let unit_y3 = rot_half.concat(&rot_half).rotate_vector(&unit_x);
|
|
|
|
/// assert!(unit_y3.approx_eq(&unit_y2));
|
2015-03-14 21:56:36 +00:00
|
|
|
/// ```
|
2015-01-03 21:29:26 +00:00
|
|
|
#[derive(PartialEq, Copy, Clone, RustcEncodable, RustcDecodable)]
|
2013-10-13 00:00:07 +00:00
|
|
|
pub struct Basis2<S> {
|
2014-04-14 01:30:24 +00:00
|
|
|
mat: Matrix2<S>
|
2013-09-05 03:55:01 +00:00
|
|
|
}
|
|
|
|
|
2014-05-26 17:10:04 +00:00
|
|
|
impl<S: BaseFloat> Basis2<S> {
|
2014-05-25 11:10:44 +00:00
|
|
|
/// Coerce to a `Matrix2`
|
2013-09-17 02:32:07 +00:00
|
|
|
#[inline]
|
2014-07-05 00:15:10 +00:00
|
|
|
pub fn as_matrix2<'a>(&'a self) -> &'a Matrix2<S> { &self.mat }
|
2013-09-17 02:32:07 +00:00
|
|
|
}
|
|
|
|
|
2014-05-25 11:10:44 +00:00
|
|
|
/// Represents types which can be converted to a rotation matrix.
|
2014-05-26 17:10:04 +00:00
|
|
|
pub trait ToBasis2<S: BaseFloat> {
|
2014-05-25 11:10:44 +00:00
|
|
|
/// Convert this type to a rotation matrix.
|
2013-10-13 00:00:07 +00:00
|
|
|
fn to_rot2(&self) -> Basis2<S>;
|
2013-09-05 03:55:01 +00:00
|
|
|
}
|
|
|
|
|
2014-05-26 17:10:04 +00:00
|
|
|
impl<S: BaseFloat> 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
|
|
|
}
|
|
|
|
|
2015-05-06 08:27:52 +00:00
|
|
|
impl<S: BaseFloat> From<Basis2<S>> for Matrix2<S> {
|
2013-09-17 02:32:07 +00:00
|
|
|
#[inline]
|
2015-05-06 08:27:52 +00:00
|
|
|
fn from(b: Basis2<S>) -> Matrix2<S> { b.mat }
|
2013-09-17 02:32:07 +00:00
|
|
|
}
|
|
|
|
|
2014-09-18 14:19:26 +00:00
|
|
|
impl<S: BaseFloat + 'static> Rotation<S, Vector2<S>, Point2<S>> for Basis2<S> {
|
2013-11-01 23:42:09 +00:00
|
|
|
#[inline]
|
2014-04-14 01:30:24 +00:00
|
|
|
fn identity() -> Basis2<S> { Basis2{ mat: Matrix2::identity() } }
|
2014-01-25 15:54:54 +00:00
|
|
|
|
|
|
|
#[inline]
|
2014-04-14 01:30:24 +00:00
|
|
|
fn look_at(dir: &Vector2<S>, up: &Vector2<S>) -> Basis2<S> {
|
|
|
|
Basis2 { mat: Matrix2::look_at(dir, up) }
|
2014-01-25 15:54:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2014-04-14 01:30:24 +00:00
|
|
|
fn between_vectors(a: &Vector2<S>, b: &Vector2<S>) -> Basis2<S> {
|
2014-01-30 00:24:34 +00:00
|
|
|
Rotation2::from_angle( acos(a.dot(b)) )
|
2014-01-25 15:54:54 +00:00
|
|
|
}
|
2014-05-25 11:10:44 +00:00
|
|
|
|
2013-09-17 02:32:07 +00:00
|
|
|
#[inline]
|
2014-04-14 01:30:24 +00:00
|
|
|
fn rotate_vector(&self, vec: &Vector2<S>) -> Vector2<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(); }
|
|
|
|
}
|
|
|
|
|
2014-05-26 17:10:04 +00:00
|
|
|
impl<S: BaseFloat> ApproxEq<S> for Basis2<S> {
|
2013-09-17 02:32:07 +00:00
|
|
|
#[inline]
|
2014-01-09 00:26:50 +00:00
|
|
|
fn approx_eq_eps(&self, other: &Basis2<S>, epsilon: &S) -> bool {
|
|
|
|
self.mat.approx_eq_eps(&other.mat, epsilon)
|
2013-09-17 02:32:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-18 14:19:26 +00:00
|
|
|
impl<S: BaseFloat + 'static> Rotation2<S> for Basis2<S> {
|
2014-04-14 01:30:24 +00:00
|
|
|
fn from_angle(theta: Rad<S>) -> Basis2<S> { Basis2 { mat: Matrix2::from_angle(theta) } }
|
2014-01-30 00:24:34 +00:00
|
|
|
}
|
2013-11-01 11:34:39 +00:00
|
|
|
|
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
|
2014-04-14 01:30:24 +00:00
|
|
|
/// `math::Matrix3`. To ensure orthogonality is maintained, the operations have
|
|
|
|
/// been restricted to a subeset of those implemented on `Matrix3`.
|
2015-01-03 21:29:26 +00:00
|
|
|
#[derive(PartialEq, Copy, Clone, RustcEncodable, RustcDecodable)]
|
2013-10-13 00:00:07 +00:00
|
|
|
pub struct Basis3<S> {
|
2014-04-14 01:30:24 +00:00
|
|
|
mat: Matrix3<S>
|
2013-09-05 03:55:01 +00:00
|
|
|
}
|
|
|
|
|
2014-05-26 17:10:04 +00:00
|
|
|
impl<S: BaseFloat> Basis3<S> {
|
2014-05-25 11:10:44 +00:00
|
|
|
/// Create a new rotation matrix from a quaternion.
|
2014-01-30 00:24:34 +00:00
|
|
|
#[inline]
|
2014-04-14 01:30:24 +00:00
|
|
|
pub fn from_quaternion(quaternion: &Quaternion<S>) -> Basis3<S> {
|
2015-05-06 08:27:52 +00:00
|
|
|
Basis3 { mat: quaternion.clone().into() }
|
2014-04-14 01:30:24 +00:00
|
|
|
}
|
2014-05-25 11:10:44 +00:00
|
|
|
|
|
|
|
/// Coerce to a `Matrix3`
|
2013-09-17 02:32:07 +00:00
|
|
|
#[inline]
|
2014-07-05 00:15:10 +00:00
|
|
|
pub fn as_matrix3<'a>(&'a self) -> &'a Matrix3<S> { &self.mat }
|
2013-09-17 02:32:07 +00:00
|
|
|
}
|
|
|
|
|
2014-05-25 11:10:44 +00:00
|
|
|
/// Represents types which can be converted to a rotation matrix.
|
2014-05-26 17:10:04 +00:00
|
|
|
pub trait ToBasis3<S: BaseFloat> {
|
2014-05-25 11:10:44 +00:00
|
|
|
/// Convert this type to a rotation matrix.
|
2013-10-13 00:00:07 +00:00
|
|
|
fn to_rot3(&self) -> Basis3<S>;
|
2013-09-05 03:55:01 +00:00
|
|
|
}
|
|
|
|
|
2014-05-26 17:10:04 +00:00
|
|
|
impl<S: BaseFloat> 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
|
|
|
}
|
|
|
|
|
2015-05-06 08:27:52 +00:00
|
|
|
impl<S: BaseFloat> From<Basis3<S>> for Matrix3<S> {
|
2013-09-17 02:32:07 +00:00
|
|
|
#[inline]
|
2015-05-06 08:27:52 +00:00
|
|
|
fn from(b: Basis3<S>) -> Matrix3<S> { b.mat }
|
2013-09-17 02:32:07 +00:00
|
|
|
}
|
|
|
|
|
2014-09-18 14:19:26 +00:00
|
|
|
impl<S: BaseFloat + 'static> ToQuaternion<S> for Basis3<S> {
|
2013-09-17 02:32:07 +00:00
|
|
|
#[inline]
|
2014-04-14 01:30:24 +00:00
|
|
|
fn to_quaternion(&self) -> Quaternion<S> { self.mat.to_quaternion() }
|
2013-09-17 02:32:07 +00:00
|
|
|
}
|
|
|
|
|
2014-09-18 14:19:26 +00:00
|
|
|
impl<S: BaseFloat + 'static> Rotation<S, Vector3<S>, Point3<S>> for Basis3<S> {
|
2013-11-01 23:42:09 +00:00
|
|
|
#[inline]
|
2014-04-14 01:30:24 +00:00
|
|
|
fn identity() -> Basis3<S> { Basis3{ mat: Matrix3::identity() } }
|
2014-01-25 15:54:54 +00:00
|
|
|
|
|
|
|
#[inline]
|
2014-04-14 01:30:24 +00:00
|
|
|
fn look_at(dir: &Vector3<S>, up: &Vector3<S>) -> Basis3<S> {
|
|
|
|
Basis3 { mat: Matrix3::look_at(dir, up) }
|
2014-01-25 15:54:54 +00:00
|
|
|
}
|
2014-01-30 00:24:34 +00:00
|
|
|
|
|
|
|
#[inline]
|
2014-04-14 01:30:24 +00:00
|
|
|
fn between_vectors(a: &Vector3<S>, b: &Vector3<S>) -> Basis3<S> {
|
|
|
|
let q: Quaternion<S> = Rotation::between_vectors(a, b);
|
2014-01-30 00:24:34 +00:00
|
|
|
q.to_rot3()
|
|
|
|
}
|
2014-05-25 11:10:44 +00:00
|
|
|
|
2013-09-17 02:32:07 +00:00
|
|
|
#[inline]
|
2014-04-14 01:30:24 +00:00
|
|
|
fn rotate_vector(&self, vec: &Vector3<S>) -> Vector3<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(); }
|
|
|
|
}
|
|
|
|
|
2014-05-26 17:10:04 +00:00
|
|
|
impl<S: BaseFloat> ApproxEq<S> for Basis3<S> {
|
2013-09-17 02:32:07 +00:00
|
|
|
#[inline]
|
2014-01-09 00:26:50 +00:00
|
|
|
fn approx_eq_eps(&self, other: &Basis3<S>, epsilon: &S) -> bool {
|
|
|
|
self.mat.approx_eq_eps(&other.mat, epsilon)
|
2013-09-17 02:32:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-18 14:19:26 +00:00
|
|
|
impl<S: BaseFloat + 'static> Rotation3<S> for Basis3<S> {
|
2014-04-14 01:30:24 +00:00
|
|
|
fn from_axis_angle(axis: &Vector3<S>, angle: Rad<S>) -> Basis3<S> {
|
|
|
|
Basis3 { mat: Matrix3::from_axis_angle(axis, angle) }
|
2014-01-25 15:54:54 +00:00
|
|
|
}
|
2013-09-17 02:32:07 +00:00
|
|
|
|
2014-01-30 00:24:34 +00:00
|
|
|
fn from_euler(x: Rad<S>, y: Rad<S>, z: Rad<S>) -> Basis3<S> {
|
2014-04-14 01:30:24 +00:00
|
|
|
Basis3 { mat: Matrix3::from_euler(x, y ,z) }
|
2014-01-30 00:24:34 +00:00
|
|
|
}
|
2013-09-17 02:32:07 +00:00
|
|
|
|
2014-01-30 00:24:34 +00:00
|
|
|
fn from_angle_x(theta: Rad<S>) -> Basis3<S> {
|
2014-04-14 01:30:24 +00:00
|
|
|
Basis3 { mat: Matrix3::from_angle_x(theta) }
|
2014-01-30 00:24:34 +00:00
|
|
|
}
|
2013-09-17 02:32:07 +00:00
|
|
|
|
2014-01-30 00:24:34 +00:00
|
|
|
fn from_angle_y(theta: Rad<S>) -> Basis3<S> {
|
2014-04-14 01:30:24 +00:00
|
|
|
Basis3 { mat: Matrix3::from_angle_y(theta) }
|
2014-01-30 00:24:34 +00:00
|
|
|
}
|
2013-09-17 02:32:07 +00:00
|
|
|
|
2014-01-30 00:24:34 +00:00
|
|
|
fn from_angle_z(theta: Rad<S>) -> Basis3<S> {
|
2014-04-14 01:30:24 +00:00
|
|
|
Basis3 { mat: Matrix3::from_angle_z(theta) }
|
2014-01-30 00:24:34 +00:00
|
|
|
}
|
2013-09-17 02:32:07 +00:00
|
|
|
}
|