From 43cf6e861a5fe2ee7d6310ae1bbedf3eead95800 Mon Sep 17 00:00:00 2001 From: Cameron Hart Date: Tue, 11 Oct 2022 11:28:22 +1300 Subject: [PATCH] Add missing `from_mat3a` methods (#352) * Add a lot of missing `from_mat3a` methods. --- codegen/templates/affine.rs.tera | 12 +++++++++++ codegen/templates/mat.rs.tera | 36 ++++++++++++++++++++++++++++---- codegen/templates/quat.rs.tera | 14 ++++++++++++- codegen/templates/vec.rs.tera | 2 +- src/f32/affine2.rs | 10 +++++++++ src/f32/coresimd/mat2.rs | 8 ++++++- src/f32/coresimd/mat4.rs | 17 ++++++++++++++- src/f32/coresimd/quat.rs | 8 ++++++- src/f32/coresimd/vec3a.rs | 2 +- src/f32/coresimd/vec4.rs | 2 +- src/f32/scalar/mat2.rs | 8 ++++++- src/f32/scalar/mat4.rs | 17 ++++++++++++++- src/f32/scalar/quat.rs | 8 ++++++- src/f32/scalar/vec3a.rs | 2 +- src/f32/scalar/vec4.rs | 2 +- src/f32/sse2/mat2.rs | 8 ++++++- src/f32/sse2/mat4.rs | 17 ++++++++++++++- src/f32/sse2/quat.rs | 8 ++++++- src/f32/sse2/vec3a.rs | 2 +- src/f32/sse2/vec4.rs | 2 +- src/f32/vec2.rs | 2 +- src/f32/vec3.rs | 2 +- src/f32/wasm32/mat2.rs | 8 ++++++- src/f32/wasm32/mat4.rs | 17 ++++++++++++++- src/f32/wasm32/quat.rs | 8 ++++++- src/f32/wasm32/vec3a.rs | 2 +- src/f32/wasm32/vec4.rs | 2 +- src/f64/dvec2.rs | 2 +- src/f64/dvec3.rs | 2 +- src/f64/dvec4.rs | 2 +- src/i32/ivec2.rs | 2 +- src/i32/ivec3.rs | 2 +- src/i32/ivec4.rs | 2 +- src/u32/uvec2.rs | 2 +- src/u32/uvec3.rs | 2 +- src/u32/uvec4.rs | 2 +- tests/affine2.rs | 9 ++++++++ tests/mat2.rs | 7 +++++++ tests/mat4.rs | 15 +++++++++++++ tests/quat.rs | 10 +++++++++ 40 files changed, 248 insertions(+), 37 deletions(-) diff --git a/codegen/templates/affine.rs.tera b/codegen/templates/affine.rs.tera index a2985cc1..52064480 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 2fb7856d..8161c64b 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 1faa6bad..f6c607a7 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 425262eb..25e43864 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 5a43d7e1..2befa9a9 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 276816fa..200aa52f 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 d8a86f47..26239ba4 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 9dfbb675..21aa519b 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 71f5c646..adaceb6e 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 fa92f936..61b4903b 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 03d082ef..9c4c2530 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 580eb279..78d7a521 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 bd7b66df..0b72e8f1 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 26b82b66..88a3c138 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 6abcccd7..cf791cf0 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 311448bf..0222bdd8 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 24e16adc..aa694938 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 b992a807..f7fbd8d8 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 56b8c8d6..7fa8a6a8 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 f72e0277..0e0882c4 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 13181e19..16bd17d0 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 56062638..b049ed8d 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 7869ff52..b96ef73f 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 433e893d..bdaeb294 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 d1aa4751..75f9c165 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 08a6269f..85b3fe4e 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 de16f666..ab53d7a7 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 42039e98..c20404bf 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 0260d42f..8cfaef8d 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 50d49b45..62ccf4f6 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 599f4f59..87b51225 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 7a87a304..6ccd5f90 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 157cf05c..5d875b25 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 ac3d7df6..d0c838ed 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 192886e1..040b482f 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 decccf3b..e6c43a38 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)) diff --git a/tests/affine2.rs b/tests/affine2.rs index 86280ed3..98b29c67 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 5c3972b3..c53c6690 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 f90ef1eb..7c35e822 100644 --- a/tests/mat4.rs +++ b/tests/mat4.rs @@ -727,6 +727,21 @@ mod mat4 { assert_eq!(64, mem::size_of::()); }); + 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 455a9e16..4c92ba11 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!(