forked from M-Labs/nalgebra
Add conversion from/to glam types + move glam/alga/mint impls to a "third_party" module.
This commit is contained in:
parent
4bb1edaab4
commit
729a8fd7f2
25
Cargo.toml
25
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,10 +31,25 @@ 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
|
||||
# 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]
|
||||
@ -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 }
|
||||
|
@ -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<N> From<mint::$VT<N>> for MatrixMN<N, $NRows, U1>
|
||||
where N: Scalar,
|
||||
DefaultAllocator: Allocator<N, $NRows, U1> {
|
||||
#[inline]
|
||||
fn from(v: mint::$VT<N>) -> 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<N, S> Into<mint::$VT<N>> for Matrix<N, $NRows, U1, S>
|
||||
where N: Scalar,
|
||||
S: ContiguousStorage<N, $NRows, U1> {
|
||||
#[inline]
|
||||
fn into(self) -> mint::$VT<N> {
|
||||
unsafe {
|
||||
let mut res: mint::$VT<N> = mem::MaybeUninit::uninit().assume_init();
|
||||
ptr::copy_nonoverlapping(self.data.ptr(), &mut res.x, $SZ);
|
||||
res
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N, S> AsRef<mint::$VT<N>> for Matrix<N, $NRows, U1, S>
|
||||
where N: Scalar,
|
||||
S: ContiguousStorage<N, $NRows, U1> {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &mint::$VT<N> {
|
||||
unsafe {
|
||||
mem::transmute(self.data.ptr())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N, S> AsMut<mint::$VT<N>> for Matrix<N, $NRows, U1, S>
|
||||
where N: Scalar,
|
||||
S: ContiguousStorageMut<N, $NRows, U1> {
|
||||
#[inline]
|
||||
fn as_mut(&mut self) -> &mut mint::$VT<N> {
|
||||
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<N> From<mint::$MV<N>> for MatrixMN<N, $NRows, $NCols>
|
||||
where N: Scalar,
|
||||
DefaultAllocator: Allocator<N, $NRows, $NCols> {
|
||||
#[inline]
|
||||
fn from(m: mint::$MV<N>) -> 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<N> Into<mint::$MV<N>> for MatrixMN<N, $NRows, $NCols>
|
||||
where N: Scalar,
|
||||
DefaultAllocator: Allocator<N, $NRows, $NCols> {
|
||||
#[inline]
|
||||
fn into(self) -> mint::$MV<N> {
|
||||
unsafe {
|
||||
let mut res: mint::$MV<N> = 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<MatrixSlice<'a, N, R, C, RStride, CStride>>
|
||||
for Matrix<N, R, C, ArrayStorage<N, R, C>>
|
||||
where
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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<N1, N2, D> SubsetOf<Point<N2, D>> for Point<N1, D>
|
||||
@ -80,57 +71,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "mint")]
|
||||
macro_rules! impl_from_into_mint_1D(
|
||||
($($NRows: ident => $PT:ident, $VT:ident [$SZ: expr]);* $(;)*) => {$(
|
||||
impl<N> From<mint::$PT<N>> for Point<N, $NRows>
|
||||
where N: Scalar {
|
||||
#[inline]
|
||||
fn from(p: mint::$PT<N>) -> Self {
|
||||
Self {
|
||||
coords: VectorN::from(mint::$VT::from(p)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> Into<mint::$PT<N>> for Point<N, $NRows>
|
||||
where N: Scalar {
|
||||
#[inline]
|
||||
fn into(self) -> mint::$PT<N> {
|
||||
let mint_vec: mint::$VT<N> = self.coords.into();
|
||||
mint::$PT::from(mint_vec)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> AsRef<mint::$PT<N>> for Point<N, $NRows>
|
||||
where N: Scalar {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &mint::$PT<N> {
|
||||
unsafe {
|
||||
&*(self.coords.data.ptr() as *const mint::$PT<N>)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> AsMut<mint::$PT<N>> for Point<N, $NRows>
|
||||
where N: Scalar {
|
||||
#[inline]
|
||||
fn as_mut(&mut self) -> &mut mint::$PT<N> {
|
||||
unsafe {
|
||||
&mut *(self.coords.data.ptr_mut() as *mut mint::$PT<N>)
|
||||
}
|
||||
}
|
||||
}
|
||||
)*}
|
||||
);
|
||||
|
||||
// Implement for points of dimension 2, 3.
|
||||
#[cfg(feature = "mint")]
|
||||
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>,
|
||||
|
@ -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<U3>
|
||||
* UnitQuaternion -> Matrix<U4> (homogeneous)
|
||||
*
|
||||
* mint::Quaternion <-> Quaternion
|
||||
* UnitQuaternion -> mint::Quaternion
|
||||
*
|
||||
* NOTE:
|
||||
* UnitQuaternion -> Quaternion is already provided by: Unit<T> -> T
|
||||
*/
|
||||
@ -206,41 +200,6 @@ impl<N1: RealField, N2: RealField + SupersetOf<N1>> SubsetOf<Matrix4<N2>> for Un
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "mint")]
|
||||
impl<N: Scalar> From<mint::Quaternion<N>> for Quaternion<N> {
|
||||
fn from(q: mint::Quaternion<N>) -> Self {
|
||||
Self::new(q.s, q.v.x, q.v.y, q.v.z)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "mint")]
|
||||
impl<N: Scalar> Into<mint::Quaternion<N>> for Quaternion<N> {
|
||||
fn into(self) -> mint::Quaternion<N> {
|
||||
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<N: Scalar + SimdValue> Into<mint::Quaternion<N>> for UnitQuaternion<N> {
|
||||
fn into(self) -> mint::Quaternion<N> {
|
||||
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<N: SimdRealField> From<UnitQuaternion<N>> for Matrix4<N>
|
||||
where
|
||||
N::Element: SimdRealField,
|
||||
|
@ -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<N: RealField> From<mint::EulerAngles<N, mint::IntraXYZ>> for Rotation3<N> {
|
||||
fn from(euler: mint::EulerAngles<N, mint::IntraXYZ>) -> Self {
|
||||
Self::from_euler_angles(euler.a, euler.b, euler.c)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: RealField> From<Rotation2<N>> for Matrix3<N> {
|
||||
#[inline]
|
||||
fn from(q: Rotation2<N>) -> Self {
|
||||
|
@ -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::*;
|
||||
|
10
src/third_party/alga/mod.rs
vendored
Normal file
10
src/third_party/alga/mod.rs
vendored
Normal file
@ -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;
|
54
src/third_party/glam/glam_isometry.rs
vendored
Normal file
54
src/third_party/glam/glam_isometry.rs
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
use crate::{Isometry2, Isometry3};
|
||||
use glam::{DMat3, DMat4, Mat3, Mat4};
|
||||
|
||||
impl From<Isometry2<f32>> for Mat3 {
|
||||
fn from(iso: Isometry2<f32>) -> Mat3 {
|
||||
iso.to_homogeneous().into()
|
||||
}
|
||||
}
|
||||
impl From<Isometry3<f32>> for Mat4 {
|
||||
fn from(iso: Isometry3<f32>) -> Mat4 {
|
||||
iso.to_homogeneous().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Isometry2<f64>> for DMat3 {
|
||||
fn from(iso: Isometry2<f64>) -> DMat3 {
|
||||
iso.to_homogeneous().into()
|
||||
}
|
||||
}
|
||||
impl From<Isometry3<f64>> for DMat4 {
|
||||
fn from(iso: Isometry3<f64>) -> 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<Mat3> for Isometry2<f32> {
|
||||
fn from(mat3: Mat3) -> Isometry2<f32> {
|
||||
crate::convert_unchecked(Matrix3::from(mat3))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Mat4> for Isometry3<f32> {
|
||||
fn from(mat4: Mat4) -> Isometry3<f32> {
|
||||
crate::convert_unchecked(Matrix4::from(mat4))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DMat3> for Isometry2<f64> {
|
||||
fn from(mat3: DMat3) -> Isometry2<f64> {
|
||||
crate::convert_unchecked(Matrix3::from(mat3))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DMat4> for Isometry3<f64> {
|
||||
fn from(mat4: DMat4) -> Isometry3<f64> {
|
||||
crate::convert_unchecked(Matrix4::from(mat4))
|
||||
}
|
||||
}
|
||||
}
|
210
src/third_party/glam/glam_matrix.rs
vendored
Normal file
210
src/third_party/glam/glam_matrix.rs
vendored
Normal file
@ -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<S> From<Vector<$N, U2, S>> 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<S> From<Vector<$N, U3, S>> 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<S> From<Vector<$N, U4, S>> 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<Vec3A> for Vector3<f32> {
|
||||
#[inline]
|
||||
fn from(e: Vec3A) -> Vector3<f32> {
|
||||
(*e.as_ref()).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> From<Vector<f32, U3, S>> for Vec3A
|
||||
where
|
||||
S: Storage<f32, U3>,
|
||||
{
|
||||
#[inline]
|
||||
fn from(e: Vector<f32, U3, S>) -> Vec3A {
|
||||
Vec3A::new(e[0], e[1], e[2])
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Mat2> for Matrix2<f32> {
|
||||
#[inline]
|
||||
fn from(e: Mat2) -> Matrix2<f32> {
|
||||
e.to_cols_array_2d().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> From<Matrix<f32, U2, U2, S>> for Mat2
|
||||
where
|
||||
S: Storage<f32, U2, U2>,
|
||||
{
|
||||
#[inline]
|
||||
fn from(e: Matrix<f32, U2, U2, S>) -> Mat2 {
|
||||
Mat2::from_cols(
|
||||
Vec2::new(e[(0, 0)], e[(1, 0)]),
|
||||
Vec2::new(e[(0, 1)], e[(1, 1)]),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Mat3> for Matrix3<f32> {
|
||||
#[inline]
|
||||
fn from(e: Mat3) -> Matrix3<f32> {
|
||||
e.to_cols_array_2d().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> From<Matrix<f32, U3, U3, S>> for Mat3
|
||||
where
|
||||
S: Storage<f32, U3, U3>,
|
||||
{
|
||||
#[inline]
|
||||
fn from(e: Matrix<f32, U3, U3, S>) -> 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<Mat4> for Matrix4<f32> {
|
||||
#[inline]
|
||||
fn from(e: Mat4) -> Matrix4<f32> {
|
||||
e.to_cols_array_2d().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> From<Matrix<f32, U4, U4, S>> for Mat4
|
||||
where
|
||||
S: Storage<f32, U4, U4>,
|
||||
{
|
||||
#[inline]
|
||||
fn from(e: Matrix<f32, U4, U4, S>) -> 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<DMat2> for Matrix2<f64> {
|
||||
#[inline]
|
||||
fn from(e: DMat2) -> Matrix2<f64> {
|
||||
e.to_cols_array_2d().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> From<Matrix<f64, U2, U2, S>> for DMat2
|
||||
where
|
||||
S: Storage<f64, U2, U2>,
|
||||
{
|
||||
#[inline]
|
||||
fn from(e: Matrix<f64, U2, U2, S>) -> DMat2 {
|
||||
DMat2::from_cols(
|
||||
DVec2::new(e[(0, 0)], e[(1, 0)]),
|
||||
DVec2::new(e[(0, 1)], e[(1, 1)]),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DMat3> for Matrix3<f64> {
|
||||
#[inline]
|
||||
fn from(e: DMat3) -> Matrix3<f64> {
|
||||
e.to_cols_array_2d().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> From<Matrix<f64, U3, U3, S>> for DMat3
|
||||
where
|
||||
S: Storage<f64, U3, U3>,
|
||||
{
|
||||
#[inline]
|
||||
fn from(e: Matrix<f64, U3, U3, S>) -> 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<DMat4> for Matrix4<f64> {
|
||||
#[inline]
|
||||
fn from(e: DMat4) -> Matrix4<f64> {
|
||||
e.to_cols_array_2d().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> From<Matrix<f64, U4, U4, S>> for DMat4
|
||||
where
|
||||
S: Storage<f64, U4, U4>,
|
||||
{
|
||||
#[inline]
|
||||
fn from(e: Matrix<f64, U4, U4, S>) -> 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)]),
|
||||
)
|
||||
}
|
||||
}
|
71
src/third_party/glam/glam_point.rs
vendored
Normal file
71
src/third_party/glam/glam_point.rs
vendored
Normal file
@ -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<Point2<$N>> 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<Point3<$N>> 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<Point4<$N>> 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<Vec3A> for Point3<f32> {
|
||||
#[inline]
|
||||
fn from(e: Vec3A) -> Point3<f32> {
|
||||
(*e.as_ref()).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Point3<f32>> for Vec3A {
|
||||
#[inline]
|
||||
fn from(e: Point3<f32>) -> Vec3A {
|
||||
Vec3A::new(e[0], e[1], e[2])
|
||||
}
|
||||
}
|
64
src/third_party/glam/glam_quaternion.rs
vendored
Normal file
64
src/third_party/glam/glam_quaternion.rs
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
use crate::{Quaternion, UnitQuaternion};
|
||||
use glam::{DQuat, Quat};
|
||||
|
||||
impl From<Quat> for Quaternion<f32> {
|
||||
#[inline]
|
||||
fn from(e: Quat) -> Quaternion<f32> {
|
||||
Quaternion::new(e.w, e.x, e.y, e.z)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Quaternion<f32>> for Quat {
|
||||
#[inline]
|
||||
fn from(e: Quaternion<f32>) -> Quat {
|
||||
Quat::from_xyzw(e.i, e.j, e.k, e.w)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UnitQuaternion<f32>> for Quat {
|
||||
#[inline]
|
||||
fn from(e: UnitQuaternion<f32>) -> Quat {
|
||||
Quat::from_xyzw(e.i, e.j, e.k, e.w)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DQuat> for Quaternion<f64> {
|
||||
#[inline]
|
||||
fn from(e: DQuat) -> Quaternion<f64> {
|
||||
Quaternion::new(e.w, e.x, e.y, e.z)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Quaternion<f64>> for DQuat {
|
||||
#[inline]
|
||||
fn from(e: Quaternion<f64>) -> DQuat {
|
||||
DQuat::from_xyzw(e.i, e.j, e.k, e.w)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UnitQuaternion<f64>> for DQuat {
|
||||
#[inline]
|
||||
fn from(e: UnitQuaternion<f64>) -> 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<Quat> for UnitQuaternion<f32> {
|
||||
#[inline]
|
||||
fn from(e: Quat) -> UnitQuaternion<f32> {
|
||||
UnitQuaternion::new_unchecked(Quaternion::from(e))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DQuat> for UnitQuaternion<f64> {
|
||||
#[inline]
|
||||
fn from(e: DQuat) -> UnitQuaternion<f64> {
|
||||
UnitQuaternion::new_unchecked(Quaternion::from(e))
|
||||
}
|
||||
}
|
||||
}
|
4
src/third_party/glam/mod.rs
vendored
Normal file
4
src/third_party/glam/mod.rs
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
mod glam_isometry;
|
||||
mod glam_matrix;
|
||||
mod glam_point;
|
||||
mod glam_quaternion;
|
117
src/third_party/mint/mint_matrix.rs
vendored
Normal file
117
src/third_party/mint/mint_matrix.rs
vendored
Normal file
@ -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<N> From<mint::$VT<N>> for MatrixMN<N, $NRows, U1>
|
||||
where N: Scalar,
|
||||
DefaultAllocator: Allocator<N, $NRows, U1> {
|
||||
#[inline]
|
||||
fn from(v: mint::$VT<N>) -> 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<N, S> Into<mint::$VT<N>> for Matrix<N, $NRows, U1, S>
|
||||
where N: Scalar,
|
||||
S: ContiguousStorage<N, $NRows, U1> {
|
||||
#[inline]
|
||||
fn into(self) -> mint::$VT<N> {
|
||||
unsafe {
|
||||
let mut res: mint::$VT<N> = mem::MaybeUninit::uninit().assume_init();
|
||||
ptr::copy_nonoverlapping(self.data.ptr(), &mut res.x, $SZ);
|
||||
res
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N, S> AsRef<mint::$VT<N>> for Matrix<N, $NRows, U1, S>
|
||||
where N: Scalar,
|
||||
S: ContiguousStorage<N, $NRows, U1> {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &mint::$VT<N> {
|
||||
unsafe {
|
||||
mem::transmute(self.data.ptr())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N, S> AsMut<mint::$VT<N>> for Matrix<N, $NRows, U1, S>
|
||||
where N: Scalar,
|
||||
S: ContiguousStorageMut<N, $NRows, U1> {
|
||||
#[inline]
|
||||
fn as_mut(&mut self) -> &mut mint::$VT<N> {
|
||||
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<N> From<mint::$MV<N>> for MatrixMN<N, $NRows, $NCols>
|
||||
where N: Scalar,
|
||||
DefaultAllocator: Allocator<N, $NRows, $NCols> {
|
||||
#[inline]
|
||||
fn from(m: mint::$MV<N>) -> 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<N> Into<mint::$MV<N>> for MatrixMN<N, $NRows, $NCols>
|
||||
where N: Scalar,
|
||||
DefaultAllocator: Allocator<N, $NRows, $NCols> {
|
||||
#[inline]
|
||||
fn into(self) -> mint::$MV<N> {
|
||||
unsafe {
|
||||
let mut res: mint::$MV<N> = 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];
|
||||
);
|
52
src/third_party/mint/mint_point.rs
vendored
Normal file
52
src/third_party/mint/mint_point.rs
vendored
Normal file
@ -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<N> From<mint::$PT<N>> for Point<N, $NRows>
|
||||
where N: Scalar {
|
||||
#[inline]
|
||||
fn from(p: mint::$PT<N>) -> Self {
|
||||
Self {
|
||||
coords: VectorN::from(mint::$VT::from(p)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> Into<mint::$PT<N>> for Point<N, $NRows>
|
||||
where N: Scalar {
|
||||
#[inline]
|
||||
fn into(self) -> mint::$PT<N> {
|
||||
let mint_vec: mint::$VT<N> = self.coords.into();
|
||||
mint::$PT::from(mint_vec)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> AsRef<mint::$PT<N>> for Point<N, $NRows>
|
||||
where N: Scalar {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &mint::$PT<N> {
|
||||
unsafe {
|
||||
&*(self.coords.data.ptr() as *const mint::$PT<N>)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> AsMut<mint::$PT<N>> for Point<N, $NRows>
|
||||
where N: Scalar {
|
||||
#[inline]
|
||||
fn as_mut(&mut self) -> &mut mint::$PT<N> {
|
||||
unsafe {
|
||||
&mut *(self.coords.data.ptr_mut() as *mut mint::$PT<N>)
|
||||
}
|
||||
}
|
||||
}
|
||||
)*}
|
||||
);
|
||||
|
||||
// Implement for points of dimension 2, 3.
|
||||
impl_from_into_mint_1D!(
|
||||
U2 => Point2, Vector2[2];
|
||||
U3 => Point3, Vector3[3];
|
||||
);
|
33
src/third_party/mint/mint_quaternion.rs
vendored
Normal file
33
src/third_party/mint/mint_quaternion.rs
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
use crate::{Quaternion, Scalar, SimdValue, UnitQuaternion};
|
||||
|
||||
impl<N: Scalar> From<mint::Quaternion<N>> for Quaternion<N> {
|
||||
fn from(q: mint::Quaternion<N>) -> Self {
|
||||
Self::new(q.s, q.v.x, q.v.y, q.v.z)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Scalar> Into<mint::Quaternion<N>> for Quaternion<N> {
|
||||
fn into(self) -> mint::Quaternion<N> {
|
||||
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<N: Scalar + SimdValue> Into<mint::Quaternion<N>> for UnitQuaternion<N> {
|
||||
fn into(self) -> mint::Quaternion<N> {
|
||||
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(),
|
||||
}
|
||||
}
|
||||
}
|
7
src/third_party/mint/mint_rotation.rs
vendored
Normal file
7
src/third_party/mint/mint_rotation.rs
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
use crate::{RealField, Rotation3};
|
||||
|
||||
impl<N: RealField> From<mint::EulerAngles<N, mint::IntraXYZ>> for Rotation3<N> {
|
||||
fn from(euler: mint::EulerAngles<N, mint::IntraXYZ>) -> Self {
|
||||
Self::from_euler_angles(euler.a, euler.b, euler.c)
|
||||
}
|
||||
}
|
4
src/third_party/mint/mod.rs
vendored
Normal file
4
src/third_party/mint/mod.rs
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
mod mint_matrix;
|
||||
mod mint_point;
|
||||
mod mint_quaternion;
|
||||
mod mint_rotation;
|
6
src/third_party/mod.rs
vendored
Normal file
6
src/third_party/mod.rs
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
#[cfg(feature = "alga")]
|
||||
mod alga;
|
||||
#[cfg(feature = "glam")]
|
||||
mod glam;
|
||||
#[cfg(feature = "mint")]
|
||||
mod mint;
|
Loading…
Reference in New Issue
Block a user