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::{ AbstractRotation, Isometry, Quaternion, Rotation, Rotation3, Similarity, SuperTCategoryOf, TAffine, Transform, Translation, UnitQuaternion, }; /* * This file provides the following conversions: * ============================================= * * Quaternion -> Quaternion * UnitQuaternion -> UnitQuaternion * UnitQuaternion -> Rotation * UnitQuaternion -> Isometry * UnitQuaternion -> Similarity * UnitQuaternion -> Transform * UnitQuaternion -> Matrix (homogeneous) * * mint::Quaternion <-> Quaternion * UnitQuaternion -> mint::Quaternion * * NOTE: * UnitQuaternion -> Quaternion is already provided by: Unit -> T */ impl SubsetOf> for Quaternion where N1: SimdRealField, N2: SimdRealField + SupersetOf, { #[inline] fn to_superset(&self) -> Quaternion { Quaternion::from(self.coords.to_superset()) } #[inline] fn is_in_subset(q: &Quaternion) -> bool { crate::is_convertible::<_, Vector4>(&q.coords) } #[inline] fn from_superset_unchecked(q: &Quaternion) -> Self { Self { coords: q.coords.to_subset_unchecked(), } } } impl SubsetOf> for UnitQuaternion where N1: SimdRealField, N2: SimdRealField + SupersetOf, { #[inline] fn to_superset(&self) -> UnitQuaternion { UnitQuaternion::new_unchecked(self.as_ref().to_superset()) } #[inline] fn is_in_subset(uq: &UnitQuaternion) -> bool { crate::is_convertible::<_, Quaternion>(uq.as_ref()) } #[inline] fn from_superset_unchecked(uq: &UnitQuaternion) -> Self { Self::new_unchecked(crate::convert_ref_unchecked(uq.as_ref())) } } impl SubsetOf> for UnitQuaternion where N1: RealField, N2: RealField + SupersetOf, { #[inline] fn to_superset(&self) -> Rotation3 { let q: UnitQuaternion = self.to_superset(); q.to_rotation_matrix() } #[inline] fn is_in_subset(rot: &Rotation3) -> bool { crate::is_convertible::<_, Rotation3>(rot) } #[inline] fn from_superset_unchecked(rot: &Rotation3) -> Self { let q = UnitQuaternion::::from_rotation_matrix(rot); crate::convert_unchecked(q) } } impl SubsetOf> for UnitQuaternion where N1: RealField, N2: RealField + SupersetOf, R: AbstractRotation + SupersetOf, { #[inline] fn to_superset(&self) -> Isometry { Isometry::from_parts(Translation::identity(), crate::convert_ref(self)) } #[inline] fn is_in_subset(iso: &Isometry) -> bool { iso.translation.vector.is_zero() } #[inline] fn from_superset_unchecked(iso: &Isometry) -> Self { crate::convert_ref_unchecked(&iso.rotation) } } impl SubsetOf> for UnitQuaternion where N1: RealField, N2: RealField + SupersetOf, R: AbstractRotation + SupersetOf, { #[inline] fn to_superset(&self) -> Similarity { Similarity::from_isometry(crate::convert_ref(self), N2::one()) } #[inline] fn is_in_subset(sim: &Similarity) -> bool { sim.isometry.translation.vector.is_zero() && sim.scaling() == N2::one() } #[inline] fn from_superset_unchecked(sim: &Similarity) -> Self { crate::convert_ref_unchecked(&sim.isometry) } } impl SubsetOf> for UnitQuaternion where N1: RealField, N2: RealField + SupersetOf, C: SuperTCategoryOf, { #[inline] fn to_superset(&self) -> Transform { Transform::from_matrix_unchecked(self.to_homogeneous().to_superset()) } #[inline] fn is_in_subset(t: &Transform) -> bool { >::is_in_subset(t.matrix()) } #[inline] fn from_superset_unchecked(t: &Transform) -> Self { Self::from_superset_unchecked(t.matrix()) } } impl> SubsetOf> for UnitQuaternion { #[inline] fn to_superset(&self) -> Matrix4 { self.to_homogeneous().to_superset() } #[inline] fn is_in_subset(m: &Matrix4) -> bool { crate::is_convertible::<_, Rotation3>(m) } #[inline] fn from_superset_unchecked(m: &Matrix4) -> Self { let rot: Rotation3 = crate::convert_ref_unchecked(m); Self::from_rotation_matrix(&rot) } } #[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], y: self[1], z: self[2], }, s: self[3], } } } #[cfg(feature = "mint")] impl Into> for UnitQuaternion { fn into(self) -> mint::Quaternion { mint::Quaternion { v: mint::Vector3 { x: self[0], y: self[1], z: self[2], }, s: self[3], } } } impl From> for Matrix4 where N::Element: SimdRealField, { #[inline] fn from(q: UnitQuaternion) -> Self { q.to_homogeneous() } } impl From> for Rotation3 where N::Element: SimdRealField, { #[inline] fn from(q: UnitQuaternion) -> Self { q.to_rotation_matrix() } } impl From> for UnitQuaternion where N::Element: SimdRealField, { #[inline] fn from(q: Rotation3) -> Self { Self::from_rotation_matrix(&q) } } impl From> for Matrix3 where N::Element: SimdRealField, { #[inline] fn from(q: UnitQuaternion) -> Self { q.to_rotation_matrix().into_inner() } } impl From> for Quaternion { #[inline] fn from(coords: Vector4) -> Self { Self { coords } } } impl From<[Quaternion; 2]> for Quaternion where N: From<[::Element; 2]>, N::Element: Scalar + Copy, { #[inline] fn from(arr: [Quaternion; 2]) -> Self { Self::from(Vector4::from([arr[0].coords, arr[1].coords])) } } impl From<[Quaternion; 4]> for Quaternion where N: From<[::Element; 4]>, N::Element: Scalar + Copy, { #[inline] fn from(arr: [Quaternion; 4]) -> Self { Self::from(Vector4::from([ arr[0].coords, arr[1].coords, arr[2].coords, arr[3].coords, ])) } } impl From<[Quaternion; 8]> for Quaternion where N: From<[::Element; 8]>, N::Element: Scalar + Copy, { #[inline] fn from(arr: [Quaternion; 8]) -> Self { Self::from(Vector4::from([ arr[0].coords, arr[1].coords, arr[2].coords, arr[3].coords, arr[4].coords, arr[5].coords, arr[6].coords, arr[7].coords, ])) } } impl From<[Quaternion; 16]> for Quaternion where N: From<[::Element; 16]>, N::Element: Scalar + Copy, { #[inline] fn from(arr: [Quaternion; 16]) -> Self { Self::from(Vector4::from([ arr[0].coords, arr[1].coords, arr[2].coords, arr[3].coords, arr[4].coords, arr[5].coords, arr[6].coords, arr[7].coords, arr[8].coords, arr[9].coords, arr[10].coords, arr[11].coords, arr[12].coords, arr[13].coords, arr[14].coords, arr[15].coords, ])) } } impl From<[UnitQuaternion; 2]> for UnitQuaternion where N: From<[::Element; 2]>, N::Element: Scalar + Copy, { #[inline] fn from(arr: [UnitQuaternion; 2]) -> Self { Self::new_unchecked(Quaternion::from([arr[0].into_inner(), arr[1].into_inner()])) } } impl From<[UnitQuaternion; 4]> for UnitQuaternion where N: From<[::Element; 4]>, N::Element: Scalar + Copy, { #[inline] fn from(arr: [UnitQuaternion; 4]) -> Self { Self::new_unchecked(Quaternion::from([ arr[0].into_inner(), arr[1].into_inner(), arr[2].into_inner(), arr[3].into_inner(), ])) } } impl From<[UnitQuaternion; 8]> for UnitQuaternion where N: From<[::Element; 8]>, N::Element: Scalar + Copy, { #[inline] fn from(arr: [UnitQuaternion; 8]) -> Self { Self::new_unchecked(Quaternion::from([ arr[0].into_inner(), arr[1].into_inner(), arr[2].into_inner(), arr[3].into_inner(), arr[4].into_inner(), arr[5].into_inner(), arr[6].into_inner(), arr[7].into_inner(), ])) } } impl From<[UnitQuaternion; 16]> for UnitQuaternion where N: From<[::Element; 16]>, N::Element: Scalar + Copy, { #[inline] fn from(arr: [UnitQuaternion; 16]) -> Self { Self::new_unchecked(Quaternion::from([ arr[0].into_inner(), arr[1].into_inner(), arr[2].into_inner(), arr[3].into_inner(), arr[4].into_inner(), arr[5].into_inner(), arr[6].into_inner(), arr[7].into_inner(), arr[8].into_inner(), arr[9].into_inner(), arr[10].into_inner(), arr[11].into_inner(), arr[12].into_inner(), arr[13].into_inner(), arr[14].into_inner(), arr[15].into_inner(), ])) } }