From 729a8fd7f2af92c0a6bd603ac8bafad82d4dd26e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crozet=20S=C3=A9bastien?= Date: Sat, 6 Mar 2021 12:20:38 +0100 Subject: [PATCH 1/4] Add conversion from/to glam types + move glam/alga/mint impls to a "third_party" module. --- Cargo.toml | 27 ++- src/base/conversion.rs | 115 ---------- src/base/mod.rs | 2 - src/geometry/mod.rs | 14 -- src/geometry/point_conversion.rs | 62 +----- src/geometry/quaternion_conversion.rs | 41 ---- src/geometry/rotation_conversion.rs | 11 - src/lib.rs | 1 + .../alga/alga_dual_quaternion.rs} | 0 .../alga/alga_isometry.rs} | 0 .../alga/alga_matrix.rs} | 0 .../alga/alga_point.rs} | 0 .../alga/alga_quaternion.rs} | 0 .../alga/alga_rotation.rs} | 0 .../alga/alga_similarity.rs} | 0 .../alga/alga_transform.rs} | 0 .../alga/alga_translation.rs} | 0 .../alga/alga_unit_complex.rs} | 0 src/third_party/alga/mod.rs | 10 + src/third_party/glam/glam_isometry.rs | 54 +++++ src/third_party/glam/glam_matrix.rs | 210 ++++++++++++++++++ src/third_party/glam/glam_point.rs | 71 ++++++ src/third_party/glam/glam_quaternion.rs | 64 ++++++ src/third_party/glam/mod.rs | 4 + src/third_party/mint/mint_matrix.rs | 117 ++++++++++ src/third_party/mint/mint_point.rs | 52 +++++ src/third_party/mint/mint_quaternion.rs | 33 +++ src/third_party/mint/mint_rotation.rs | 7 + src/third_party/mint/mod.rs | 4 + src/third_party/mod.rs | 6 + 30 files changed, 653 insertions(+), 252 deletions(-) rename src/{geometry/dual_quaternion_alga.rs => third_party/alga/alga_dual_quaternion.rs} (100%) rename src/{geometry/isometry_alga.rs => third_party/alga/alga_isometry.rs} (100%) rename src/{base/matrix_alga.rs => third_party/alga/alga_matrix.rs} (100%) rename src/{geometry/point_alga.rs => third_party/alga/alga_point.rs} (100%) rename src/{geometry/quaternion_alga.rs => third_party/alga/alga_quaternion.rs} (100%) rename src/{geometry/rotation_alga.rs => third_party/alga/alga_rotation.rs} (100%) rename src/{geometry/similarity_alga.rs => third_party/alga/alga_similarity.rs} (100%) rename src/{geometry/transform_alga.rs => third_party/alga/alga_transform.rs} (100%) rename src/{geometry/translation_alga.rs => third_party/alga/alga_translation.rs} (100%) rename src/{geometry/unit_complex_alga.rs => third_party/alga/alga_unit_complex.rs} (100%) create mode 100644 src/third_party/alga/mod.rs create mode 100644 src/third_party/glam/glam_isometry.rs create mode 100644 src/third_party/glam/glam_matrix.rs create mode 100644 src/third_party/glam/glam_point.rs create mode 100644 src/third_party/glam/glam_quaternion.rs create mode 100644 src/third_party/glam/mod.rs create mode 100644 src/third_party/mint/mint_matrix.rs create mode 100644 src/third_party/mint/mint_point.rs create mode 100644 src/third_party/mint/mint_quaternion.rs create mode 100644 src/third_party/mint/mint_rotation.rs create mode 100644 src/third_party/mint/mod.rs create mode 100644 src/third_party/mod.rs diff --git a/Cargo.toml b/Cargo.toml index ea9a2894..34963447 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,11 +24,6 @@ path = "src/lib.rs" [features] default = [ "std" ] std = [ "matrixmultiply", "simba/std" ] -rand-no-std = [ "rand-package" ] -rand = [ "rand-no-std", "rand-package/std", "rand-package/std_rng", "rand_distr" ] -arbitrary = [ "quickcheck" ] -serde-serialize = [ "serde", "num-complex/serde" ] -abomonation-serialize = [ "abomonation" ] sparse = [ ] debug = [ "approx/num-complex", "rand" ] alloc = [ ] @@ -36,11 +31,26 @@ io = [ "pest", "pest_derive" ] compare = [ "matrixcompare-core" ] libm = [ "simba/libm" ] libm-force = [ "simba/libm_force" ] -proptest-support = [ "proptest" ] no_unsound_assume_init = [ ] -# This feature is only used for tests, and enables tests that require more time to run -slow-tests = [] +# Conversion +convert-mint = [ "mint" ] +convert-glam = [ "glam" ] +convert-glam-unchecked = [ "convert-glam" ] # Unable edgy conversions like Mat4 -> Isometry3 +convert-bytemuck = [ "bytemuck" ] + +# Serialization +serde-serialize = [ "serde", "num-complex/serde" ] +abomonation-serialize = [ "abomonation" ] + +# Randomness +rand-no-std = [ "rand-package" ] +rand = [ "rand-no-std", "rand-package/std", "rand-package/std_rng", "rand_distr" ] + +# Tests +arbitrary = [ "quickcheck" ] +proptest-support = [ "proptest" ] +slow-tests = [] [dependencies] typenum = "1.12" @@ -57,6 +67,7 @@ matrixmultiply = { version = "0.3", optional = true } serde = { version = "1.0", default-features = false, features = [ "derive" ], optional = true } abomonation = { version = "0.7", optional = true } mint = { version = "0.5", optional = true } +glam = { version = "0.13", optional = true } quickcheck = { version = "1", optional = true } pest = { version = "2", optional = true } pest_derive = { version = "2", optional = true } diff --git a/src/base/conversion.rs b/src/base/conversion.rs index 8ef1a967..92d3be15 100644 --- a/src/base/conversion.rs +++ b/src/base/conversion.rs @@ -1,7 +1,5 @@ #[cfg(all(feature = "alloc", not(feature = "std")))] use alloc::vec::Vec; -#[cfg(feature = "mint")] -use mint; use simba::scalar::{SubsetOf, SupersetOf}; use std::convert::{AsMut, AsRef, From, Into}; use std::mem; @@ -235,119 +233,6 @@ impl_from_into_asref_2D!( (U6, U2) => (6, 2); (U6, U3) => (6, 3); (U6, U4) => (6, 4); (U6, U5) => (6, 5); (U6, U6) => (6, 6); ); -#[cfg(feature = "mint")] -macro_rules! impl_from_into_mint_1D( - ($($NRows: ident => $VT:ident [$SZ: expr]);* $(;)*) => {$( - impl From> for MatrixMN - where N: Scalar, - DefaultAllocator: Allocator { - #[inline] - fn from(v: mint::$VT) -> Self { - unsafe { - let mut res = Self::new_uninitialized(); - ptr::copy_nonoverlapping(&v.x, (*res.as_mut_ptr()).data.ptr_mut(), $SZ); - - res.assume_init() - } - } - } - - impl Into> for Matrix - where N: Scalar, - S: ContiguousStorage { - #[inline] - fn into(self) -> mint::$VT { - unsafe { - let mut res: mint::$VT = mem::MaybeUninit::uninit().assume_init(); - ptr::copy_nonoverlapping(self.data.ptr(), &mut res.x, $SZ); - res - } - } - } - - impl AsRef> for Matrix - where N: Scalar, - S: ContiguousStorage { - #[inline] - fn as_ref(&self) -> &mint::$VT { - unsafe { - mem::transmute(self.data.ptr()) - } - } - } - - impl AsMut> for Matrix - where N: Scalar, - S: ContiguousStorageMut { - #[inline] - fn as_mut(&mut self) -> &mut mint::$VT { - unsafe { - mem::transmute(self.data.ptr_mut()) - } - } - } - )*} -); - -// Implement for vectors of dimension 2 .. 4. -#[cfg(feature = "mint")] -impl_from_into_mint_1D!( - U2 => Vector2[2]; - U3 => Vector3[3]; - U4 => Vector4[4]; -); - -#[cfg(feature = "mint")] -macro_rules! impl_from_into_mint_2D( - ($(($NRows: ty, $NCols: ty) => $MV:ident{ $($component:ident),* }[$SZRows: expr]);* $(;)*) => {$( - impl From> for MatrixMN - where N: Scalar, - DefaultAllocator: Allocator { - #[inline] - fn from(m: mint::$MV) -> Self { - unsafe { - let mut res = Self::new_uninitialized(); - let mut ptr = (*res.as_mut_ptr()).data.ptr_mut(); - $( - ptr::copy_nonoverlapping(&m.$component.x, ptr, $SZRows); - ptr = ptr.offset($SZRows); - )* - let _ = ptr; - res.assume_init() - } - } - } - - impl Into> for MatrixMN - where N: Scalar, - DefaultAllocator: Allocator { - #[inline] - fn into(self) -> mint::$MV { - unsafe { - let mut res: mint::$MV = mem::MaybeUninit::uninit().assume_init(); - let mut ptr = self.data.ptr(); - $( - ptr::copy_nonoverlapping(ptr, &mut res.$component.x, $SZRows); - ptr = ptr.offset($SZRows); - )* - let _ = ptr; - res - } - } - } - )*} -); - -// Implement for matrices with shape 2x2 .. 4x4. -#[cfg(feature = "mint")] -impl_from_into_mint_2D!( - (U2, U2) => ColumnMatrix2{x, y}[2]; - (U2, U3) => ColumnMatrix2x3{x, y, z}[2]; - (U3, U3) => ColumnMatrix3{x, y, z}[3]; - (U3, U4) => ColumnMatrix3x4{x, y, z, w}[3]; - (U4, U4) => ColumnMatrix4{x, y, z, w}[4]; -); - impl<'a, N, R, C, RStride, CStride> From> for Matrix> where diff --git a/src/base/mod.rs b/src/base/mod.rs index 9f08572f..fdfbb5c7 100644 --- a/src/base/mod.rs +++ b/src/base/mod.rs @@ -22,8 +22,6 @@ mod conversion; mod edition; pub mod indexing; mod matrix; -#[cfg(feature = "alga")] -mod matrix_alga; mod matrix_simba; mod matrix_slice; mod norm; diff --git a/src/geometry/mod.rs b/src/geometry/mod.rs index 5fa8c094..ef5e3eff 100644 --- a/src/geometry/mod.rs +++ b/src/geometry/mod.rs @@ -6,8 +6,6 @@ mod op_macros; mod abstract_rotation; mod point; -#[cfg(feature = "alga")] -mod point_alga; mod point_alias; mod point_construction; mod point_conversion; @@ -16,8 +14,6 @@ mod point_ops; mod point_simba; mod rotation; -#[cfg(feature = "alga")] -mod rotation_alga; mod rotation_alias; mod rotation_construction; mod rotation_conversion; @@ -43,16 +39,12 @@ mod dual_quaternion_conversion; mod dual_quaternion_ops; mod unit_complex; -#[cfg(feature = "alga")] -mod unit_complex_alga; mod unit_complex_construction; mod unit_complex_conversion; mod unit_complex_ops; mod unit_complex_simba; mod translation; -#[cfg(feature = "alga")] -mod translation_alga; mod translation_alias; mod translation_construction; mod translation_conversion; @@ -61,8 +53,6 @@ mod translation_ops; mod translation_simba; mod isometry; -#[cfg(feature = "alga")] -mod isometry_alga; mod isometry_alias; mod isometry_construction; mod isometry_conversion; @@ -71,8 +61,6 @@ mod isometry_ops; mod isometry_simba; mod similarity; -#[cfg(feature = "alga")] -mod similarity_alga; mod similarity_alias; mod similarity_construction; mod similarity_conversion; @@ -82,8 +70,6 @@ mod similarity_simba; mod swizzle; mod transform; -#[cfg(feature = "alga")] -mod transform_alga; mod transform_alias; mod transform_construction; mod transform_conversion; diff --git a/src/geometry/point_conversion.rs b/src/geometry/point_conversion.rs index 2723e626..6f3d865b 100644 --- a/src/geometry/point_conversion.rs +++ b/src/geometry/point_conversion.rs @@ -6,23 +6,14 @@ use crate::base::allocator::Allocator; use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; use crate::base::{DefaultAllocator, Matrix, Scalar, VectorN}; -#[cfg(feature = "mint")] -use crate::base::dimension::{U2, U3}; -#[cfg(feature = "mint")] -use crate::base::storage::{Storage, StorageMut}; use crate::geometry::Point; -#[cfg(feature = "mint")] -use mint; -#[cfg(feature = "mint")] -use std::convert::{AsMut, AsRef, From, Into}; + /* * This file provides the following conversions: * ============================================= * * Point -> Point * Point -> Vector (homogeneous) - * - * mint::Point <-> Point */ impl SubsetOf> for Point @@ -80,57 +71,6 @@ where } } -#[cfg(feature = "mint")] -macro_rules! impl_from_into_mint_1D( - ($($NRows: ident => $PT:ident, $VT:ident [$SZ: expr]);* $(;)*) => {$( - impl From> for Point - where N: Scalar { - #[inline] - fn from(p: mint::$PT) -> Self { - Self { - coords: VectorN::from(mint::$VT::from(p)), - } - } - } - - impl Into> for Point - where N: Scalar { - #[inline] - fn into(self) -> mint::$PT { - let mint_vec: mint::$VT = self.coords.into(); - mint::$PT::from(mint_vec) - } - } - - impl AsRef> for Point - where N: Scalar { - #[inline] - fn as_ref(&self) -> &mint::$PT { - unsafe { - &*(self.coords.data.ptr() as *const mint::$PT) - } - } - } - - impl AsMut> for Point - where N: Scalar { - #[inline] - fn as_mut(&mut self) -> &mut mint::$PT { - unsafe { - &mut *(self.coords.data.ptr_mut() as *mut mint::$PT) - } - } - } - )*} -); - -// Implement for points of dimension 2, 3. -#[cfg(feature = "mint")] -impl_from_into_mint_1D!( - U2 => Point2, Vector2[2]; - U3 => Point3, Vector3[3]; -); - impl From> for VectorN> where D: DimNameAdd, diff --git a/src/geometry/quaternion_conversion.rs b/src/geometry/quaternion_conversion.rs index c597603b..c8b5c6ed 100644 --- a/src/geometry/quaternion_conversion.rs +++ b/src/geometry/quaternion_conversion.rs @@ -3,9 +3,6 @@ use num::Zero; use simba::scalar::{RealField, SubsetOf, SupersetOf}; use simba::simd::{PrimitiveSimdValue, SimdRealField, SimdValue}; -#[cfg(feature = "mint")] -use mint; - use crate::base::dimension::U3; use crate::base::{Matrix3, Matrix4, Scalar, Vector4}; use crate::geometry::{ @@ -26,9 +23,6 @@ use crate::geometry::{ * UnitQuaternion -> Transform * UnitQuaternion -> Matrix (homogeneous) * - * mint::Quaternion <-> Quaternion - * UnitQuaternion -> mint::Quaternion - * * NOTE: * UnitQuaternion -> Quaternion is already provided by: Unit -> T */ @@ -206,41 +200,6 @@ impl> SubsetOf> for Un } } -#[cfg(feature = "mint")] -impl From> for Quaternion { - fn from(q: mint::Quaternion) -> Self { - Self::new(q.s, q.v.x, q.v.y, q.v.z) - } -} - -#[cfg(feature = "mint")] -impl Into> for Quaternion { - fn into(self) -> mint::Quaternion { - mint::Quaternion { - v: mint::Vector3 { - x: self[0].inlined_clone(), - y: self[1].inlined_clone(), - z: self[2].inlined_clone(), - }, - s: self[3].inlined_clone(), - } - } -} - -#[cfg(feature = "mint")] -impl Into> for UnitQuaternion { - fn into(self) -> mint::Quaternion { - mint::Quaternion { - v: mint::Vector3 { - x: self[0].inlined_clone(), - y: self[1].inlined_clone(), - z: self[2].inlined_clone(), - }, - s: self[3].inlined_clone(), - } - } -} - impl From> for Matrix4 where N::Element: SimdRealField, diff --git a/src/geometry/rotation_conversion.rs b/src/geometry/rotation_conversion.rs index accf9a41..21f5a936 100644 --- a/src/geometry/rotation_conversion.rs +++ b/src/geometry/rotation_conversion.rs @@ -3,9 +3,6 @@ use num::Zero; use simba::scalar::{RealField, SubsetOf, SupersetOf}; use simba::simd::{PrimitiveSimdValue, SimdValue}; -#[cfg(feature = "mint")] -use mint; - use crate::base::allocator::Allocator; use crate::base::dimension::{DimMin, DimName, DimNameAdd, DimNameSum, U1}; use crate::base::{DefaultAllocator, Matrix2, Matrix3, Matrix4, MatrixN, Scalar}; @@ -27,7 +24,6 @@ use crate::geometry::{ * Rotation -> Similarity * Rotation -> Transform * Rotation -> Matrix (homogeneous) - * mint::EulerAngles -> Rotation */ @@ -236,13 +232,6 @@ where } } -#[cfg(feature = "mint")] -impl From> for Rotation3 { - fn from(euler: mint::EulerAngles) -> Self { - Self::from_euler_angles(euler.a, euler.b, euler.c) - } -} - impl From> for Matrix3 { #[inline] fn from(q: Rotation2) -> Self { diff --git a/src/lib.rs b/src/lib.rs index 14314116..d8f48189 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -123,6 +123,7 @@ pub mod linalg; pub mod proptest; #[cfg(feature = "sparse")] pub mod sparse; +mod third_party; pub use crate::base::*; pub use crate::geometry::*; diff --git a/src/geometry/dual_quaternion_alga.rs b/src/third_party/alga/alga_dual_quaternion.rs similarity index 100% rename from src/geometry/dual_quaternion_alga.rs rename to src/third_party/alga/alga_dual_quaternion.rs diff --git a/src/geometry/isometry_alga.rs b/src/third_party/alga/alga_isometry.rs similarity index 100% rename from src/geometry/isometry_alga.rs rename to src/third_party/alga/alga_isometry.rs diff --git a/src/base/matrix_alga.rs b/src/third_party/alga/alga_matrix.rs similarity index 100% rename from src/base/matrix_alga.rs rename to src/third_party/alga/alga_matrix.rs diff --git a/src/geometry/point_alga.rs b/src/third_party/alga/alga_point.rs similarity index 100% rename from src/geometry/point_alga.rs rename to src/third_party/alga/alga_point.rs diff --git a/src/geometry/quaternion_alga.rs b/src/third_party/alga/alga_quaternion.rs similarity index 100% rename from src/geometry/quaternion_alga.rs rename to src/third_party/alga/alga_quaternion.rs diff --git a/src/geometry/rotation_alga.rs b/src/third_party/alga/alga_rotation.rs similarity index 100% rename from src/geometry/rotation_alga.rs rename to src/third_party/alga/alga_rotation.rs diff --git a/src/geometry/similarity_alga.rs b/src/third_party/alga/alga_similarity.rs similarity index 100% rename from src/geometry/similarity_alga.rs rename to src/third_party/alga/alga_similarity.rs diff --git a/src/geometry/transform_alga.rs b/src/third_party/alga/alga_transform.rs similarity index 100% rename from src/geometry/transform_alga.rs rename to src/third_party/alga/alga_transform.rs diff --git a/src/geometry/translation_alga.rs b/src/third_party/alga/alga_translation.rs similarity index 100% rename from src/geometry/translation_alga.rs rename to src/third_party/alga/alga_translation.rs diff --git a/src/geometry/unit_complex_alga.rs b/src/third_party/alga/alga_unit_complex.rs similarity index 100% rename from src/geometry/unit_complex_alga.rs rename to src/third_party/alga/alga_unit_complex.rs diff --git a/src/third_party/alga/mod.rs b/src/third_party/alga/mod.rs new file mode 100644 index 00000000..f8cc3b00 --- /dev/null +++ b/src/third_party/alga/mod.rs @@ -0,0 +1,10 @@ +mod alga_dual_quaternion; +mod alga_isometry; +mod alga_matrix; +mod alga_point; +mod alga_quaternion; +mod alga_rotation; +mod alga_similarity; +mod alga_transform; +mod alga_translation; +mod alga_unit_complex; diff --git a/src/third_party/glam/glam_isometry.rs b/src/third_party/glam/glam_isometry.rs new file mode 100644 index 00000000..52c36e37 --- /dev/null +++ b/src/third_party/glam/glam_isometry.rs @@ -0,0 +1,54 @@ +use crate::{Isometry2, Isometry3}; +use glam::{DMat3, DMat4, Mat3, Mat4}; + +impl From> for Mat3 { + fn from(iso: Isometry2) -> Mat3 { + iso.to_homogeneous().into() + } +} +impl From> for Mat4 { + fn from(iso: Isometry3) -> Mat4 { + iso.to_homogeneous().into() + } +} + +impl From> for DMat3 { + fn from(iso: Isometry2) -> DMat3 { + iso.to_homogeneous().into() + } +} +impl From> for DMat4 { + fn from(iso: Isometry3) -> DMat4 { + iso.to_homogeneous().into() + } +} + +#[cfg(feature = "convert-glam-unchecked")] +mod unchecked { + use crate::{Isometry2, Isometry3, Matrix3, Matrix4}; + use glam::{DMat3, DMat4, Mat3, Mat4}; + + impl From for Isometry2 { + fn from(mat3: Mat3) -> Isometry2 { + crate::convert_unchecked(Matrix3::from(mat3)) + } + } + + impl From for Isometry3 { + fn from(mat4: Mat4) -> Isometry3 { + crate::convert_unchecked(Matrix4::from(mat4)) + } + } + + impl From for Isometry2 { + fn from(mat3: DMat3) -> Isometry2 { + crate::convert_unchecked(Matrix3::from(mat3)) + } + } + + impl From for Isometry3 { + fn from(mat4: DMat4) -> Isometry3 { + crate::convert_unchecked(Matrix4::from(mat4)) + } + } +} diff --git a/src/third_party/glam/glam_matrix.rs b/src/third_party/glam/glam_matrix.rs new file mode 100644 index 00000000..bbb2bd17 --- /dev/null +++ b/src/third_party/glam/glam_matrix.rs @@ -0,0 +1,210 @@ +use crate::storage::Storage; +use crate::{Matrix, Matrix2, Matrix3, Matrix4, Vector, Vector2, Vector3, Vector4, U2, U3, U4}; +use glam::{ + BVec2, BVec3, BVec4, DMat2, DMat3, DMat4, DVec2, DVec3, DVec4, IVec2, IVec3, IVec4, Mat2, Mat3, + Mat4, UVec2, UVec3, UVec4, Vec2, Vec3, Vec3A, Vec4, +}; + +macro_rules! impl_vec_conversion( + ($N: ty, $Vec2: ty, $Vec3: ty, $Vec4: ty) => { + impl From<$Vec2> for Vector2<$N> { + #[inline] + fn from(e: $Vec2) -> Vector2<$N> { + (*e.as_ref()).into() + } + } + + impl From> for $Vec2 + where + S: Storage<$N, U2>, + { + #[inline] + fn from(e: Vector<$N, U2, S>) -> $Vec2 { + <$Vec2>::new(e[0], e[1]) + } + } + + impl From<$Vec3> for Vector3<$N> { + #[inline] + fn from(e: $Vec3) -> Vector3<$N> { + (*e.as_ref()).into() + } + } + + impl From> for $Vec3 + where + S: Storage<$N, U3>, + { + #[inline] + fn from(e: Vector<$N, U3, S>) -> $Vec3 { + <$Vec3>::new(e[0], e[1], e[2]) + } + } + + impl From<$Vec4> for Vector4<$N> { + #[inline] + fn from(e: $Vec4) -> Vector4<$N> { + (*e.as_ref()).into() + } + } + + impl From> for $Vec4 + where + S: Storage<$N, U4>, + { + #[inline] + fn from(e: Vector<$N, U4, S>) -> $Vec4 { + <$Vec4>::new(e[0], e[1], e[2], e[3]) + } + } + } +); + +impl_vec_conversion!(f32, Vec2, Vec3, Vec4); +impl_vec_conversion!(f64, DVec2, DVec3, DVec4); +impl_vec_conversion!(i32, IVec2, IVec3, IVec4); +impl_vec_conversion!(u32, UVec2, UVec3, UVec4); +impl_vec_conversion!(bool, BVec2, BVec3, BVec4); + +impl From for Vector3 { + #[inline] + fn from(e: Vec3A) -> Vector3 { + (*e.as_ref()).into() + } +} + +impl From> for Vec3A +where + S: Storage, +{ + #[inline] + fn from(e: Vector) -> Vec3A { + Vec3A::new(e[0], e[1], e[2]) + } +} + +impl From for Matrix2 { + #[inline] + fn from(e: Mat2) -> Matrix2 { + e.to_cols_array_2d().into() + } +} + +impl From> for Mat2 +where + S: Storage, +{ + #[inline] + fn from(e: Matrix) -> Mat2 { + Mat2::from_cols( + Vec2::new(e[(0, 0)], e[(1, 0)]), + Vec2::new(e[(0, 1)], e[(1, 1)]), + ) + } +} + +impl From for Matrix3 { + #[inline] + fn from(e: Mat3) -> Matrix3 { + e.to_cols_array_2d().into() + } +} + +impl From> for Mat3 +where + S: Storage, +{ + #[inline] + fn from(e: Matrix) -> Mat3 { + Mat3::from_cols( + Vec3::new(e[(0, 0)], e[(1, 0)], e[(2, 0)]), + Vec3::new(e[(0, 1)], e[(1, 1)], e[(2, 1)]), + Vec3::new(e[(0, 2)], e[(1, 2)], e[(2, 2)]), + ) + } +} + +impl From for Matrix4 { + #[inline] + fn from(e: Mat4) -> Matrix4 { + e.to_cols_array_2d().into() + } +} + +impl From> for Mat4 +where + S: Storage, +{ + #[inline] + fn from(e: Matrix) -> Mat4 { + Mat4::from_cols( + Vec4::new(e[(0, 0)], e[(1, 0)], e[(2, 0)], e[(3, 0)]), + Vec4::new(e[(0, 1)], e[(1, 1)], e[(2, 1)], e[(3, 1)]), + Vec4::new(e[(0, 2)], e[(1, 2)], e[(2, 2)], e[(3, 2)]), + Vec4::new(e[(0, 3)], e[(1, 3)], e[(2, 3)], e[(3, 3)]), + ) + } +} + +impl From for Matrix2 { + #[inline] + fn from(e: DMat2) -> Matrix2 { + e.to_cols_array_2d().into() + } +} + +impl From> for DMat2 +where + S: Storage, +{ + #[inline] + fn from(e: Matrix) -> DMat2 { + DMat2::from_cols( + DVec2::new(e[(0, 0)], e[(1, 0)]), + DVec2::new(e[(0, 1)], e[(1, 1)]), + ) + } +} + +impl From for Matrix3 { + #[inline] + fn from(e: DMat3) -> Matrix3 { + e.to_cols_array_2d().into() + } +} + +impl From> for DMat3 +where + S: Storage, +{ + #[inline] + fn from(e: Matrix) -> DMat3 { + DMat3::from_cols( + DVec3::new(e[(0, 0)], e[(1, 0)], e[(2, 0)]), + DVec3::new(e[(0, 1)], e[(1, 1)], e[(2, 1)]), + DVec3::new(e[(0, 2)], e[(1, 2)], e[(2, 2)]), + ) + } +} + +impl From for Matrix4 { + #[inline] + fn from(e: DMat4) -> Matrix4 { + e.to_cols_array_2d().into() + } +} + +impl From> for DMat4 +where + S: Storage, +{ + #[inline] + fn from(e: Matrix) -> DMat4 { + DMat4::from_cols( + DVec4::new(e[(0, 0)], e[(1, 0)], e[(2, 0)], e[(3, 0)]), + DVec4::new(e[(0, 1)], e[(1, 1)], e[(2, 1)], e[(3, 1)]), + DVec4::new(e[(0, 2)], e[(1, 2)], e[(2, 2)], e[(3, 2)]), + DVec4::new(e[(0, 3)], e[(1, 3)], e[(2, 3)], e[(3, 3)]), + ) + } +} diff --git a/src/third_party/glam/glam_point.rs b/src/third_party/glam/glam_point.rs new file mode 100644 index 00000000..823dc806 --- /dev/null +++ b/src/third_party/glam/glam_point.rs @@ -0,0 +1,71 @@ +use crate::{Point2, Point3, Point4}; +use glam::{ + BVec2, BVec3, BVec4, DVec2, DVec3, DVec4, IVec2, IVec3, IVec4, UVec2, UVec3, UVec4, Vec2, Vec3, + Vec3A, Vec4, +}; + +macro_rules! impl_point_conversion( + ($N: ty, $Vec2: ty, $Vec3: ty, $Vec4: ty) => { + impl From<$Vec2> for Point2<$N> { + #[inline] + fn from(e: $Vec2) -> Point2<$N> { + (*e.as_ref()).into() + } + } + + impl From> for $Vec2 { + #[inline] + fn from(e: Point2<$N>) -> $Vec2 { + <$Vec2>::new(e[0], e[1]) + } + } + + impl From<$Vec3> for Point3<$N> { + #[inline] + fn from(e: $Vec3) -> Point3<$N> { + (*e.as_ref()).into() + } + } + + impl From> for $Vec3 { + #[inline] + fn from(e: Point3<$N>) -> $Vec3 { + <$Vec3>::new(e[0], e[1], e[2]) + } + } + + impl From<$Vec4> for Point4<$N> { + #[inline] + fn from(e: $Vec4) -> Point4<$N> { + (*e.as_ref()).into() + } + } + + impl From> for $Vec4 { + #[inline] + fn from(e: Point4<$N>) -> $Vec4 { + <$Vec4>::new(e[0], e[1], e[2], e[3]) + } + } + } +); + +impl_point_conversion!(f32, Vec2, Vec3, Vec4); +impl_point_conversion!(f64, DVec2, DVec3, DVec4); +impl_point_conversion!(i32, IVec2, IVec3, IVec4); +impl_point_conversion!(u32, UVec2, UVec3, UVec4); +impl_point_conversion!(bool, BVec2, BVec3, BVec4); + +impl From for Point3 { + #[inline] + fn from(e: Vec3A) -> Point3 { + (*e.as_ref()).into() + } +} + +impl From> for Vec3A { + #[inline] + fn from(e: Point3) -> Vec3A { + Vec3A::new(e[0], e[1], e[2]) + } +} diff --git a/src/third_party/glam/glam_quaternion.rs b/src/third_party/glam/glam_quaternion.rs new file mode 100644 index 00000000..e57b7714 --- /dev/null +++ b/src/third_party/glam/glam_quaternion.rs @@ -0,0 +1,64 @@ +use crate::{Quaternion, UnitQuaternion}; +use glam::{DQuat, Quat}; + +impl From for Quaternion { + #[inline] + fn from(e: Quat) -> Quaternion { + Quaternion::new(e.w, e.x, e.y, e.z) + } +} + +impl From> for Quat { + #[inline] + fn from(e: Quaternion) -> Quat { + Quat::from_xyzw(e.i, e.j, e.k, e.w) + } +} + +impl From> for Quat { + #[inline] + fn from(e: UnitQuaternion) -> Quat { + Quat::from_xyzw(e.i, e.j, e.k, e.w) + } +} + +impl From for Quaternion { + #[inline] + fn from(e: DQuat) -> Quaternion { + Quaternion::new(e.w, e.x, e.y, e.z) + } +} + +impl From> for DQuat { + #[inline] + fn from(e: Quaternion) -> DQuat { + DQuat::from_xyzw(e.i, e.j, e.k, e.w) + } +} + +impl From> for DQuat { + #[inline] + fn from(e: UnitQuaternion) -> DQuat { + DQuat::from_xyzw(e.i, e.j, e.k, e.w) + } +} + +#[cfg(feature = "convert-glam-unchecked")] +mod unchecked { + use crate::{Quaternion, UnitQuaternion}; + use glam::{DQuat, Quat}; + + impl From for UnitQuaternion { + #[inline] + fn from(e: Quat) -> UnitQuaternion { + UnitQuaternion::new_unchecked(Quaternion::from(e)) + } + } + + impl From for UnitQuaternion { + #[inline] + fn from(e: DQuat) -> UnitQuaternion { + UnitQuaternion::new_unchecked(Quaternion::from(e)) + } + } +} diff --git a/src/third_party/glam/mod.rs b/src/third_party/glam/mod.rs new file mode 100644 index 00000000..a0bb8cda --- /dev/null +++ b/src/third_party/glam/mod.rs @@ -0,0 +1,4 @@ +mod glam_isometry; +mod glam_matrix; +mod glam_point; +mod glam_quaternion; diff --git a/src/third_party/mint/mint_matrix.rs b/src/third_party/mint/mint_matrix.rs new file mode 100644 index 00000000..30800f65 --- /dev/null +++ b/src/third_party/mint/mint_matrix.rs @@ -0,0 +1,117 @@ +use std::convert::{AsMut, AsRef, From, Into}; +use std::mem; +use std::ptr; + +use crate::base::allocator::Allocator; +use crate::base::dimension::{U1, U2, U3, U4}; +use crate::base::storage::{ContiguousStorage, ContiguousStorageMut, Storage, StorageMut}; +use crate::base::{DefaultAllocator, Matrix, MatrixMN, Scalar}; + +macro_rules! impl_from_into_mint_1D( + ($($NRows: ident => $VT:ident [$SZ: expr]);* $(;)*) => {$( + impl From> for MatrixMN + where N: Scalar, + DefaultAllocator: Allocator { + #[inline] + fn from(v: mint::$VT) -> Self { + unsafe { + let mut res = Self::new_uninitialized(); + ptr::copy_nonoverlapping(&v.x, (*res.as_mut_ptr()).data.ptr_mut(), $SZ); + + res.assume_init() + } + } + } + + impl Into> for Matrix + where N: Scalar, + S: ContiguousStorage { + #[inline] + fn into(self) -> mint::$VT { + unsafe { + let mut res: mint::$VT = mem::MaybeUninit::uninit().assume_init(); + ptr::copy_nonoverlapping(self.data.ptr(), &mut res.x, $SZ); + res + } + } + } + + impl AsRef> for Matrix + where N: Scalar, + S: ContiguousStorage { + #[inline] + fn as_ref(&self) -> &mint::$VT { + unsafe { + mem::transmute(self.data.ptr()) + } + } + } + + impl AsMut> for Matrix + where N: Scalar, + S: ContiguousStorageMut { + #[inline] + fn as_mut(&mut self) -> &mut mint::$VT { + unsafe { + mem::transmute(self.data.ptr_mut()) + } + } + } + )*} +); + +// Implement for vectors of dimension 2 .. 4. +impl_from_into_mint_1D!( + U2 => Vector2[2]; + U3 => Vector3[3]; + U4 => Vector4[4]; +); + +macro_rules! impl_from_into_mint_2D( + ($(($NRows: ty, $NCols: ty) => $MV:ident{ $($component:ident),* }[$SZRows: expr]);* $(;)*) => {$( + impl From> for MatrixMN + where N: Scalar, + DefaultAllocator: Allocator { + #[inline] + fn from(m: mint::$MV) -> Self { + unsafe { + let mut res = Self::new_uninitialized(); + let mut ptr = (*res.as_mut_ptr()).data.ptr_mut(); + $( + ptr::copy_nonoverlapping(&m.$component.x, ptr, $SZRows); + ptr = ptr.offset($SZRows); + )* + let _ = ptr; + res.assume_init() + } + } + } + + impl Into> for MatrixMN + where N: Scalar, + DefaultAllocator: Allocator { + #[inline] + fn into(self) -> mint::$MV { + unsafe { + let mut res: mint::$MV = mem::MaybeUninit::uninit().assume_init(); + let mut ptr = self.data.ptr(); + $( + ptr::copy_nonoverlapping(ptr, &mut res.$component.x, $SZRows); + ptr = ptr.offset($SZRows); + )* + let _ = ptr; + res + } + } + } + )*} +); + +// Implement for matrices with shape 2x2 .. 4x4. +impl_from_into_mint_2D!( + (U2, U2) => ColumnMatrix2{x, y}[2]; + (U2, U3) => ColumnMatrix2x3{x, y, z}[2]; + (U3, U3) => ColumnMatrix3{x, y, z}[3]; + (U3, U4) => ColumnMatrix3x4{x, y, z, w}[3]; + (U4, U4) => ColumnMatrix4{x, y, z, w}[4]; +); diff --git a/src/third_party/mint/mint_point.rs b/src/third_party/mint/mint_point.rs new file mode 100644 index 00000000..62a2bf77 --- /dev/null +++ b/src/third_party/mint/mint_point.rs @@ -0,0 +1,52 @@ +use crate::base::storage::{Storage, StorageMut}; +use crate::{Point, Scalar, VectorN, U2, U3}; +use std::convert::{AsMut, AsRef}; + +macro_rules! impl_from_into_mint_1D( + ($($NRows: ident => $PT:ident, $VT:ident [$SZ: expr]);* $(;)*) => {$( + impl From> for Point + where N: Scalar { + #[inline] + fn from(p: mint::$PT) -> Self { + Self { + coords: VectorN::from(mint::$VT::from(p)), + } + } + } + + impl Into> for Point + where N: Scalar { + #[inline] + fn into(self) -> mint::$PT { + let mint_vec: mint::$VT = self.coords.into(); + mint::$PT::from(mint_vec) + } + } + + impl AsRef> for Point + where N: Scalar { + #[inline] + fn as_ref(&self) -> &mint::$PT { + unsafe { + &*(self.coords.data.ptr() as *const mint::$PT) + } + } + } + + impl AsMut> for Point + where N: Scalar { + #[inline] + fn as_mut(&mut self) -> &mut mint::$PT { + unsafe { + &mut *(self.coords.data.ptr_mut() as *mut mint::$PT) + } + } + } + )*} +); + +// Implement for points of dimension 2, 3. +impl_from_into_mint_1D!( + U2 => Point2, Vector2[2]; + U3 => Point3, Vector3[3]; +); diff --git a/src/third_party/mint/mint_quaternion.rs b/src/third_party/mint/mint_quaternion.rs new file mode 100644 index 00000000..01a1a94c --- /dev/null +++ b/src/third_party/mint/mint_quaternion.rs @@ -0,0 +1,33 @@ +use crate::{Quaternion, Scalar, SimdValue, UnitQuaternion}; + +impl From> for Quaternion { + fn from(q: mint::Quaternion) -> Self { + Self::new(q.s, q.v.x, q.v.y, q.v.z) + } +} + +impl Into> for Quaternion { + fn into(self) -> mint::Quaternion { + mint::Quaternion { + v: mint::Vector3 { + x: self[0].inlined_clone(), + y: self[1].inlined_clone(), + z: self[2].inlined_clone(), + }, + s: self[3].inlined_clone(), + } + } +} + +impl Into> for UnitQuaternion { + fn into(self) -> mint::Quaternion { + mint::Quaternion { + v: mint::Vector3 { + x: self[0].inlined_clone(), + y: self[1].inlined_clone(), + z: self[2].inlined_clone(), + }, + s: self[3].inlined_clone(), + } + } +} diff --git a/src/third_party/mint/mint_rotation.rs b/src/third_party/mint/mint_rotation.rs new file mode 100644 index 00000000..9903da5d --- /dev/null +++ b/src/third_party/mint/mint_rotation.rs @@ -0,0 +1,7 @@ +use crate::{RealField, Rotation3}; + +impl From> for Rotation3 { + fn from(euler: mint::EulerAngles) -> Self { + Self::from_euler_angles(euler.a, euler.b, euler.c) + } +} diff --git a/src/third_party/mint/mod.rs b/src/third_party/mint/mod.rs new file mode 100644 index 00000000..3f326dfe --- /dev/null +++ b/src/third_party/mint/mod.rs @@ -0,0 +1,4 @@ +mod mint_matrix; +mod mint_point; +mod mint_quaternion; +mod mint_rotation; diff --git a/src/third_party/mod.rs b/src/third_party/mod.rs new file mode 100644 index 00000000..ce0fcaad --- /dev/null +++ b/src/third_party/mod.rs @@ -0,0 +1,6 @@ +#[cfg(feature = "alga")] +mod alga; +#[cfg(feature = "glam")] +mod glam; +#[cfg(feature = "mint")] +mod mint; From bdf0de68cf189b68cfd903061e9d7e8c60a12333 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crozet=20S=C3=A9bastien?= Date: Sat, 6 Mar 2021 12:38:15 +0100 Subject: [PATCH 2/4] Add conversion of Rotation and UnitComplex from/to glam types. --- src/geometry/mod.rs | 4 -- src/third_party/glam/glam_rotation.rs | 64 +++++++++++++++++++++++ src/third_party/glam/glam_unit_complex.rs | 36 +++++++++++++ src/third_party/glam/mod.rs | 2 + 4 files changed, 102 insertions(+), 4 deletions(-) create mode 100644 src/third_party/glam/glam_rotation.rs create mode 100644 src/third_party/glam/glam_unit_complex.rs diff --git a/src/geometry/mod.rs b/src/geometry/mod.rs index ef5e3eff..2675817e 100644 --- a/src/geometry/mod.rs +++ b/src/geometry/mod.rs @@ -23,8 +23,6 @@ mod rotation_simba; // TODO: implement Rotation methods. mod rotation_specialization; mod quaternion; -#[cfg(feature = "alga")] -mod quaternion_alga; mod quaternion_construction; mod quaternion_conversion; mod quaternion_coordinates; @@ -32,8 +30,6 @@ mod quaternion_ops; mod quaternion_simba; mod dual_quaternion; -#[cfg(feature = "alga")] -mod dual_quaternion_alga; mod dual_quaternion_construction; mod dual_quaternion_conversion; mod dual_quaternion_ops; diff --git a/src/third_party/glam/glam_rotation.rs b/src/third_party/glam/glam_rotation.rs new file mode 100644 index 00000000..2db9f50e --- /dev/null +++ b/src/third_party/glam/glam_rotation.rs @@ -0,0 +1,64 @@ +use crate::{Rotation2, Rotation3, UnitQuaternion}; +use glam::{DMat2, DQuat, Mat2, Quat}; + +impl From> for Mat2 { + #[inline] + fn from(e: Rotation2) -> Mat2 { + e.into_inner().into() + } +} + +impl From> for DMat2 { + #[inline] + fn from(e: Rotation2) -> DMat2 { + e.into_inner().into() + } +} + +impl From> for Quat { + #[inline] + fn from(e: Rotation3) -> Quat { + UnitQuaternion::from(e).into() + } +} + +impl From> for DQuat { + #[inline] + fn from(e: Rotation3) -> DQuat { + UnitQuaternion::from(e).into() + } +} + +#[cfg(feature = "convert-glam-unchecked")] +mod unchecked { + use crate::{Rotation2, Rotation3, UnitQuaternion}; + use glam::{DMat2, DQuat, Mat2, Quat}; + + impl From for Rotation2 { + #[inline] + fn from(e: Mat2) -> Rotation2 { + Rotation2::from_matrix_unchecked(e.into()) + } + } + + impl From for Rotation2 { + #[inline] + fn from(e: DMat2) -> Rotation2 { + Rotation2::from_matrix_unchecked(e.into()) + } + } + + impl From for Rotation3 { + #[inline] + fn from(e: Quat) -> Rotation3 { + Rotation3::from(UnitQuaternion::from(e)) + } + } + + impl From for Rotation3 { + #[inline] + fn from(e: DQuat) -> Rotation3 { + Rotation3::from(UnitQuaternion::from(e)) + } + } +} diff --git a/src/third_party/glam/glam_unit_complex.rs b/src/third_party/glam/glam_unit_complex.rs new file mode 100644 index 00000000..c5d9cc6a --- /dev/null +++ b/src/third_party/glam/glam_unit_complex.rs @@ -0,0 +1,36 @@ +use crate::UnitComplex; +use glam::{DMat2, Mat2}; + +impl From> for Mat2 { + #[inline] + fn from(e: UnitComplex) -> Mat2 { + e.to_rotation_matrix().into_inner().into() + } +} + +impl From> for DMat2 { + #[inline] + fn from(e: UnitComplex) -> DMat2 { + e.to_rotation_matrix().into_inner().into() + } +} + +#[cfg(feature = "convert-glam-unchecked")] +mod unchecked { + use crate::{Rotation2, UnitComplex}; + use glam::{DMat2, Mat2}; + + impl From for UnitComplex { + #[inline] + fn from(e: Mat2) -> UnitComplex { + Rotation2::from_matrix_unchecked(e.into()).into() + } + } + + impl From for UnitComplex { + #[inline] + fn from(e: DMat2) -> UnitComplex { + Rotation2::from_matrix_unchecked(e.into()).into() + } + } +} diff --git a/src/third_party/glam/mod.rs b/src/third_party/glam/mod.rs index a0bb8cda..55dc82c1 100644 --- a/src/third_party/glam/mod.rs +++ b/src/third_party/glam/mod.rs @@ -2,3 +2,5 @@ mod glam_isometry; mod glam_matrix; mod glam_point; mod glam_quaternion; +mod glam_rotation; +mod glam_unit_complex; From 2dae1ca44f4492c2bee7f476f4e6cb90f73341d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crozet=20S=C3=A9bastien?= Date: Sat, 6 Mar 2021 12:39:43 +0100 Subject: [PATCH 3/4] Add conversion of Similarity from/to glam types. --- src/third_party/glam/glam_similarity.rs | 54 +++++++++++++++++++++++++ src/third_party/glam/mod.rs | 1 + 2 files changed, 55 insertions(+) create mode 100644 src/third_party/glam/glam_similarity.rs diff --git a/src/third_party/glam/glam_similarity.rs b/src/third_party/glam/glam_similarity.rs new file mode 100644 index 00000000..92107074 --- /dev/null +++ b/src/third_party/glam/glam_similarity.rs @@ -0,0 +1,54 @@ +use crate::{Similarity2, Similarity3}; +use glam::{DMat3, DMat4, Mat3, Mat4}; + +impl From> for Mat3 { + fn from(iso: Similarity2) -> Mat3 { + iso.to_homogeneous().into() + } +} +impl From> for Mat4 { + fn from(iso: Similarity3) -> Mat4 { + iso.to_homogeneous().into() + } +} + +impl From> for DMat3 { + fn from(iso: Similarity2) -> DMat3 { + iso.to_homogeneous().into() + } +} +impl From> for DMat4 { + fn from(iso: Similarity3) -> DMat4 { + iso.to_homogeneous().into() + } +} + +#[cfg(feature = "convert-glam-unchecked")] +mod unchecked { + use crate::{Matrix3, Matrix4, Similarity2, Similarity3}; + use glam::{DMat3, DMat4, Mat3, Mat4}; + + impl From for Similarity2 { + fn from(mat3: Mat3) -> Similarity2 { + crate::convert_unchecked(Matrix3::from(mat3)) + } + } + + impl From for Similarity3 { + fn from(mat4: Mat4) -> Similarity3 { + crate::convert_unchecked(Matrix4::from(mat4)) + } + } + + impl From for Similarity2 { + fn from(mat3: DMat3) -> Similarity2 { + crate::convert_unchecked(Matrix3::from(mat3)) + } + } + + impl From for Similarity3 { + fn from(mat4: DMat4) -> Similarity3 { + crate::convert_unchecked(Matrix4::from(mat4)) + } + } +} diff --git a/src/third_party/glam/mod.rs b/src/third_party/glam/mod.rs index 55dc82c1..d4f8b643 100644 --- a/src/third_party/glam/mod.rs +++ b/src/third_party/glam/mod.rs @@ -3,4 +3,5 @@ mod glam_matrix; mod glam_point; mod glam_quaternion; mod glam_rotation; +mod glam_similarity; mod glam_unit_complex; From 35ffdc960d7fa93b8d31cb9c483636a51b31a82d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crozet=20S=C3=A9bastien?= Date: Sat, 6 Mar 2021 12:45:58 +0100 Subject: [PATCH 4/4] Update the changelog. --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2224a62a..b4af9114 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,12 @@ This project adheres to [Semantic Versioning](https://semver.org/). ## [0.25.2] - WIP ### Added +- A `convert-glam` cargo feature to enable implementations of `From` traits to convert + between `glam` types and `nalgebra` types. +- A `convert-glam-unchecked` cargo feature to enable some extra `glam`/`nalgebra` conversions that may + lead to unexpected results if used improperly. For example, this enables the conversion from a + `glam::Mat4` to a `na::Isometry3`. This conversion will be cheap (without any check) but willlead to + unexpected results if the glam matrix contains non-isometric components (like scaling for example). - A `cast` method has been added to most types. This can be used to change the type of the components of a given entity. Example: `vector.cast::()`.