]> git.nega.tv - josh/narcissus/commitdiff
Fill out `Mat2` and `Mat3` some more
authorJoshua Simmons <josh@nega.tv>
Thu, 8 Sep 2022 20:46:38 +0000 (22:46 +0200)
committerJoshua Simmons <josh@nega.tv>
Thu, 8 Sep 2022 20:46:38 +0000 (22:46 +0200)
narcissus-maths/src/affine2.rs
narcissus-maths/src/affine3.rs
narcissus-maths/src/mat2.rs
narcissus-maths/src/mat3.rs
narcissus-maths/src/mat4.rs

index 42a0a2cd0d4f0731d8de90b93ca39e573e4858ca..0d10b17936c736b07da42d9a1669532967be443d 100644 (file)
@@ -1,5 +1,6 @@
 use crate::{Mat2, Vec2};
 
+/// Matrix and translation vector which together represent a 2d affine transformation.
 #[derive(Clone, Copy, PartialEq)]
 #[repr(C)]
 pub struct Affine2 {
index f13a653f3d446b31c00a81149b5ace1ae41ae378..39c924eef529db3d95f313ae02aeeccf95c19141 100644 (file)
@@ -1,5 +1,6 @@
 use crate::{Mat3, Vec3};
 
+/// Matrix and translation vector which together represent a 3d affine transformation.
 #[derive(Clone, Copy, PartialEq)]
 #[repr(C)]
 pub struct Affine3 {
index 8b21e7b2433da2f3cbde3a3b39bcb73f85ec4f48..e36669feea1e88c49a93529a923e9f84482bcd0d 100644 (file)
@@ -1,3 +1,38 @@
+/// 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) }
+    }
+}
index 93a772a11a4f94a3f02dfd7d625e34c8be4aecbc..33741fc9f15ff8bf69fb9ede33190f26bb8d39b2 100644 (file)
@@ -1,3 +1,82 @@
+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,
+            ],
+        ])
+    }
+}
index 40260b4c7d47087aa04a4fbdf6326d86045f3d0f..ae7615bd9877d4c2a5e3bf8da0dbbf120d2a0f3d 100644 (file)
@@ -1,5 +1,8 @@
 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]);
@@ -77,6 +80,7 @@ impl Mat4 {
         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],
@@ -86,6 +90,7 @@ impl Mat4 {
         ])
     }
 
+    /// 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],
@@ -95,6 +100,7 @@ impl Mat4 {
         ])
     }
 
+    /// 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],
@@ -104,6 +110,7 @@ impl Mat4 {
         ])
     }
 
+    /// 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;
@@ -147,6 +154,7 @@ impl Mat4 {
         ])
     }
 
+    // Safety: Requires SSE2.
     #[inline]
     #[target_feature(enable = "sse2")]
     unsafe fn transpose_sse2(self) -> Mat4 {
@@ -156,6 +164,7 @@ impl Mat4 {
         Mat4::from_m128_array([row0, row1, row2, row3])
     }
 
+    /// Returns the transpose of `self`.
     #[must_use]
     #[inline(always)]
     pub fn transpose(self) -> Mat4 {
@@ -169,6 +178,7 @@ impl Mat4 {
         }
     }
 
+    /// Transforms the given [`Vec2`] `vec` by `self`.
     #[must_use]
     #[inline]
     pub fn mul_vec2(&self, vec: Vec2) -> Vec2 {
@@ -177,6 +187,7 @@ impl Mat4 {
         Vec2::new(vec.x, vec.y)
     }
 
+    /// Transforms the given [`Point2`] `point` by `self`.
     #[must_use]
     #[inline]
     pub fn mul_point2(&self, point: Point2) -> Point2 {
@@ -185,6 +196,7 @@ impl Mat4 {
         Point2::new(vec.x, vec.y)
     }
 
+    /// Transforms the given [`Vec3`] `vec` by `self`.
     #[must_use]
     #[inline]
     pub fn mul_vec3(&self, vec: Vec3) -> Vec3 {
@@ -193,6 +205,7 @@ impl Mat4 {
         [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 {
@@ -212,6 +225,7 @@ impl Mat4 {
         )
     }
 
+    // Safety: Requires SSE4.1.
     #[allow(dead_code)]
     #[inline]
     #[target_feature(enable = "sse4.1")]
@@ -229,6 +243,7 @@ impl Mat4 {
         values.into()
     }
 
+    /// Transforms the given [`Vec4`] `vec` by `self`.
     #[must_use]
     #[inline(always)]
     pub fn mul_vec4(&self, vec: Vec4) -> Vec4 {
@@ -263,6 +278,7 @@ impl Mat4 {
         result
     }
 
+    // Safety: Requires SSE2.
     #[allow(dead_code)]
     #[inline]
     #[target_feature(enable = "sse2")]
@@ -290,6 +306,7 @@ impl Mat4 {
         Mat4::from_m128_array([x0, x1, x2, x3])
     }
 
+    // Safety: Requires AVX2.
     #[allow(dead_code)]
     #[inline]
     #[target_feature(enable = "avx2")]