use crate::{Mat2, Vec2};
+/// Matrix and translation vector which together represent a 2d affine transformation.
#[derive(Clone, Copy, PartialEq)]
#[repr(C)]
pub struct Affine2 {
use crate::{Mat3, Vec3};
+/// Matrix and translation vector which together represent a 3d affine transformation.
#[derive(Clone, Copy, PartialEq)]
#[repr(C)]
pub struct Affine3 {
+/// 2x2 matrix.
#[derive(Clone, Copy, PartialEq)]
#[repr(C)]
pub struct Mat2(pub [f32; 4]);
+
+impl std::fmt::Debug for Mat2 {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if f.alternate() {
+ writeln!(f, "Mat2 [")?;
+ for row in self.as_rows() {
+ writeln!(f, "\t{:?}", row)?;
+ }
+ writeln!(f, "]")
+ } else {
+ writeln!(f, "Mat2 {:?}", self.as_rows())
+ }
+ }
+}
+
+impl Mat2 {
+ pub const ZERO: Mat2 = Mat2::from_rows([[0.0, 0.0], [0.0, 0.0]]);
+ pub const IDENTITY: Mat2 = Mat2::from_rows([[1.0, 0.0], [0.0, 1.0]]);
+
+ #[inline(always)]
+ pub fn as_rows(&self) -> &[[f32; 2]; 2] {
+ unsafe { std::mem::transmute(&self.0) }
+ }
+
+ #[inline(always)]
+ pub fn as_rows_mut(&mut self) -> &mut [[f32; 2]; 2] {
+ unsafe { std::mem::transmute(&mut self.0) }
+ }
+
+ #[inline(always)]
+ pub const fn from_rows(rows: [[f32; 2]; 2]) -> Self {
+ unsafe { std::mem::transmute(rows) }
+ }
+}
+use crate::{Rad, Vec3};
+
+/// 3x3 matrix.
#[derive(Clone, Copy, PartialEq)]
#[repr(C)]
pub struct Mat3(pub [f32; 9]);
+
+impl std::fmt::Debug for Mat3 {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if f.alternate() {
+ writeln!(f, "Mat3 [")?;
+ for row in self.as_rows() {
+ writeln!(f, "\t{:?}", row)?;
+ }
+ writeln!(f, "]")
+ } else {
+ writeln!(f, "Mat3 {:?}", self.as_rows())
+ }
+ }
+}
+
+impl Mat3 {
+ pub const ZERO: Mat3 = Mat3::from_rows([[0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]]);
+ pub const IDENTITY: Mat3 = Mat3::from_rows([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]);
+
+ #[inline(always)]
+ pub fn as_rows(&self) -> &[[f32; 3]; 3] {
+ unsafe { std::mem::transmute(&self.0) }
+ }
+
+ #[inline(always)]
+ pub fn as_rows_mut(&mut self) -> &mut [[f32; 3]; 3] {
+ unsafe { std::mem::transmute(&mut self.0) }
+ }
+
+ #[inline(always)]
+ pub const fn from_rows(rows: [[f32; 3]; 3]) -> Self {
+ unsafe { std::mem::transmute(rows) }
+ }
+
+ /// Construct a matrix with the provided `diagonal` and all other values set to `0.0`.
+ pub const fn from_diagonal(diagonal: Vec3) -> Mat3 {
+ Mat3::from_rows([
+ [diagonal.x, 0.0, 0.0],
+ [0.0, diagonal.y, 0.0],
+ [0.0, 0.0, diagonal.z],
+ ])
+ }
+
+ /// Construct a transformation matrix which scales along the coordinate axis by the values given in `scale`.
+ pub const fn from_scale(scale: Vec3) -> Mat3 {
+ Mat3::from_diagonal(scale)
+ }
+
+ /// Constructs a transformation matrix which rotates around the given `axis` by `angle`.
+ pub fn from_axis_angle(axis: Vec3, angle: Rad) -> Mat3 {
+ let (sin, cos) = angle.as_f32().sin_cos();
+ let axis_sin = axis * sin;
+ let axis_sq = axis * axis;
+ let one_minus_cos = 1.0 - cos;
+ let xy = axis.x * axis.y * one_minus_cos;
+ let xz = axis.x * axis.z * one_minus_cos;
+ let yz = axis.y * axis.z * one_minus_cos;
+ Mat3::from_rows([
+ [
+ axis_sq.x * one_minus_cos + cos,
+ xy - axis_sin.z,
+ xz + axis_sin.y,
+ ],
+ [
+ xy + axis_sin.z,
+ axis_sq.y * one_minus_cos + cos,
+ yz - axis_sin.x,
+ ],
+ [
+ xz - axis_sin.y,
+ yz + axis_sin.x,
+ axis_sq.z * one_minus_cos + cos,
+ ],
+ ])
+ }
+}
use crate::{Point2, Point3, Rad, Vec2, Vec3, Vec4};
+/// 4x4 matrix.
+///
+/// Supports affine transformations.
#[derive(Clone, Copy, PartialEq)]
#[repr(C)]
pub struct Mat4(pub [f32; 16]);
result
}
+ /// Construct a matrix with the provided `diagonal` and all other values set to `0.0`.
pub const fn from_diagonal(diagonal: Vec4) -> Mat4 {
Mat4::from_rows([
[diagonal.x, 0.0, 0.0, 0.0],
])
}
+ /// Construct a transformation matrix which scales along the coordinate axis by the values given in `scale`.
pub const fn from_scale(scale: Vec3) -> Mat4 {
Mat4::from_rows([
[scale.x, 0.0, 0.0, 0.0],
])
}
+ /// Construct an affine transformation matrix with the given `translation` along the coordinate axis.
pub const fn from_translation(translation: Vec3) -> Mat4 {
Mat4::from_rows([
[1.0, 0.0, 0.0, translation.x],
])
}
+ /// Constructs a transformation matrix which rotates around the given `axis` by `angle`.
pub fn from_axis_angle(axis: Vec3, angle: Rad) -> Mat4 {
let (sin, cos) = angle.as_f32().sin_cos();
let axis_sin = axis * sin;
])
}
+ // Safety: Requires SSE2.
#[inline]
#[target_feature(enable = "sse2")]
unsafe fn transpose_sse2(self) -> Mat4 {
Mat4::from_m128_array([row0, row1, row2, row3])
}
+ /// Returns the transpose of `self`.
#[must_use]
#[inline(always)]
pub fn transpose(self) -> Mat4 {
}
}
+ /// Transforms the given [`Vec2`] `vec` by `self`.
#[must_use]
#[inline]
pub fn mul_vec2(&self, vec: Vec2) -> Vec2 {
Vec2::new(vec.x, vec.y)
}
+ /// Transforms the given [`Point2`] `point` by `self`.
#[must_use]
#[inline]
pub fn mul_point2(&self, point: Point2) -> Point2 {
Point2::new(vec.x, vec.y)
}
+ /// Transforms the given [`Vec3`] `vec` by `self`.
#[must_use]
#[inline]
pub fn mul_vec3(&self, vec: Vec3) -> Vec3 {
[vec.x, vec.y, vec.z].into()
}
+ /// Transforms the given [`Point3`] `point` by `self`.
#[must_use]
#[inline]
pub fn mul_point3(&self, point: Point3) -> Point3 {
)
}
+ // Safety: Requires SSE4.1.
#[allow(dead_code)]
#[inline]
#[target_feature(enable = "sse4.1")]
values.into()
}
+ /// Transforms the given [`Vec4`] `vec` by `self`.
#[must_use]
#[inline(always)]
pub fn mul_vec4(&self, vec: Vec4) -> Vec4 {
result
}
+ // Safety: Requires SSE2.
#[allow(dead_code)]
#[inline]
#[target_feature(enable = "sse2")]
Mat4::from_m128_array([x0, x1, x2, x3])
}
+ // Safety: Requires AVX2.
#[allow(dead_code)]
#[inline]
#[target_feature(enable = "avx2")]