Add impls of From/Into to convert any transformation types to a matrix.

This commit is contained in:
sebcrozet 2018-10-13 10:25:34 +02:00 committed by Sébastien Crozet
parent 4d7b215146
commit 18e9b8998d
13 changed files with 181 additions and 48 deletions

View File

@ -14,6 +14,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
* Add `.slerp` and `.try_slerp` to unit vectors.
* Add `.to_projective` and `.as_projective` to `Perspective3` and `Orthographic3` in order to
use them as `Projective3` structures.
* Add impl for `From/Into` to allow the conversion of any transformation type to a matrix.
## [0.16.0]
All dependencies have been updated to their latest versions.

View File

@ -5,18 +5,20 @@ use std::convert::{AsMut, AsRef, From, Into};
use std::mem;
use std::ptr;
use generic_array::ArrayLength;
use std::ops::Mul;
use typenum::Prod;
use generic_array::ArrayLength;
use base::allocator::{Allocator, SameShapeAllocator};
use base::constraint::{SameNumberOfColumns, SameNumberOfRows, ShapeConstraint};
use base::dimension::{Dim, DimName, Dynamic, U1, U10, U11, U12, U13, U14, U15, U16, U2, U3, U4, U5, U6, U7, U8, U9};
use base::dimension::{
Dim, DimName, Dynamic, U1, U10, U11, U12, U13, U14, U15, U16, U2, U3, U4, U5, U6, U7, U8, U9,
};
use base::iter::{MatrixIter, MatrixIterMut};
use base::storage::{ContiguousStorage, ContiguousStorageMut, Storage, StorageMut};
use base::{DefaultAllocator, Matrix, MatrixMN, MatrixArray, MatrixSlice, MatrixSliceMut, Scalar};
#[cfg(any(feature = "std", feature = "alloc"))]
use base::MatrixVec;
use base::{DefaultAllocator, Matrix, MatrixArray, MatrixMN, MatrixSlice, MatrixSliceMut, Scalar};
// FIXME: too bad this won't work allo slice conversions.
impl<N1, N2, R1, C1, R2, C2> SubsetOf<MatrixMN<N2, R2, C2>> for MatrixMN<N1, R1, C1>
@ -333,7 +335,6 @@ impl_from_into_mint_2D!(
(U4, U4) => ColumnMatrix4{x, y, z, w}[4];
);
impl<'a, N, R, C, RStride, CStride> From<MatrixSlice<'a, N, R, C, RStride, CStride>>
for Matrix<N, R, C, MatrixArray<N, R, C>>
where
@ -403,8 +404,7 @@ where
RStride: Dim,
CStride: Dim,
{
fn from(matrix_slice: MatrixSliceMut<'a, N, Dynamic, C, RStride, CStride>) -> Self
{
fn from(matrix_slice: MatrixSliceMut<'a, N, Dynamic, C, RStride, CStride>) -> Self {
matrix_slice.into_owned()
}
}

View File

@ -1,9 +1,9 @@
use alga::general::{Real, SubsetOf, SupersetOf};
use alga::linear::Rotation;
use base::{DefaultAllocator, MatrixN};
use base::dimension::{DimMin, DimName, DimNameAdd, DimNameSum, U1};
use base::allocator::Allocator;
use base::dimension::{DimMin, DimName, DimNameAdd, DimNameSum, U1};
use base::{DefaultAllocator, MatrixN};
use geometry::{Isometry, Point, Similarity, SuperTCategoryOf, TAffine, Transform, Translation};
@ -146,3 +146,15 @@ where
Self::from_parts(t, ::convert_unchecked(m.clone_owned()))
}
}
impl<N: Real, D: DimName, R> From<Isometry<N, D, R>> for MatrixN<N, DimNameSum<D, U1>>
where
D: DimNameAdd<U1>,
R: SubsetOf<MatrixN<N, DimNameSum<D, U1>>>,
DefaultAllocator: Allocator<N, DimNameSum<D, U1>, DimNameSum<D, U1>> + Allocator<N, D>,
{
#[inline]
fn from(iso: Isometry<N, D, R>) -> Self {
iso.to_homogeneous()
}
}

View File

@ -3,7 +3,7 @@ use quickcheck::{Arbitrary, Gen};
use rand::distributions::{Distribution, Standard};
use rand::Rng;
#[cfg(feature = "serde-serialize")]
use serde::{Serialize, Deserialize, Serializer, Deserializer};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::fmt;
use std::mem;
@ -14,7 +14,7 @@ use base::helper;
use base::storage::Storage;
use base::{Matrix4, Vector, Vector3};
use geometry::{Projective3, Point3};
use geometry::{Point3, Projective3};
/// A 3D orthographic projection stored as an homogeneous 4x4 matrix.
pub struct Orthographic3<N: Real> {
@ -150,7 +150,7 @@ impl<N: Real> Orthographic3<N> {
/// Computes the corresponding homogeneous matrix.
#[inline]
pub fn to_homogeneous(&self) -> Matrix4<N> {
self.matrix.clone_owned()
self.matrix
}
/// A reference to the underlying homogeneous transformation matrix.
@ -356,3 +356,10 @@ where
Self::new(left, right, bottom, top, znear, zfar)
}
}
impl<N: Real> From<Orthographic3<N>> for Matrix4<N> {
#[inline]
fn from(orth: Orthographic3<N>) -> Self {
orth.unwrap()
}
}

View File

@ -4,7 +4,7 @@ use rand::distributions::{Distribution, Standard};
use rand::Rng;
#[cfg(feature = "serde-serialize")]
use serde::{Serialize, Deserialize, Serializer, Deserializer};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::fmt;
use std::mem;
@ -15,7 +15,7 @@ use base::helper;
use base::storage::Storage;
use base::{Matrix4, Scalar, Vector, Vector3};
use geometry::{Projective3, Point3};
use geometry::{Point3, Projective3};
/// A 3D perspective projection stored as an homogeneous 4x4 matrix.
pub struct Perspective3<N: Scalar> {
@ -282,3 +282,10 @@ impl<N: Real + Arbitrary> Arbitrary for Perspective3<N> {
Self::new(aspect, Arbitrary::arbitrary(g), znear, zfar)
}
}
impl<N: Real> From<Perspective3<N>> for Matrix4<N> {
#[inline]
fn from(orth: Perspective3<N>) -> Self {
orth.unwrap()
}
}

View File

@ -1,19 +1,19 @@
use num::{One, Zero};
use alga::general::{ClosedDiv, SubsetOf, SupersetOf};
use num::{One, Zero};
use base::{DefaultAllocator, Matrix, Scalar, VectorN};
use base::dimension::{DimName, DimNameAdd, DimNameSum, U1};
use base::allocator::Allocator;
use base::dimension::{DimName, DimNameAdd, DimNameSum, U1};
use base::{DefaultAllocator, Matrix, Scalar, VectorN};
#[cfg(feature = "mint")]
use base::dimension::{U2, U3};
#[cfg(feature = "mint")]
use base::storage::{Storage, StorageMut};
use geometry::Point;
#[cfg(feature = "mint")]
use mint;
#[cfg(feature = "mint")]
use base::dimension::{U2, U3};
#[cfg(feature = "mint")]
use std::convert::{AsMut, AsRef, From, Into};
#[cfg(feature = "mint")]
use base::storage::{Storage, StorageMut};
/*
* This file provides the following conversions:
* =============================================
@ -77,8 +77,6 @@ where
}
}
#[cfg(feature = "mint")]
macro_rules! impl_from_into_mint_1D(
($($NRows: ident => $PT:ident, $VT:ident [$SZ: expr]);* $(;)*) => {$(
@ -129,3 +127,14 @@ impl_from_into_mint_1D!(
U2 => Point2, Vector2[2];
U3 => Point3, Vector3[3];
);
impl<N: Scalar + Zero + One, D: DimName> From<Point<N, D>> for VectorN<N, DimNameSum<D, U1>>
where
D: DimNameAdd<U1>,
DefaultAllocator: Allocator<N, D> + Allocator<N, DimNameSum<D, U1>>,
{
#[inline]
fn from(t: Point<N, D>) -> Self {
t.to_homogeneous()
}
}

View File

@ -6,10 +6,12 @@ use alga::linear::Rotation as AlgaRotation;
#[cfg(feature = "mint")]
use mint;
use base::{Matrix4, Vector4};
use base::dimension::U3;
use geometry::{Isometry, Point3, Quaternion, Rotation, Rotation3, Similarity, SuperTCategoryOf,
TAffine, Transform, Translation, UnitQuaternion};
use base::{Matrix3, Matrix4, Vector4};
use geometry::{
Isometry, Point3, Quaternion, Rotation, Rotation3, Similarity, SuperTCategoryOf, TAffine,
Transform, Translation, UnitQuaternion,
};
/*
* This file provides the following conversions:
@ -213,3 +215,17 @@ impl<N: Real> Into<mint::Quaternion<N>> for UnitQuaternion<N> {
}
}
}
impl<N: Real> From<UnitQuaternion<N>> for Matrix4<N> {
#[inline]
fn from(q: UnitQuaternion<N>) -> Matrix4<N> {
q.to_homogeneous()
}
}
impl<N: Real> From<UnitQuaternion<N>> for Matrix3<N> {
#[inline]
fn from(q: UnitQuaternion<N>) -> Matrix3<N> {
q.to_rotation_matrix().unwrap()
}
}

View File

@ -6,12 +6,14 @@ use alga::linear::Rotation as AlgaRotation;
#[cfg(feature = "mint")]
use mint;
use base::{DefaultAllocator, MatrixN};
use base::dimension::{DimMin, DimName, DimNameAdd, DimNameSum, U1};
use base::allocator::Allocator;
use base::dimension::{DimMin, DimName, DimNameAdd, DimNameSum, U1};
use base::{DefaultAllocator, Matrix2, Matrix3, Matrix4, MatrixN};
use geometry::{Isometry, Point, Rotation, Rotation2, Rotation3, Similarity, SuperTCategoryOf,
TAffine, Transform, Translation, UnitComplex, UnitQuaternion};
use geometry::{
Isometry, Point, Rotation, Rotation2, Rotation3, Similarity, SuperTCategoryOf, TAffine,
Transform, Translation, UnitComplex, UnitQuaternion,
};
/*
* This file provides the following conversions:
@ -214,3 +216,31 @@ impl<N: Real> From<mint::EulerAngles<N, mint::IntraXYZ>> for Rotation3<N> {
Self::from_euler_angles(euler.a, euler.b, euler.c)
}
}
impl<N: Real> From<Rotation2<N>> for Matrix3<N> {
#[inline]
fn from(q: Rotation2<N>) -> Matrix3<N> {
q.to_homogeneous()
}
}
impl<N: Real> From<Rotation2<N>> for Matrix2<N> {
#[inline]
fn from(q: Rotation2<N>) -> Matrix2<N> {
q.unwrap()
}
}
impl<N: Real> From<Rotation3<N>> for Matrix4<N> {
#[inline]
fn from(q: Rotation3<N>) -> Matrix4<N> {
q.to_homogeneous()
}
}
impl<N: Real> From<Rotation3<N>> for Matrix3<N> {
#[inline]
fn from(q: Rotation3<N>) -> Matrix3<N> {
q.unwrap()
}
}

View File

@ -1,9 +1,9 @@
use alga::general::{Real, SubsetOf, SupersetOf};
use alga::linear::Rotation;
use base::{DefaultAllocator, MatrixN};
use base::dimension::{DimMin, DimName, DimNameAdd, DimNameSum, U1};
use base::allocator::Allocator;
use base::dimension::{DimMin, DimName, DimNameAdd, DimNameSum, U1};
use base::{DefaultAllocator, MatrixN};
use geometry::{Isometry, Point, Similarity, SuperTCategoryOf, TAffine, Transform, Translation};
@ -103,13 +103,16 @@ where
#[inline]
fn is_in_subset(m: &MatrixN<N2, DimNameSum<D, U1>>) -> bool {
let mut rot = m.fixed_slice::<D, D>(0, 0).clone_owned();
if rot.fixed_columns_mut::<U1>(0)
if rot
.fixed_columns_mut::<U1>(0)
.try_normalize_mut(N2::zero())
.is_some()
&& rot.fixed_columns_mut::<U1>(1)
&& rot
.fixed_columns_mut::<U1>(1)
.try_normalize_mut(N2::zero())
.is_some()
&& rot.fixed_columns_mut::<U1>(2)
&& rot
.fixed_columns_mut::<U1>(2)
.try_normalize_mut(N2::zero())
.is_some()
{
@ -157,3 +160,15 @@ where
Self::from_parts(t, ::convert_unchecked(mm), ::convert_unchecked(scale))
}
}
impl<N: Real, D: DimName, R> From<Similarity<N, D, R>> for MatrixN<N, DimNameSum<D, U1>>
where
D: DimNameAdd<U1>,
R: SubsetOf<MatrixN<N, DimNameSum<D, U1>>>,
DefaultAllocator: Allocator<N, D> + Allocator<N, DimNameSum<D, U1>, DimNameSum<D, U1>>,
{
#[inline]
fn from(sim: Similarity<N, D, R>) -> Self {
sim.to_homogeneous()
}
}

View File

@ -1,8 +1,8 @@
use alga::general::{Real, SubsetOf};
use base::{DefaultAllocator, MatrixN};
use base::dimension::{DimName, DimNameAdd, DimNameSum, U1};
use base::allocator::Allocator;
use base::dimension::{DimName, DimNameAdd, DimNameSum, U1};
use base::{DefaultAllocator, MatrixN};
use geometry::{SuperTCategoryOf, TCategory, Transform};
@ -60,3 +60,15 @@ where
Transform::from_matrix_unchecked(::convert_ref_unchecked(m))
}
}
impl<N: Real, D: DimName, C> From<Transform<N, D, C>> for MatrixN<N, DimNameSum<D, U1>>
where
D: DimNameAdd<U1>,
C: TCategory,
DefaultAllocator: Allocator<N, DimNameSum<D, U1>, DimNameSum<D, U1>>,
{
#[inline]
fn from(t: Transform<N, D, C>) -> Self {
t.to_homogeneous()
}
}

View File

@ -1,9 +1,11 @@
use num::{One, Zero};
use alga::general::{Real, SubsetOf, SupersetOf};
use alga::linear::Rotation;
use base::{DefaultAllocator, MatrixN, Scalar, VectorN};
use base::dimension::{DimName, DimNameAdd, DimNameSum, U1};
use base::allocator::Allocator;
use base::dimension::{DimName, DimNameAdd, DimNameSum, U1};
use base::{DefaultAllocator, MatrixN, Scalar, VectorN};
use geometry::{Isometry, Point, Similarity, SuperTCategoryOf, TAffine, Transform, Translation};
@ -146,3 +148,14 @@ where
Self::from_vector(::convert_unchecked(t.into_owned()))
}
}
impl<N: Scalar + Zero + One, D: DimName> From<Translation<N, D>> for MatrixN<N, DimNameSum<D, U1>>
where
D: DimNameAdd<U1>,
DefaultAllocator: Allocator<N, D> + Allocator<N, DimNameSum<D, U1>, DimNameSum<D, U1>>,
{
#[inline]
fn from(t: Translation<N, D>) -> Self {
t.to_homogeneous()
}
}

View File

@ -173,3 +173,17 @@ impl<N: Real> UlpsEq for UnitComplex<N> {
&& self.im.ulps_eq(&other.im, epsilon, max_ulps)
}
}
impl<N: Real> From<UnitComplex<N>> for Matrix3<N> {
#[inline]
fn from(q: UnitComplex<N>) -> Matrix3<N> {
q.to_homogeneous()
}
}
impl<N: Real> From<UnitComplex<N>> for Matrix2<N> {
#[inline]
fn from(q: UnitComplex<N>) -> Matrix2<N> {
q.to_rotation_matrix().unwrap()
}
}

View File

@ -242,12 +242,8 @@ fn from_rows_with_different_dimensions() {
#[test]
fn copy_from_slice() {
let mut a = Matrix3::zeros();
let data = [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0 ];
let expected_a = Matrix3::new(
1.0, 4.0, 7.0,
2.0, 5.0, 8.0,
3.0, 6.0, 9.0
);
let data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
let expected_a = Matrix3::new(1.0, 4.0, 7.0, 2.0, 5.0, 8.0, 3.0, 6.0, 9.0);
a.copy_from_slice(&data);
@ -258,7 +254,7 @@ fn copy_from_slice() {
#[test]
fn copy_from_slice_too_small() {
let mut a = Matrix3::zeros();
let data = [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ];
let data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0];
a.copy_from_slice(&data);
}
@ -266,7 +262,7 @@ fn copy_from_slice_too_small() {
#[test]
fn copy_from_slice_too_large() {
let mut a = Matrix3::zeros();
let data = [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0 ];
let data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0];
a.copy_from_slice(&data);
}
@ -727,6 +723,7 @@ fn partial_clamp() {
assert_eq!(*inter.unwrap(), n);
}
#[test]
fn swizzle() {
let a = Vector2::new(1.0f32, 2.0);
let b = Vector3::new(1.0f32, 2.0, 3.0);
@ -761,7 +758,6 @@ fn swizzle() {
assert_eq!(b.zxz(), Vector3::new(3.0, 1.0, 3.0));
assert_eq!(b.zyz(), Vector3::new(3.0, 2.0, 3.0));
assert_eq!(c.xy(), Vector2::new(1.0, 2.0));
assert_eq!(c.yx(), Vector2::new(2.0, 1.0));
assert_eq!(c.xx(), Vector2::new(1.0, 1.0));