Repository: bitshifter/glam-rs
Pull request #352 (2022-10-06 04:39:15)

Add missing `from_mat3a` methods


Patch:
diff --git a/codegen/templates/affine.rs.tera b/codegen/templates/affine.rs.tera
index a2985cc..5206448 100644
--- a/codegen/templates/affine.rs.tera
+++ b/codegen/templates/affine.rs.tera
@@ -270,6 +270,18 @@ impl {{ self_t }} {
         }
     }
 
+{% if scalar_t == "f32" %}
+    /// The given `Mat3A` must be an affine transform,
+    #[inline]
+    pub fn from_mat3a(m: Mat3A) -> Self {
+        use crate::swizzles::Vec3Swizzles;
+        Self {
+            matrix2: Mat2::from_cols(m.x_axis.xy(), m.y_axis.xy()),
+            translation: m.z_axis.xy(),
+        }
+    }
+{% endif %}
+
     /// Transforms the given 2D point, applying shear, scale, rotation and translation.
     #[inline]
     pub fn transform_point2(&self, rhs: {{ vec2_t }}) -> {{ vec2_t }} {
diff --git a/codegen/templates/mat.rs.tera b/codegen/templates/mat.rs.tera
index 2fb7856..8161c64 100644
--- a/codegen/templates/mat.rs.tera
+++ b/codegen/templates/mat.rs.tera
@@ -18,11 +18,9 @@
     {% set affine3_t = "Affine3A" %}
     {% set vec2_t = "Vec2" %}
     {% set vec3_t = "Vec3" %}
-    {% set vec3a_t = "Vec3A" %}
     {% set vec4_t = "Vec4" %}
     {% set mat2_t = "Mat2" %}
     {% set mat3_t = "Mat3" %}
-    {% set mat3a_t = "Mat3A" %}
     {% set mat4_t = "Mat4" %}
 {% elif scalar_t == "f64" %}
     {% set vecn_t = "DVec" ~ dim %}
@@ -66,19 +64,22 @@ use crate::{
 {% endif %}
 {% if dim == 2 %}
     {{ mat3_t }}, {{ vec2_t }},
+    {% if scalar_t == "f32" %}
+        Mat3A,
+    {% endif %}
 {% elif dim == 3 %}
     EulerRot,
     {{ mat2_t }}, {{ mat4_t }}, {{ quat_t }}, {{ vec2_t }}, {{ col_t }},
     {% if is_align %}
         {{ mat3_t }}, {{ vec3_t }},
     {% elif scalar_t == "f32" %}
-        {{ mat3a_t }}, {{ vec3a_t }},
+        Mat3A, Vec3A,
     {% endif %}
 {% elif dim == 4 %}
     EulerRot,
     {{ mat3_t }}, {{ quat_t }}, {{ vec3_t }}, {{ col_t }},
     {% if scalar_t == "f32" %}
-        {{ vec3a_t }},
+        Mat3A, Vec3A,
     {% endif %}
 {% endif %}
 {% if self_t == "Mat4" %}
@@ -407,6 +408,16 @@ impl {{ self_t }} {
     pub fn from_mat3(m: {{ mat3_t }}) -> Self {
         Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
     }
+
+{% if scalar_t == "f32" %}
+    /// Creates a {{ nxn }} matrix from a 3x3 matrix, discarding the 2nd row and column.
+    #[inline]
+    pub fn from_mat3a(m: Mat3A) -> Self {
+        {# TODO: SIMD optimise #}
+        Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
+    }
+{% endif %}
+
 {% elif dim == 3 %}
     /// Creates a 3x3 matrix from a 4x4 matrix, discarding the 4th row and column.
     pub fn from_mat4(m: {{ mat4_t }}) -> Self {
@@ -717,6 +728,23 @@ impl {{ self_t }} {
         )
     }
 
+{% if scalar_t == "f32" %}
+    /// Creates an affine transformation matrix from the given 3x3 linear transformation
+    /// matrix.
+    ///
+    /// The resulting matrix can be used to transform 3D points and vectors. See
+    /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
+    #[inline]
+    pub fn from_mat3a(m: Mat3A) -> Self {
+        Self::from_cols(
+            Vec4::from((m.x_axis, 0.0)),
+            Vec4::from((m.y_axis, 0.0)),
+            Vec4::from((m.z_axis, 0.0)),
+            Vec4::W,
+        )
+    }
+{% endif %}
+
     /// Creates an affine transformation matrix from the given 3D `translation`.
     ///
     /// The resulting matrix can be used to transform 3D points and vectors. See
diff --git a/codegen/templates/quat.rs.tera b/codegen/templates/quat.rs.tera
index 1faa6ba..f6c607a 100644
--- a/codegen/templates/quat.rs.tera
+++ b/codegen/templates/quat.rs.tera
@@ -33,7 +33,7 @@ use crate::{
     FloatEx,
     euler::{EulerFromQuaternion, EulerRot, EulerToQuaternion},
     {% if scalar_t == "f32" %}
-        DQuat, Mat3, Mat4, Vec2, Vec3, Vec3A, Vec4,
+        DQuat, Mat3, Mat3A, Mat4, Vec2, Vec3, Vec3A, Vec4,
     {% elif scalar_t == "f64" %}
         DMat3, DMat4, DVec2, DVec3, DVec4, Quat,
     {% endif %}
@@ -340,6 +340,18 @@ impl {{ self_t }} {
         )
     }
 
+{% if scalar_t == "f32" %}
+    /// Creates a quaternion from a 3x3 SIMD aligned rotation matrix.
+    #[inline]
+    pub fn from_mat3a(mat: &Mat3A) -> Self {
+        Self::from_rotation_axes(
+            mat.x_axis.into(),
+            mat.y_axis.into(),
+            mat.z_axis.into(),
+        )
+    }
+{% endif %}
+
     /// Creates a quaternion from a 3x3 rotation matrix inside a homogeneous 4x4 matrix.
     #[inline]
     pub fn from_mat4(mat: &{{ mat4_t }}) -> Self {
diff --git a/codegen/templates/vec.rs.tera b/codegen/templates/vec.rs.tera
index 425262e..25e4386 100644
--- a/codegen/templates/vec.rs.tera
+++ b/codegen/templates/vec.rs.tera
@@ -430,7 +430,7 @@ impl {{ self_t }} {
         {% endif %}
     }
 
-    /// Returns a vector where every component is the dot product of `self` and `rhs` 
+    /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
         {% if is_sse2 %}
diff --git a/src/f32/affine2.rs b/src/f32/affine2.rs
index 5a43d7e..2befa9a 100644
--- a/src/f32/affine2.rs
+++ b/src/f32/affine2.rs
@@ -196,6 +196,16 @@ impl Affine2 {
         }
     }
 
+    /// The given `Mat3A` must be an affine transform,
+    #[inline]
+    pub fn from_mat3a(m: Mat3A) -> Self {
+        use crate::swizzles::Vec3Swizzles;
+        Self {
+            matrix2: Mat2::from_cols(m.x_axis.xy(), m.y_axis.xy()),
+            translation: m.z_axis.xy(),
+        }
+    }
+
     /// Transforms the given 2D point, applying shear, scale, rotation and translation.
     #[inline]
     pub fn transform_point2(&self, rhs: Vec2) -> Vec2 {
diff --git a/src/f32/coresimd/mat2.rs b/src/f32/coresimd/mat2.rs
index 276816f..200aa52 100644
--- a/src/f32/coresimd/mat2.rs
+++ b/src/f32/coresimd/mat2.rs
@@ -1,6 +1,6 @@
 // Generated from mat.rs.tera template. Edit the template, not the generated file.
 
-use crate::{swizzles::*, DMat2, Mat3, Vec2};
+use crate::{swizzles::*, DMat2, Mat3, Mat3A, Vec2};
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
 use core::iter::{Product, Sum};
@@ -103,6 +103,12 @@ impl Mat2 {
         Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
     }
 
+    /// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column.
+    #[inline]
+    pub fn from_mat3a(m: Mat3A) -> Self {
+        Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
+    }
+
     /// Creates a 2x2 matrix from the first 4 values in `slice`.
     ///
     /// # Panics
diff --git a/src/f32/coresimd/mat4.rs b/src/f32/coresimd/mat4.rs
index d8a86f4..26239ba 100644
--- a/src/f32/coresimd/mat4.rs
+++ b/src/f32/coresimd/mat4.rs
@@ -1,6 +1,6 @@
 // Generated from mat.rs.tera template. Edit the template, not the generated file.
 
-use crate::{coresimd::*, swizzles::*, DMat4, EulerRot, Mat3, Quat, Vec3, Vec3A, Vec4};
+use crate::{coresimd::*, swizzles::*, DMat4, EulerRot, Mat3, Mat3A, Quat, Vec3, Vec3A, Vec4};
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
 use core::iter::{Product, Sum};
@@ -287,6 +287,21 @@ impl Mat4 {
         )
     }
 
+    /// Creates an affine transformation matrix from the given 3x3 linear transformation
+    /// matrix.
+    ///
+    /// The resulting matrix can be used to transform 3D points and vectors. See
+    /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
+    #[inline]
+    pub fn from_mat3a(m: Mat3A) -> Self {
+        Self::from_cols(
+            Vec4::from((m.x_axis, 0.0)),
+            Vec4::from((m.y_axis, 0.0)),
+            Vec4::from((m.z_axis, 0.0)),
+            Vec4::W,
+        )
+    }
+
     /// Creates an affine transformation matrix from the given 3D `translation`.
     ///
     /// The resulting matrix can be used to transform 3D points and vectors. See
diff --git a/src/f32/coresimd/quat.rs b/src/f32/coresimd/quat.rs
index 9dfbb67..21aa519 100644
--- a/src/f32/coresimd/quat.rs
+++ b/src/f32/coresimd/quat.rs
@@ -3,7 +3,7 @@
 use crate::{
     coresimd::*,
     euler::{EulerFromQuaternion, EulerRot, EulerToQuaternion},
-    DQuat, FloatEx, Mat3, Mat4, Vec2, Vec3, Vec3A, Vec4,
+    DQuat, FloatEx, Mat3, Mat3A, Mat4, Vec2, Vec3, Vec3A, Vec4,
 };
 
 #[cfg(feature = "libm")]
@@ -233,6 +233,12 @@ impl Quat {
         Self::from_rotation_axes(mat.x_axis, mat.y_axis, mat.z_axis)
     }
 
+    /// Creates a quaternion from a 3x3 SIMD aligned rotation matrix.
+    #[inline]
+    pub fn from_mat3a(mat: &Mat3A) -> Self {
+        Self::from_rotation_axes(mat.x_axis.into(), mat.y_axis.into(), mat.z_axis.into())
+    }
+
     /// Creates a quaternion from a 3x3 rotation matrix inside a homogeneous 4x4 matrix.
     #[inline]
     pub fn from_mat4(mat: &Mat4) -> Self {
diff --git a/src/f32/coresimd/vec3a.rs b/src/f32/coresimd/vec3a.rs
index 71f5c64..adaceb6 100644
--- a/src/f32/coresimd/vec3a.rs
+++ b/src/f32/coresimd/vec3a.rs
@@ -148,7 +148,7 @@ impl Vec3A {
         dot3(self.0, rhs.0)
     }
 
-    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
         Self(unsafe { dot3_into_f32x4(self.0, rhs.0) })
diff --git a/src/f32/coresimd/vec4.rs b/src/f32/coresimd/vec4.rs
index fa92f93..61b4903 100644
--- a/src/f32/coresimd/vec4.rs
+++ b/src/f32/coresimd/vec4.rs
@@ -141,7 +141,7 @@ impl Vec4 {
         dot4(self.0, rhs.0)
     }
 
-    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
         Self(unsafe { dot4_into_f32x4(self.0, rhs.0) })
diff --git a/src/f32/scalar/mat2.rs b/src/f32/scalar/mat2.rs
index 03d082e..9c4c253 100644
--- a/src/f32/scalar/mat2.rs
+++ b/src/f32/scalar/mat2.rs
@@ -1,6 +1,6 @@
 // Generated from mat.rs.tera template. Edit the template, not the generated file.
 
-use crate::{swizzles::*, DMat2, Mat3, Vec2};
+use crate::{swizzles::*, DMat2, Mat3, Mat3A, Vec2};
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
 use core::iter::{Product, Sum};
@@ -112,6 +112,12 @@ impl Mat2 {
         Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
     }
 
+    /// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column.
+    #[inline]
+    pub fn from_mat3a(m: Mat3A) -> Self {
+        Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
+    }
+
     /// Creates a 2x2 matrix from the first 4 values in `slice`.
     ///
     /// # Panics
diff --git a/src/f32/scalar/mat4.rs b/src/f32/scalar/mat4.rs
index 580eb27..78d7a52 100644
--- a/src/f32/scalar/mat4.rs
+++ b/src/f32/scalar/mat4.rs
@@ -1,6 +1,6 @@
 // Generated from mat.rs.tera template. Edit the template, not the generated file.
 
-use crate::{swizzles::*, DMat4, EulerRot, Mat3, Quat, Vec3, Vec3A, Vec4};
+use crate::{swizzles::*, DMat4, EulerRot, Mat3, Mat3A, Quat, Vec3, Vec3A, Vec4};
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
 use core::iter::{Product, Sum};
@@ -300,6 +300,21 @@ impl Mat4 {
         )
     }
 
+    /// Creates an affine transformation matrix from the given 3x3 linear transformation
+    /// matrix.
+    ///
+    /// The resulting matrix can be used to transform 3D points and vectors. See
+    /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
+    #[inline]
+    pub fn from_mat3a(m: Mat3A) -> Self {
+        Self::from_cols(
+            Vec4::from((m.x_axis, 0.0)),
+            Vec4::from((m.y_axis, 0.0)),
+            Vec4::from((m.z_axis, 0.0)),
+            Vec4::W,
+        )
+    }
+
     /// Creates an affine transformation matrix from the given 3D `translation`.
     ///
     /// The resulting matrix can be used to transform 3D points and vectors. See
diff --git a/src/f32/scalar/quat.rs b/src/f32/scalar/quat.rs
index bd7b66d..0b72e8f 100644
--- a/src/f32/scalar/quat.rs
+++ b/src/f32/scalar/quat.rs
@@ -2,7 +2,7 @@
 
 use crate::{
     euler::{EulerFromQuaternion, EulerRot, EulerToQuaternion},
-    DQuat, FloatEx, Mat3, Mat4, Vec2, Vec3, Vec3A, Vec4,
+    DQuat, FloatEx, Mat3, Mat3A, Mat4, Vec2, Vec3, Vec3A, Vec4,
 };
 
 #[cfg(feature = "libm")]
@@ -243,6 +243,12 @@ impl Quat {
         Self::from_rotation_axes(mat.x_axis, mat.y_axis, mat.z_axis)
     }
 
+    /// Creates a quaternion from a 3x3 SIMD aligned rotation matrix.
+    #[inline]
+    pub fn from_mat3a(mat: &Mat3A) -> Self {
+        Self::from_rotation_axes(mat.x_axis.into(), mat.y_axis.into(), mat.z_axis.into())
+    }
+
     /// Creates a quaternion from a 3x3 rotation matrix inside a homogeneous 4x4 matrix.
     #[inline]
     pub fn from_mat4(mat: &Mat4) -> Self {
diff --git a/src/f32/scalar/vec3a.rs b/src/f32/scalar/vec3a.rs
index 26b82b6..88a3c13 100644
--- a/src/f32/scalar/vec3a.rs
+++ b/src/f32/scalar/vec3a.rs
@@ -159,7 +159,7 @@ impl Vec3A {
         (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z)
     }
 
-    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
         Self::splat(self.dot(rhs))
diff --git a/src/f32/scalar/vec4.rs b/src/f32/scalar/vec4.rs
index 6abcccd..cf791cf 100644
--- a/src/f32/scalar/vec4.rs
+++ b/src/f32/scalar/vec4.rs
@@ -162,7 +162,7 @@ impl Vec4 {
         (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z) + (self.w * rhs.w)
     }
 
-    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
         Self::splat(self.dot(rhs))
diff --git a/src/f32/sse2/mat2.rs b/src/f32/sse2/mat2.rs
index 311448b..0222bdd 100644
--- a/src/f32/sse2/mat2.rs
+++ b/src/f32/sse2/mat2.rs
@@ -1,6 +1,6 @@
 // Generated from mat.rs.tera template. Edit the template, not the generated file.
 
-use crate::{swizzles::*, DMat2, Mat3, Vec2};
+use crate::{swizzles::*, DMat2, Mat3, Mat3A, Vec2};
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
 use core::iter::{Product, Sum};
@@ -121,6 +121,12 @@ impl Mat2 {
         Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
     }
 
+    /// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column.
+    #[inline]
+    pub fn from_mat3a(m: Mat3A) -> Self {
+        Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
+    }
+
     /// Creates a 2x2 matrix from the first 4 values in `slice`.
     ///
     /// # Panics
diff --git a/src/f32/sse2/mat4.rs b/src/f32/sse2/mat4.rs
index 24e16ad..aa69493 100644
--- a/src/f32/sse2/mat4.rs
+++ b/src/f32/sse2/mat4.rs
@@ -1,6 +1,6 @@
 // Generated from mat.rs.tera template. Edit the template, not the generated file.
 
-use crate::{sse2::*, swizzles::*, DMat4, EulerRot, Mat3, Quat, Vec3, Vec3A, Vec4};
+use crate::{sse2::*, swizzles::*, DMat4, EulerRot, Mat3, Mat3A, Quat, Vec3, Vec3A, Vec4};
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
 use core::iter::{Product, Sum};
@@ -290,6 +290,21 @@ impl Mat4 {
         )
     }
 
+    /// Creates an affine transformation matrix from the given 3x3 linear transformation
+    /// matrix.
+    ///
+    /// The resulting matrix can be used to transform 3D points and vectors. See
+    /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
+    #[inline]
+    pub fn from_mat3a(m: Mat3A) -> Self {
+        Self::from_cols(
+            Vec4::from((m.x_axis, 0.0)),
+            Vec4::from((m.y_axis, 0.0)),
+            Vec4::from((m.z_axis, 0.0)),
+            Vec4::W,
+        )
+    }
+
     /// Creates an affine transformation matrix from the given 3D `translation`.
     ///
     /// The resulting matrix can be used to transform 3D points and vectors. See
diff --git a/src/f32/sse2/quat.rs b/src/f32/sse2/quat.rs
index b992a80..f7fbd8d 100644
--- a/src/f32/sse2/quat.rs
+++ b/src/f32/sse2/quat.rs
@@ -3,7 +3,7 @@
 use crate::{
     euler::{EulerFromQuaternion, EulerRot, EulerToQuaternion},
     sse2::*,
-    DQuat, FloatEx, Mat3, Mat4, Vec2, Vec3, Vec3A, Vec4,
+    DQuat, FloatEx, Mat3, Mat3A, Mat4, Vec2, Vec3, Vec3A, Vec4,
 };
 
 #[cfg(feature = "libm")]
@@ -240,6 +240,12 @@ impl Quat {
         Self::from_rotation_axes(mat.x_axis, mat.y_axis, mat.z_axis)
     }
 
+    /// Creates a quaternion from a 3x3 SIMD aligned rotation matrix.
+    #[inline]
+    pub fn from_mat3a(mat: &Mat3A) -> Self {
+        Self::from_rotation_axes(mat.x_axis.into(), mat.y_axis.into(), mat.z_axis.into())
+    }
+
     /// Creates a quaternion from a 3x3 rotation matrix inside a homogeneous 4x4 matrix.
     #[inline]
     pub fn from_mat4(mat: &Mat4) -> Self {
diff --git a/src/f32/sse2/vec3a.rs b/src/f32/sse2/vec3a.rs
index 56b8c8d..7fa8a6a 100644
--- a/src/f32/sse2/vec3a.rs
+++ b/src/f32/sse2/vec3a.rs
@@ -160,7 +160,7 @@ impl Vec3A {
         unsafe { dot3(self.0, rhs.0) }
     }
 
-    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
         Self(unsafe { dot3_into_m128(self.0, rhs.0) })
diff --git a/src/f32/sse2/vec4.rs b/src/f32/sse2/vec4.rs
index f72e027..0e0882c 100644
--- a/src/f32/sse2/vec4.rs
+++ b/src/f32/sse2/vec4.rs
@@ -153,7 +153,7 @@ impl Vec4 {
         unsafe { dot4(self.0, rhs.0) }
     }
 
-    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
         Self(unsafe { dot4_into_m128(self.0, rhs.0) })
diff --git a/src/f32/vec2.rs b/src/f32/vec2.rs
index 13181e1..16bd17d 100644
--- a/src/f32/vec2.rs
+++ b/src/f32/vec2.rs
@@ -125,7 +125,7 @@ impl Vec2 {
         (self.x * rhs.x) + (self.y * rhs.y)
     }
 
-    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
         Self::splat(self.dot(rhs))
diff --git a/src/f32/vec3.rs b/src/f32/vec3.rs
index 5606263..b049ed8 100644
--- a/src/f32/vec3.rs
+++ b/src/f32/vec3.rs
@@ -153,7 +153,7 @@ impl Vec3 {
         (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z)
     }
 
-    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
         Self::splat(self.dot(rhs))
diff --git a/src/f32/wasm32/mat2.rs b/src/f32/wasm32/mat2.rs
index 7869ff5..b96ef73 100644
--- a/src/f32/wasm32/mat2.rs
+++ b/src/f32/wasm32/mat2.rs
@@ -1,6 +1,6 @@
 // Generated from mat.rs.tera template. Edit the template, not the generated file.
 
-use crate::{swizzles::*, DMat2, Mat3, Vec2};
+use crate::{swizzles::*, DMat2, Mat3, Mat3A, Vec2};
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
 use core::iter::{Product, Sum};
@@ -103,6 +103,12 @@ impl Mat2 {
         Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
     }
 
+    /// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column.
+    #[inline]
+    pub fn from_mat3a(m: Mat3A) -> Self {
+        Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
+    }
+
     /// Creates a 2x2 matrix from the first 4 values in `slice`.
     ///
     /// # Panics
diff --git a/src/f32/wasm32/mat4.rs b/src/f32/wasm32/mat4.rs
index 433e893..bdaeb29 100644
--- a/src/f32/wasm32/mat4.rs
+++ b/src/f32/wasm32/mat4.rs
@@ -1,6 +1,6 @@
 // Generated from mat.rs.tera template. Edit the template, not the generated file.
 
-use crate::{swizzles::*, wasm32::*, DMat4, EulerRot, Mat3, Quat, Vec3, Vec3A, Vec4};
+use crate::{swizzles::*, wasm32::*, DMat4, EulerRot, Mat3, Mat3A, Quat, Vec3, Vec3A, Vec4};
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
 use core::iter::{Product, Sum};
@@ -287,6 +287,21 @@ impl Mat4 {
         )
     }
 
+    /// Creates an affine transformation matrix from the given 3x3 linear transformation
+    /// matrix.
+    ///
+    /// The resulting matrix can be used to transform 3D points and vectors. See
+    /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
+    #[inline]
+    pub fn from_mat3a(m: Mat3A) -> Self {
+        Self::from_cols(
+            Vec4::from((m.x_axis, 0.0)),
+            Vec4::from((m.y_axis, 0.0)),
+            Vec4::from((m.z_axis, 0.0)),
+            Vec4::W,
+        )
+    }
+
     /// Creates an affine transformation matrix from the given 3D `translation`.
     ///
     /// The resulting matrix can be used to transform 3D points and vectors. See
diff --git a/src/f32/wasm32/quat.rs b/src/f32/wasm32/quat.rs
index d1aa475..75f9c16 100644
--- a/src/f32/wasm32/quat.rs
+++ b/src/f32/wasm32/quat.rs
@@ -3,7 +3,7 @@
 use crate::{
     euler::{EulerFromQuaternion, EulerRot, EulerToQuaternion},
     wasm32::*,
-    DQuat, FloatEx, Mat3, Mat4, Vec2, Vec3, Vec3A, Vec4,
+    DQuat, FloatEx, Mat3, Mat3A, Mat4, Vec2, Vec3, Vec3A, Vec4,
 };
 
 #[cfg(feature = "libm")]
@@ -233,6 +233,12 @@ impl Quat {
         Self::from_rotation_axes(mat.x_axis, mat.y_axis, mat.z_axis)
     }
 
+    /// Creates a quaternion from a 3x3 SIMD aligned rotation matrix.
+    #[inline]
+    pub fn from_mat3a(mat: &Mat3A) -> Self {
+        Self::from_rotation_axes(mat.x_axis.into(), mat.y_axis.into(), mat.z_axis.into())
+    }
+
     /// Creates a quaternion from a 3x3 rotation matrix inside a homogeneous 4x4 matrix.
     #[inline]
     pub fn from_mat4(mat: &Mat4) -> Self {
diff --git a/src/f32/wasm32/vec3a.rs b/src/f32/wasm32/vec3a.rs
index 08a6269..85b3fe4 100644
--- a/src/f32/wasm32/vec3a.rs
+++ b/src/f32/wasm32/vec3a.rs
@@ -152,7 +152,7 @@ impl Vec3A {
         dot3(self.0, rhs.0)
     }
 
-    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
         Self(unsafe { dot3_into_v128(self.0, rhs.0) })
diff --git a/src/f32/wasm32/vec4.rs b/src/f32/wasm32/vec4.rs
index de16f66..ab53d7a 100644
--- a/src/f32/wasm32/vec4.rs
+++ b/src/f32/wasm32/vec4.rs
@@ -145,7 +145,7 @@ impl Vec4 {
         dot4(self.0, rhs.0)
     }
 
-    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
         Self(unsafe { dot4_into_v128(self.0, rhs.0) })
diff --git a/src/f64/dvec2.rs b/src/f64/dvec2.rs
index 42039e9..c20404b 100644
--- a/src/f64/dvec2.rs
+++ b/src/f64/dvec2.rs
@@ -125,7 +125,7 @@ impl DVec2 {
         (self.x * rhs.x) + (self.y * rhs.y)
     }
 
-    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
         Self::splat(self.dot(rhs))
diff --git a/src/f64/dvec3.rs b/src/f64/dvec3.rs
index 0260d42..8cfaef8 100644
--- a/src/f64/dvec3.rs
+++ b/src/f64/dvec3.rs
@@ -153,7 +153,7 @@ impl DVec3 {
         (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z)
     }
 
-    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
         Self::splat(self.dot(rhs))
diff --git a/src/f64/dvec4.rs b/src/f64/dvec4.rs
index 50d49b4..62ccf4f 100644
--- a/src/f64/dvec4.rs
+++ b/src/f64/dvec4.rs
@@ -154,7 +154,7 @@ impl DVec4 {
         (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z) + (self.w * rhs.w)
     }
 
-    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
         Self::splat(self.dot(rhs))
diff --git a/src/i32/ivec2.rs b/src/i32/ivec2.rs
index 599f4f5..87b5122 100644
--- a/src/i32/ivec2.rs
+++ b/src/i32/ivec2.rs
@@ -119,7 +119,7 @@ impl IVec2 {
         (self.x * rhs.x) + (self.y * rhs.y)
     }
 
-    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
         Self::splat(self.dot(rhs))
diff --git a/src/i32/ivec3.rs b/src/i32/ivec3.rs
index 7a87a30..6ccd5f9 100644
--- a/src/i32/ivec3.rs
+++ b/src/i32/ivec3.rs
@@ -147,7 +147,7 @@ impl IVec3 {
         (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z)
     }
 
-    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
         Self::splat(self.dot(rhs))
diff --git a/src/i32/ivec4.rs b/src/i32/ivec4.rs
index 157cf05..5d875b2 100644
--- a/src/i32/ivec4.rs
+++ b/src/i32/ivec4.rs
@@ -148,7 +148,7 @@ impl IVec4 {
         (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z) + (self.w * rhs.w)
     }
 
-    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
         Self::splat(self.dot(rhs))
diff --git a/src/u32/uvec2.rs b/src/u32/uvec2.rs
index ac3d7df..d0c838e 100644
--- a/src/u32/uvec2.rs
+++ b/src/u32/uvec2.rs
@@ -110,7 +110,7 @@ impl UVec2 {
         (self.x * rhs.x) + (self.y * rhs.y)
     }
 
-    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
         Self::splat(self.dot(rhs))
diff --git a/src/u32/uvec3.rs b/src/u32/uvec3.rs
index 192886e..040b482 100644
--- a/src/u32/uvec3.rs
+++ b/src/u32/uvec3.rs
@@ -135,7 +135,7 @@ impl UVec3 {
         (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z)
     }
 
-    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
         Self::splat(self.dot(rhs))
diff --git a/src/u32/uvec4.rs b/src/u32/uvec4.rs
index decccf3..e6c43a3 100644
--- a/src/u32/uvec4.rs
+++ b/src/u32/uvec4.rs
@@ -133,7 +133,7 @@ impl UVec4 {
         (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z) + (self.w * rhs.w)
     }
 
-    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    /// Returns a vector where every component is the dot product of `self` and `rhs`.
     #[inline]
     pub fn dot_into_vec(self, rhs: Self) -> Self {
         Self::splat(self.dot(rhs))


Test patch:
diff --git a/tests/affine2.rs b/tests/affine2.rs
index 86280ed..98b29c6 100644
--- a/tests/affine2.rs
+++ b/tests/affine2.rs
@@ -233,6 +233,15 @@ mod affine2 {
         }
     });
 
+    glam_test!(test_affine2_from_mat3a, {
+        use glam::Mat3A;
+        let m = Mat3A::from_cols_array_2d(&[[1.0, 2.0, 0.0], [3.0, 4.0, 0.0], [5.0, 6.0, 1.0]]);
+        let a = Affine2::from_mat3a(m);
+        assert_eq!(MATRIX2D, a.to_cols_array_2d());
+
+        assert_eq!(m, Mat3A::from(a));
+    });
+
     impl_affine2_tests!(f32, Affine2, Vec2, Mat2, Mat3);
 }
 
diff --git a/tests/mat2.rs b/tests/mat2.rs
index 5c3972b..c53c669 100644
--- a/tests/mat2.rs
+++ b/tests/mat2.rs
@@ -265,6 +265,13 @@ mod mat2 {
         }
     });
 
+    glam_test!(test_from_mat3a, {
+        use glam::Mat3A;
+        let m3 = Mat3A::from_cols_array_2d(&[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]]);
+        let m2 = Mat2::from_mat3a(m3);
+        assert_eq!(Mat2::from_cols_array_2d(&[[1.0, 2.0], [4.0, 5.0]]), m2);
+    });
+
     glam_test!(test_as, {
         use glam::DMat2;
         assert_eq!(
diff --git a/tests/mat4.rs b/tests/mat4.rs
index f90ef1e..7c35e82 100644
--- a/tests/mat4.rs
+++ b/tests/mat4.rs
@@ -727,6 +727,21 @@ mod mat4 {
         assert_eq!(64, mem::size_of::<Mat4>());
     });
 
+    glam_test!(test_from_mat3a, {
+        use glam::Mat3A;
+        let m3 = Mat3A::from_cols_array_2d(&[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]]);
+        let m4 = Mat4::from_mat3a(m3);
+        assert_eq!(
+            Mat4::from_cols_array_2d(&[
+                [1.0, 2.0, 3.0, 0.0],
+                [4.0, 5.0, 6.0, 0.0],
+                [7.0, 8.0, 9.0, 0.0],
+                [0.0, 0.0, 0.0, 1.0]
+            ]),
+            m4
+        );
+    });
+
     glam_test!(test_as, {
         use glam::DMat4;
         assert_eq!(
diff --git a/tests/quat.rs b/tests/quat.rs
index 455a9e1..4c92ba1 100644
--- a/tests/quat.rs
+++ b/tests/quat.rs
@@ -590,6 +590,16 @@ mod quat {
         assert_approx_eq!(-Vec3A::X, mrzx.mul_vec3a(Vec3A::Y));
     });
 
+    glam_test!(test_from_mat3a, {
+        use glam::Mat3A;
+        let yaw = deg(30.0);
+        let y0 = Quat::from_rotation_y(yaw);
+        let y1 = Quat::from_mat3a(&Mat3A::from_rotation_y(yaw));
+        assert_approx_eq!(y0, y1);
+        let y2 = Quat::from_mat3a(&Mat3A::from_quat(y0));
+        assert_approx_eq!(y0, y2);
+    });
+
     glam_test!(test_as, {
         use glam::DQuat;
         assert_approx_eq!(