diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c762fd5..029532b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,16 @@ documented here. This project adheres to [Semantic Versioning](https://semver.org/). +## [0.26.2] +###Added +- Conversion from an array `[T; D]` to an isometry `Isometry` (as a translation). +- Conversion from a static vector `SVector` to an isometry `Isometry` (as a translation). +- Conversion from a point `Point` to an isometry `Isometry` (as a translation). +- Conversion of an array `[T; D]` from/to a translation `Translation`. +- Conversion of a point `Point` to a translation `Translation`. +- Conversion of the tuple of glam types `(Vec3, Quat)` from/to an `Isometry2` or `Isometry3`. +- Conversion of a glam type `Vec2/3/4` from/to a `Translation2/3/4`. + ## [0.26.1] Fix a regression introduced in 0.26.0 preventing `DVector` from being serialized with `serde`. diff --git a/src/base/conversion.rs b/src/base/conversion.rs index 24a088a2..b329dba1 100644 --- a/src/base/conversion.rs +++ b/src/base/conversion.rs @@ -3,7 +3,6 @@ use alloc::vec::Vec; use simba::scalar::{SubsetOf, SupersetOf}; use std::convert::{AsMut, AsRef, From, Into}; use std::mem; -use std::ptr; use simba::simd::{PrimitiveSimdValue, SimdValue}; @@ -24,6 +23,7 @@ use crate::base::{ use crate::base::{DVector, VecStorage}; use crate::base::{SliceStorage, SliceStorageMut}; use crate::constraint::DimEq; +use crate::{SMatrix, SVector}; // TODO: too bad this won't work allo slice conversions. impl SubsetOf> for OMatrix @@ -103,35 +103,23 @@ impl<'a, T: Scalar, R: Dim, C: Dim, S: StorageMut> IntoIterator } } +impl From<[T; D]> for SVector { + #[inline] + fn from(arr: [T; D]) -> Self { + unsafe { Self::from_data_statically_unchecked(ArrayStorage([arr; 1])) } + } +} + +impl Into<[T; D]> for SVector { + #[inline] + fn into(self) -> [T; D] { + // TODO: unfortunately, we must clone because we can move out of an array. + self.data.0[0].clone() + } +} + macro_rules! impl_from_into_asref_1D( ($(($NRows: ident, $NCols: ident) => $SZ: expr);* $(;)*) => {$( - impl From<[T; $SZ]> for OMatrix - where T: Scalar, - DefaultAllocator: Allocator { - #[inline] - fn from(arr: [T; $SZ]) -> Self { - unsafe { - let mut res = Self::new_uninitialized(); - ptr::copy_nonoverlapping(&arr[0], (*res.as_mut_ptr()).data.ptr_mut(), $SZ); - - res.assume_init() - } - } - } - - impl Into<[T; $SZ]> for Matrix - where T: Scalar, - S: ContiguousStorage { - #[inline] - fn into(self) -> [T; $SZ] { - let mut res = mem::MaybeUninit::<[T; $SZ]>::uninit(); - - unsafe { ptr::copy_nonoverlapping(self.data.ptr(), res.as_mut_ptr() as *mut T, $SZ) }; - - unsafe { res.assume_init() } - } - } - impl AsRef<[T; $SZ]> for Matrix where T: Scalar, S: ContiguousStorage { @@ -171,33 +159,22 @@ impl_from_into_asref_1D!( (U13, U1) => 13; (U14, U1) => 14; (U15, U1) => 15; (U16, U1) => 16; ); +impl From<[[T; R]; C]> for SMatrix { + #[inline] + fn from(arr: [[T; R]; C]) -> Self { + unsafe { Self::from_data_statically_unchecked(ArrayStorage(arr)) } + } +} + +impl Into<[[T; R]; C]> for SMatrix { + #[inline] + fn into(self) -> [[T; R]; C] { + self.data.0 + } +} + macro_rules! impl_from_into_asref_2D( ($(($NRows: ty, $NCols: ty) => ($SZRows: expr, $SZCols: expr));* $(;)*) => {$( - impl From<[[T; $SZRows]; $SZCols]> for OMatrix - where DefaultAllocator: Allocator { - #[inline] - fn from(arr: [[T; $SZRows]; $SZCols]) -> Self { - unsafe { - let mut res = Self::new_uninitialized(); - ptr::copy_nonoverlapping(&arr[0][0], (*res.as_mut_ptr()).data.ptr_mut(), $SZRows * $SZCols); - - res.assume_init() - } - } - } - - impl Into<[[T; $SZRows]; $SZCols]> for Matrix - where S: ContiguousStorage { - #[inline] - fn into(self) -> [[T; $SZRows]; $SZCols] { - let mut res = mem::MaybeUninit::<[[T; $SZRows]; $SZCols]>::uninit(); - - unsafe { ptr::copy_nonoverlapping(self.data.ptr(), res.as_mut_ptr() as *mut T, $SZRows * $SZCols) }; - - unsafe { res.assume_init() } - } - } - impl AsRef<[[T; $SZRows]; $SZCols]> for Matrix where S: ContiguousStorage { #[inline] diff --git a/src/geometry/isometry_conversion.rs b/src/geometry/isometry_conversion.rs index b8cc4568..75c0d98d 100644 --- a/src/geometry/isometry_conversion.rs +++ b/src/geometry/isometry_conversion.rs @@ -9,6 +9,7 @@ use crate::geometry::{ AbstractRotation, Isometry, Isometry3, Similarity, SuperTCategoryOf, TAffine, Transform, Translation, UnitDualQuaternion, UnitQuaternion, }; +use crate::{Point, SVector}; /* * This file provides the following conversions: @@ -198,6 +199,35 @@ where } } +impl From<[T; D]> for Isometry +where + R: AbstractRotation, +{ + #[inline] + fn from(coords: [T; D]) -> Self { + Self::from_parts(coords.into(), R::identity()) + } +} + +impl From> for Isometry +where + R: AbstractRotation, +{ + #[inline] + fn from(coords: SVector) -> Self { + Self::from_parts(coords.into(), R::identity()) + } +} +impl From> for Isometry +where + R: AbstractRotation, +{ + #[inline] + fn from(coords: Point) -> Self { + Self::from_parts(coords.into(), R::identity()) + } +} + impl From<[Isometry; 2]> for Isometry where diff --git a/src/geometry/point_construction.rs b/src/geometry/point_construction.rs index f50a3fc1..7e34137c 100644 --- a/src/geometry/point_construction.rs +++ b/src/geometry/point_construction.rs @@ -225,17 +225,3 @@ componentwise_constructors_impl!( "# use nalgebra::Point6;\nlet p = Point6::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0);\nassert!(p.x == 1.0 && p.y == 2.0 && p.z == 3.0 && p.w == 4.0 && p.a == 5.0 && p.b == 6.0);"; Point6, Vector6, x:0, y:1, z:2, w:3, a:4, b:5; ); - -macro_rules! from_array_impl( - ($($Point: ident, $len: expr);*) => {$( - impl From<[T; $len]> for $Point { - fn from(coords: [T; $len]) -> Self { - Self { - coords: coords.into() - } - } - } - )*} -); - -from_array_impl!(Point1, 1; Point2, 2; Point3, 3; Point4, 4; Point5, 5; Point6, 6); diff --git a/src/geometry/point_conversion.rs b/src/geometry/point_conversion.rs index 08438ec0..91cd62ce 100644 --- a/src/geometry/point_conversion.rs +++ b/src/geometry/point_conversion.rs @@ -81,6 +81,22 @@ where } } +impl From<[T; D]> for Point { + #[inline] + fn from(coords: [T; D]) -> Self { + Point { + coords: coords.into(), + } + } +} + +impl Into<[T; D]> for Point { + #[inline] + fn into(self) -> [T; D] { + self.coords.into() + } +} + impl From>> for Point { #[inline] fn from(coords: OVector>) -> Self { diff --git a/src/geometry/translation_conversion.rs b/src/geometry/translation_conversion.rs index 8c8f860f..ff8e797f 100644 --- a/src/geometry/translation_conversion.rs +++ b/src/geometry/translation_conversion.rs @@ -11,6 +11,7 @@ use crate::geometry::{ AbstractRotation, Isometry, Similarity, SuperTCategoryOf, TAffine, Transform, Translation, Translation3, UnitDualQuaternion, UnitQuaternion, }; +use crate::Point; /* * This file provides the following conversions: @@ -199,6 +200,31 @@ impl From>> for Translation } } +impl From<[T; D]> for Translation { + #[inline] + fn from(coords: [T; D]) -> Self { + Translation { + vector: coords.into(), + } + } +} + +impl From> for Translation { + #[inline] + fn from(pt: Point) -> Self { + Translation { + vector: pt.coords.into(), + } + } +} + +impl Into<[T; D]> for Translation { + #[inline] + fn into(self) -> [T; D] { + self.vector.into() + } +} + impl From<[Translation; 2]> for Translation where diff --git a/src/third_party/glam/glam_isometry.rs b/src/third_party/glam/glam_isometry.rs index 52c36e37..34a321e5 100644 --- a/src/third_party/glam/glam_isometry.rs +++ b/src/third_party/glam/glam_isometry.rs @@ -1,5 +1,5 @@ use crate::{Isometry2, Isometry3}; -use glam::{DMat3, DMat4, Mat3, Mat4}; +use glam::{DMat3, DMat4, DQuat, DVec3, Mat3, Mat4, Quat, Vec3}; impl From> for Mat3 { fn from(iso: Isometry2) -> Mat3 { @@ -23,10 +23,74 @@ impl From> for DMat4 { } } +impl From> for (Vec3, Quat) { + fn from(iso: Isometry3) -> (Vec3, Quat) { + (iso.translation.into(), iso.rotation.into()) + } +} + +impl From> for (DVec3, DQuat) { + fn from(iso: Isometry3) -> (DVec3, DQuat) { + (iso.translation.into(), iso.rotation.into()) + } +} + +impl From> for (Vec3, Quat) { + fn from(iso: Isometry2) -> (Vec3, Quat) { + let tra = Vec3::new(iso.translation.x, iso.translation.y, 0.0); + let rot = Quat::from_axis_angle(Vec3::new(0.0, 0.0, 1.0), iso.rotation.angle()); + (tra, rot) + } +} + +impl From> for (DVec3, DQuat) { + fn from(iso: Isometry2) -> (DVec3, DQuat) { + let tra = DVec3::new(iso.translation.x, iso.translation.y, 0.0); + let rot = DQuat::from_axis_angle(DVec3::new(0.0, 0.0, 1.0), iso.rotation.angle()); + (tra, rot) + } +} + #[cfg(feature = "convert-glam-unchecked")] mod unchecked { use crate::{Isometry2, Isometry3, Matrix3, Matrix4}; - use glam::{DMat3, DMat4, Mat3, Mat4}; + use glam::{DMat3, DMat4, DQuat, DVec2, DVec3, Mat3, Mat4, Quat, Vec2, Vec3}; + + impl From<(Vec3, Quat)> for Isometry3 { + fn from((tra, rot): (Vec3, Quat)) -> Self { + Isometry3::from_parts(tra.into(), rot.into()) + } + } + + impl From<(DVec3, DQuat)> for Isometry3 { + fn from((tra, rot): (DVec3, DQuat)) -> Self { + Isometry3::from_parts(tra.into(), rot.into()) + } + } + + impl From<(Vec3, Quat)> for Isometry2 { + fn from((tra, rot): (Vec3, Quat)) -> Self { + Isometry2::new([tra.x, tra.y].into(), rot.to_axis_angle().1) + } + } + + impl From<(DVec3, DQuat)> for Isometry2 { + fn from((tra, rot): (DVec3, DQuat)) -> Self { + Isometry2::new([tra.x, tra.y].into(), rot.to_axis_angle().1) + } + } + + impl From<(Vec2, Quat)> for Isometry2 { + fn from((tra, rot): (Vec2, Quat)) -> Self { + Isometry2::new([tra.x, tra.y].into(), rot.to_axis_angle().1) + } + } + + impl From<(DVec2, DQuat)> for Isometry2 { + fn from((tra, rot): (DVec2, DQuat)) -> Self { + Isometry2::new([tra.x, tra.y].into(), rot.to_axis_angle().1) + } + } impl From for Isometry2 { fn from(mat3: Mat3) -> Isometry2 { diff --git a/src/third_party/glam/glam_translation.rs b/src/third_party/glam/glam_translation.rs new file mode 100644 index 00000000..f92d3275 --- /dev/null +++ b/src/third_party/glam/glam_translation.rs @@ -0,0 +1,65 @@ +use crate::{Translation2, Translation3, Translation4}; +use glam::{DVec2, DVec3, DVec4, Vec2, Vec3, Vec3A, Vec4}; + +macro_rules! impl_translation_conversion( + ($N: ty, $Vec2: ty, $Vec3: ty, $Vec4: ty) => { + impl From<$Vec2> for Translation2<$N> { + #[inline] + fn from(e: $Vec2) -> Translation2<$N> { + (*e.as_ref()).into() + } + } + + impl From> for $Vec2 { + #[inline] + fn from(e: Translation2<$N>) -> $Vec2 { + e.vector.into() + } + } + + impl From<$Vec3> for Translation3<$N> { + #[inline] + fn from(e: $Vec3) -> Translation3<$N> { + (*e.as_ref()).into() + } + } + + impl From> for $Vec3 { + #[inline] + fn from(e: Translation3<$N>) -> $Vec3 { + e.vector.into() + } + } + + impl From<$Vec4> for Translation4<$N> { + #[inline] + fn from(e: $Vec4) -> Translation4<$N> { + (*e.as_ref()).into() + } + } + + impl From> for $Vec4 { + #[inline] + fn from(e: Translation4<$N>) -> $Vec4 { + e.vector.into() + } + } + } +); + +impl_translation_conversion!(f32, Vec2, Vec3, Vec4); +impl_translation_conversion!(f64, DVec2, DVec3, DVec4); + +impl From for Translation3 { + #[inline] + fn from(e: Vec3A) -> Translation3 { + (*e.as_ref()).into() + } +} + +impl From> for Vec3A { + #[inline] + fn from(e: Translation3) -> Vec3A { + e.vector.into() + } +} diff --git a/src/third_party/glam/mod.rs b/src/third_party/glam/mod.rs index d4f8b643..20925923 100644 --- a/src/third_party/glam/mod.rs +++ b/src/third_party/glam/mod.rs @@ -4,4 +4,5 @@ mod glam_point; mod glam_quaternion; mod glam_rotation; mod glam_similarity; +mod glam_translation; mod glam_unit_complex;