2016-12-05 05:44:42 +08:00
|
|
|
#[cfg(feature = "arbitrary")]
|
|
|
|
use quickcheck::{Arbitrary, Gen};
|
2017-08-03 01:37:44 +08:00
|
|
|
#[cfg(feature = "arbitrary")]
|
|
|
|
use core::storage::Owned;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
|
|
use num::One;
|
|
|
|
use rand::{Rng, Rand};
|
|
|
|
|
|
|
|
use alga::general::Real;
|
|
|
|
use alga::linear::Rotation as AlgaRotation;
|
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
use core::{DefaultAllocator, Vector2, Vector3};
|
|
|
|
use core::dimension::{DimName, U2, U3};
|
|
|
|
use core::allocator::Allocator;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
use geometry::{Point, Translation, Rotation, Isometry, UnitQuaternion, UnitComplex,
|
|
|
|
Point3, Rotation2, Rotation3};
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
impl<N: Real, D: DimName, R: AlgaRotation<Point<N, D>>> Isometry<N, D, R>
|
|
|
|
where DefaultAllocator: Allocator<N, D> {
|
2016-12-05 05:44:42 +08:00
|
|
|
/// Creates a new identity isometry.
|
|
|
|
#[inline]
|
|
|
|
pub fn identity() -> Self {
|
2017-08-03 01:37:44 +08:00
|
|
|
Self::from_parts(Translation::identity(), R::identity())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// The isometry that applies the rotation `r` with its axis passing through the point `p`.
|
|
|
|
/// This effectively lets `p` invariant.
|
|
|
|
#[inline]
|
|
|
|
pub fn rotation_wrt_point(r: R, p: Point<N, D>) -> Self {
|
|
|
|
let shift = r.transform_vector(&-&p.coords);
|
|
|
|
Self::from_parts(Translation::from_vector(shift + p.coords), r)
|
2016-12-05 05:44:42 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
impl<N: Real, D: DimName, R: AlgaRotation<Point<N, D>>> One for Isometry<N, D, R>
|
|
|
|
where DefaultAllocator: Allocator<N, D> {
|
2016-12-05 05:44:42 +08:00
|
|
|
/// Creates a new identity isometry.
|
|
|
|
#[inline]
|
|
|
|
fn one() -> Self {
|
|
|
|
Self::identity()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
impl<N: Real + Rand, D: DimName, R> Rand for Isometry<N, D, R>
|
|
|
|
where R: AlgaRotation<Point<N, D>> + Rand,
|
|
|
|
DefaultAllocator: Allocator<N, D> {
|
2016-12-05 05:44:42 +08:00
|
|
|
#[inline]
|
|
|
|
fn rand<G: Rng>(rng: &mut G) -> Self {
|
|
|
|
Self::from_parts(rng.gen(), rng.gen())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "arbitrary")]
|
2017-08-03 01:37:44 +08:00
|
|
|
impl<N, D: DimName, R> Arbitrary for Isometry<N, D, R>
|
2016-12-05 05:44:42 +08:00
|
|
|
where N: Real + Arbitrary + Send,
|
2017-08-03 01:37:44 +08:00
|
|
|
R: AlgaRotation<Point<N, D>> + Arbitrary + Send,
|
|
|
|
Owned<N, D>: Send,
|
|
|
|
DefaultAllocator: Allocator<N, D> {
|
2016-12-05 05:44:42 +08:00
|
|
|
#[inline]
|
|
|
|
fn arbitrary<G: Gen>(rng: &mut G) -> Self {
|
|
|
|
Self::from_parts(Arbitrary::arbitrary(rng), Arbitrary::arbitrary(rng))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
* Constructors for various static dimensions.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
// 2D rotation.
|
2017-08-03 01:37:44 +08:00
|
|
|
impl<N: Real> Isometry<N, U2, Rotation2<N>> {
|
2016-12-05 05:44:42 +08:00
|
|
|
/// Creates a new isometry from a translation and a rotation angle.
|
|
|
|
#[inline]
|
2017-08-03 01:37:44 +08:00
|
|
|
pub fn new(translation: Vector2<N>, angle: N) -> Self {
|
|
|
|
Self::from_parts(Translation::from_vector(translation), Rotation::<N, U2>::new(angle))
|
2016-12-05 05:44:42 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
impl<N: Real> Isometry<N, U2, UnitComplex<N>> {
|
2016-12-05 05:44:42 +08:00
|
|
|
/// Creates a new isometry from a translation and a rotation angle.
|
|
|
|
#[inline]
|
2017-08-03 01:37:44 +08:00
|
|
|
pub fn new(translation: Vector2<N>, angle: N) -> Self {
|
|
|
|
Self::from_parts(Translation::from_vector(translation), UnitComplex::from_angle(angle))
|
2016-12-05 05:44:42 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 3D rotation.
|
|
|
|
macro_rules! isometry_construction_impl(
|
|
|
|
($RotId: ident < $($RotParams: ident),*>, $RRDim: ty, $RCDim: ty) => {
|
2017-08-03 01:37:44 +08:00
|
|
|
impl<N: Real> Isometry<N, U3, $RotId<$($RotParams),*>> {
|
2016-12-05 05:44:42 +08:00
|
|
|
/// Creates a new isometry from a translation and a rotation axis-angle.
|
|
|
|
#[inline]
|
2017-08-03 01:37:44 +08:00
|
|
|
pub fn new(translation: Vector3<N>, axisangle: Vector3<N>) -> Self {
|
2016-12-05 05:44:42 +08:00
|
|
|
Self::from_parts(
|
2017-08-03 01:37:44 +08:00
|
|
|
Translation::from_vector(translation),
|
2016-12-05 05:44:42 +08:00
|
|
|
$RotId::<$($RotParams),*>::from_scaled_axis(axisangle))
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Creates an isometry that corresponds to the local frame of an observer standing at the
|
|
|
|
/// point `eye` and looking toward `target`.
|
|
|
|
///
|
|
|
|
/// It maps the view direction `target - eye` to the positive `z` axis and the origin to the
|
|
|
|
/// `eye`.
|
|
|
|
///
|
|
|
|
/// # Arguments
|
|
|
|
/// * eye - The observer position.
|
|
|
|
/// * target - The target position.
|
|
|
|
/// * up - Vertical direction. The only requirement of this parameter is to not be collinear
|
|
|
|
/// to `eye - at`. Non-collinearity is not checked.
|
|
|
|
#[inline]
|
2017-08-03 01:37:44 +08:00
|
|
|
pub fn new_observer_frame(eye: &Point3<N>,
|
|
|
|
target: &Point3<N>,
|
|
|
|
up: &Vector3<N>)
|
2016-12-05 05:44:42 +08:00
|
|
|
-> Self {
|
|
|
|
Self::from_parts(
|
2017-08-03 01:37:44 +08:00
|
|
|
Translation::from_vector(eye.coords.clone()),
|
2016-12-05 05:44:42 +08:00
|
|
|
$RotId::new_observer_frame(&(target - eye), up))
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Builds a right-handed look-at view matrix.
|
|
|
|
///
|
|
|
|
/// This conforms to the common notion of right handed look-at matrix from the computer
|
|
|
|
/// graphics community.
|
|
|
|
///
|
|
|
|
/// # Arguments
|
|
|
|
/// * eye - The eye position.
|
|
|
|
/// * target - The target position.
|
|
|
|
/// * up - A vector approximately aligned with required the vertical axis. The only
|
|
|
|
/// requirement of this parameter is to not be collinear to `target - eye`.
|
|
|
|
#[inline]
|
2017-08-03 01:37:44 +08:00
|
|
|
pub fn look_at_rh(eye: &Point3<N>,
|
|
|
|
target: &Point3<N>,
|
|
|
|
up: &Vector3<N>)
|
2016-12-05 05:44:42 +08:00
|
|
|
-> Self {
|
|
|
|
let rotation = $RotId::look_at_rh(&(target - eye), up);
|
|
|
|
let trans = &rotation * (-eye);
|
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
Self::from_parts(Translation::from_vector(trans.coords), rotation)
|
2016-12-05 05:44:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Builds a left-handed look-at view matrix.
|
|
|
|
///
|
|
|
|
/// This conforms to the common notion of left handed look-at matrix from the computer
|
|
|
|
/// graphics community.
|
|
|
|
///
|
|
|
|
/// # Arguments
|
|
|
|
/// * eye - The eye position.
|
|
|
|
/// * target - The target position.
|
|
|
|
/// * up - A vector approximately aligned with required the vertical axis. The only
|
|
|
|
/// requirement of this parameter is to not be collinear to `target - eye`.
|
|
|
|
#[inline]
|
2017-08-03 01:37:44 +08:00
|
|
|
pub fn look_at_lh(eye: &Point3<N>,
|
|
|
|
target: &Point3<N>,
|
|
|
|
up: &Vector3<N>)
|
2016-12-05 05:44:42 +08:00
|
|
|
-> Self {
|
|
|
|
let rotation = $RotId::look_at_lh(&(target - eye), up);
|
|
|
|
let trans = &rotation * (-eye);
|
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
Self::from_parts(Translation::from_vector(trans.coords), rotation)
|
2016-12-05 05:44:42 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
isometry_construction_impl!(Rotation3<N>, U3, U3);
|
|
|
|
isometry_construction_impl!(UnitQuaternion<N>, U4, U1);
|