Skip to content

Commit

Permalink
Merge pull request #874 from dimforge/more_conversions
Browse files Browse the repository at this point in the history
More conversions
  • Loading branch information
sebcrozet committed Apr 27, 2021
2 parents 984bb1a + 0745384 commit fb21476
Show file tree
Hide file tree
Showing 9 changed files with 244 additions and 69 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Expand Up @@ -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<T, _, D>` (as a translation).
- Conversion from a static vector `SVector<T; D>` to an isometry `Isometry<T, _, D>` (as a translation).
- Conversion from a point `Point<T; D>` to an isometry `Isometry<T, _, D>` (as a translation).
- Conversion of an array `[T; D]` from/to a translation `Translation<T, D>`.
- Conversion of a point `Point<T, D>` to a translation `Translation<T, D>`.
- 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`.

Expand Down
83 changes: 30 additions & 53 deletions src/base/conversion.rs
Expand Up @@ -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};

Expand All @@ -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<T1, T2, R1, C1, R2, C2> SubsetOf<OMatrix<T2, R2, C2>> for OMatrix<T1, R1, C1>
Expand Down Expand Up @@ -103,35 +103,23 @@ impl<'a, T: Scalar, R: Dim, C: Dim, S: StorageMut<T, R, C>> IntoIterator
}
}

macro_rules! impl_from_into_asref_1D(
($(($NRows: ident, $NCols: ident) => $SZ: expr);* $(;)*) => {$(
impl<T> From<[T; $SZ]> for OMatrix<T, $NRows, $NCols>
where T: Scalar,
DefaultAllocator: Allocator<T, $NRows, $NCols> {
#[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<T, S> Into<[T; $SZ]> for Matrix<T, $NRows, $NCols, S>
where T: Scalar,
S: ContiguousStorage<T, $NRows, $NCols> {
#[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) };
impl<T: Scalar, const D: usize> From<[T; D]> for SVector<T, D> {
#[inline]
fn from(arr: [T; D]) -> Self {
unsafe { Self::from_data_statically_unchecked(ArrayStorage([arr; 1])) }
}
}

unsafe { res.assume_init() }
}
}
impl<T: Scalar, const D: usize> Into<[T; D]> for SVector<T, D> {
#[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<T, S> AsRef<[T; $SZ]> for Matrix<T, $NRows, $NCols, S>
where T: Scalar,
S: ContiguousStorage<T, $NRows, $NCols> {
Expand Down Expand Up @@ -171,33 +159,22 @@ impl_from_into_asref_1D!(
(U13, U1) => 13; (U14, U1) => 14; (U15, U1) => 15; (U16, U1) => 16;
);

macro_rules! impl_from_into_asref_2D(
($(($NRows: ty, $NCols: ty) => ($SZRows: expr, $SZCols: expr));* $(;)*) => {$(
impl<T: Scalar> From<[[T; $SZRows]; $SZCols]> for OMatrix<T, $NRows, $NCols>
where DefaultAllocator: Allocator<T, $NRows, $NCols> {
#[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<T: Scalar, S> Into<[[T; $SZRows]; $SZCols]> for Matrix<T, $NRows, $NCols, S>
where S: ContiguousStorage<T, $NRows, $NCols> {
#[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) };
impl<T: Scalar, const R: usize, const C: usize> From<[[T; R]; C]> for SMatrix<T, R, C> {
#[inline]
fn from(arr: [[T; R]; C]) -> Self {
unsafe { Self::from_data_statically_unchecked(ArrayStorage(arr)) }
}
}

unsafe { res.assume_init() }
}
}
impl<T: Scalar, const R: usize, const C: usize> Into<[[T; R]; C]> for SMatrix<T, R, C> {
#[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<T: Scalar, S> AsRef<[[T; $SZRows]; $SZCols]> for Matrix<T, $NRows, $NCols, S>
where S: ContiguousStorage<T, $NRows, $NCols> {
#[inline]
Expand Down
30 changes: 30 additions & 0 deletions src/geometry/isometry_conversion.rs
Expand Up @@ -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:
Expand Down Expand Up @@ -198,6 +199,35 @@ where
}
}

impl<T: SimdRealField, R, const D: usize> From<[T; D]> for Isometry<T, R, D>
where
R: AbstractRotation<T, D>,
{
#[inline]
fn from(coords: [T; D]) -> Self {
Self::from_parts(coords.into(), R::identity())
}
}

impl<T: SimdRealField, R, const D: usize> From<SVector<T, D>> for Isometry<T, R, D>
where
R: AbstractRotation<T, D>,
{
#[inline]
fn from(coords: SVector<T, D>) -> Self {
Self::from_parts(coords.into(), R::identity())
}
}
impl<T: SimdRealField, R, const D: usize> From<Point<T, D>> for Isometry<T, R, D>
where
R: AbstractRotation<T, D>,
{
#[inline]
fn from(coords: Point<T, D>) -> Self {
Self::from_parts(coords.into(), R::identity())
}
}

impl<T: Scalar + PrimitiveSimdValue, R, const D: usize>
From<[Isometry<T::Element, R::Element, D>; 2]> for Isometry<T, R, D>
where
Expand Down
14 changes: 0 additions & 14 deletions src/geometry/point_construction.rs
Expand Up @@ -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 <T: Scalar> From<[T; $len]> for $Point<T> {
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);
16 changes: 16 additions & 0 deletions src/geometry/point_conversion.rs
Expand Up @@ -81,6 +81,22 @@ where
}
}

impl<T: Scalar, const D: usize> From<[T; D]> for Point<T, D> {
#[inline]
fn from(coords: [T; D]) -> Self {
Point {
coords: coords.into(),
}
}
}

impl<T: Scalar, const D: usize> Into<[T; D]> for Point<T, D> {
#[inline]
fn into(self) -> [T; D] {
self.coords.into()
}
}

impl<T: Scalar, const D: usize> From<OVector<T, Const<D>>> for Point<T, D> {
#[inline]
fn from(coords: OVector<T, Const<D>>) -> Self {
Expand Down
26 changes: 26 additions & 0 deletions src/geometry/translation_conversion.rs
Expand Up @@ -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:
Expand Down Expand Up @@ -199,6 +200,31 @@ impl<T: Scalar, const D: usize> From<OVector<T, Const<D>>> for Translation<T, D>
}
}

impl<T: Scalar, const D: usize> From<[T; D]> for Translation<T, D> {
#[inline]
fn from(coords: [T; D]) -> Self {
Translation {
vector: coords.into(),
}
}
}

impl<T: Scalar, const D: usize> From<Point<T, D>> for Translation<T, D> {
#[inline]
fn from(pt: Point<T, D>) -> Self {
Translation {
vector: pt.coords.into(),
}
}
}

impl<T: Scalar, const D: usize> Into<[T; D]> for Translation<T, D> {
#[inline]
fn into(self) -> [T; D] {
self.vector.into()
}
}

impl<T: Scalar + PrimitiveSimdValue, const D: usize> From<[Translation<T::Element, D>; 2]>
for Translation<T, D>
where
Expand Down
68 changes: 66 additions & 2 deletions 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<Isometry2<f32>> for Mat3 {
fn from(iso: Isometry2<f32>) -> Mat3 {
Expand All @@ -23,10 +23,74 @@ impl From<Isometry3<f64>> for DMat4 {
}
}

impl From<Isometry3<f32>> for (Vec3, Quat) {
fn from(iso: Isometry3<f32>) -> (Vec3, Quat) {
(iso.translation.into(), iso.rotation.into())
}
}

impl From<Isometry3<f64>> for (DVec3, DQuat) {
fn from(iso: Isometry3<f64>) -> (DVec3, DQuat) {
(iso.translation.into(), iso.rotation.into())
}
}

impl From<Isometry2<f32>> for (Vec3, Quat) {
fn from(iso: Isometry2<f32>) -> (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<Isometry2<f64>> for (DVec3, DQuat) {
fn from(iso: Isometry2<f64>) -> (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<f32> {
fn from((tra, rot): (Vec3, Quat)) -> Self {
Isometry3::from_parts(tra.into(), rot.into())
}
}

impl From<(DVec3, DQuat)> for Isometry3<f64> {
fn from((tra, rot): (DVec3, DQuat)) -> Self {
Isometry3::from_parts(tra.into(), rot.into())
}
}

impl From<(Vec3, Quat)> for Isometry2<f32> {
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<f64> {
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<f32> {
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<f64> {
fn from((tra, rot): (DVec2, DQuat)) -> Self {
Isometry2::new([tra.x, tra.y].into(), rot.to_axis_angle().1)
}
}

impl From<Mat3> for Isometry2<f32> {
fn from(mat3: Mat3) -> Isometry2<f32> {
Expand Down

0 comments on commit fb21476

Please sign in to comment.