comparison utils/src/math.rs @ 790:d005f5927447

utils: Use const_for to make more const fn
author Link Mauve <linkmauve@linkmauve.fr>
date Sat, 17 Jan 2026 14:12:08 +0100
parents b5bca9274335
children a29122662cde
comparison
equal deleted inserted replaced
789:b5bca9274335 790:d005f5927447
1 //! Various helpers to deal with vectors and matrices. 1 //! Various helpers to deal with vectors and matrices.
2
3 use const_for::const_for;
2 4
3 /// A 4×4 f32 matrix type. 5 /// A 4×4 f32 matrix type.
4 pub struct Mat4 { 6 pub struct Mat4 {
5 inner: [[f32; 4]; 4] 7 inner: [[f32; 4]; 4]
6 } 8 }
32 pub const fn borrow_inner(&self) -> &[[f32; 4]; 4] { 34 pub const fn borrow_inner(&self) -> &[[f32; 4]; 4] {
33 &self.inner 35 &self.inner
34 } 36 }
35 37
36 /// Scale the matrix in 2D. 38 /// Scale the matrix in 2D.
37 pub fn scale2d(&mut self, x: f32, y: f32) { 39 pub const fn scale2d(&mut self, x: f32, y: f32) {
38 for i in 0..4 { 40 const_for!(i in 0..4 => {
39 self.inner[0][i] *= x; 41 self.inner[0][i] *= x;
40 self.inner[1][i] *= y; 42 self.inner[1][i] *= y;
41 } 43 });
42 } 44 }
43 45
44 /// Flip the matrix. 46 /// Flip the matrix.
45 pub fn flip(&mut self) { 47 pub const fn flip(&mut self) {
46 for i in 0..4 { 48 const_for!(i in 0..4 => {
47 self.inner[0][i] = -self.inner[0][i]; 49 self.inner[0][i] = -self.inner[0][i];
48 } 50 });
49 } 51 }
50 52
51 /// Rotate the matrix around its x angle (in radians). 53 /// Rotate the matrix around its x angle (in radians).
52 pub fn rotate_x(&mut self, angle: f32) { 54 pub fn rotate_x(&mut self, angle: f32) {
53 let mut lines: [f32; 8] = [0.; 8]; 55 let mut lines: [f32; 8] = [0.; 8];
54 let cos_a = angle.cos(); 56 let cos_a = angle.cos();
55 let sin_a = angle.sin(); 57 let sin_a = angle.sin();
56 for i in 0..4 { 58 const_for!(i in 0..4 => {
57 lines[ i] = self.inner[0][i]; 59 lines[ i] = self.inner[0][i];
58 lines[4 + i] = self.inner[1][i]; 60 lines[4 + i] = self.inner[1][i];
59 } 61 });
60 for i in 0..4 { 62 const_for!(i in 0..4 => {
61 self.inner[1][i] = cos_a * lines[i] - sin_a * lines[4+i]; 63 self.inner[1][i] = cos_a * lines[i] - sin_a * lines[4+i];
62 self.inner[2][i] = sin_a * lines[i] + cos_a * lines[4+i]; 64 self.inner[2][i] = sin_a * lines[i] + cos_a * lines[4+i];
63 } 65 });
64 } 66 }
65 67
66 /// Rotate the matrix around its y angle (in radians). 68 /// Rotate the matrix around its y angle (in radians).
67 pub fn rotate_y(&mut self, angle: f32) { 69 pub fn rotate_y(&mut self, angle: f32) {
68 let mut lines: [f32; 8] = [0.; 8]; 70 let mut lines: [f32; 8] = [0.; 8];
69 let cos_a = angle.cos(); 71 let cos_a = angle.cos();
70 let sin_a = angle.sin(); 72 let sin_a = angle.sin();
71 for i in 0..4 { 73 const_for!(i in 0..4 => {
72 lines[ i] = self.inner[0][i]; 74 lines[ i] = self.inner[0][i];
73 lines[4 + i] = self.inner[2][i]; 75 lines[4 + i] = self.inner[2][i];
74 } 76 });
75 for i in 0..4 { 77 const_for!(i in 0..4 => {
76 self.inner[0][i] = cos_a * lines[i] + sin_a * lines[4+i]; 78 self.inner[0][i] = cos_a * lines[i] + sin_a * lines[4+i];
77 self.inner[2][i] = -sin_a * lines[i] + cos_a * lines[4+i]; 79 self.inner[2][i] = -sin_a * lines[i] + cos_a * lines[4+i];
78 } 80 });
79 } 81 }
80 82
81 /// Rotate the matrix around its z angle (in radians). 83 /// Rotate the matrix around its z angle (in radians).
82 pub fn rotate_z(&mut self, angle: f32) { 84 pub fn rotate_z(&mut self, angle: f32) {
83 let mut lines: [f32; 8] = [0.; 8]; 85 let mut lines: [f32; 8] = [0.; 8];
84 let cos_a = angle.cos(); 86 let cos_a = angle.cos();
85 let sin_a = angle.sin(); 87 let sin_a = angle.sin();
86 for i in 0..4 { 88 const_for!(i in 0..4 => {
87 lines[ i] = self.inner[0][i]; 89 lines[ i] = self.inner[0][i];
88 lines[4 + i] = self.inner[1][i]; 90 lines[4 + i] = self.inner[1][i];
89 } 91 });
90 for i in 0..4 { 92 const_for!(i in 0..4 => {
91 self.inner[0][i] = cos_a * lines[i] - sin_a * lines[4+i]; 93 self.inner[0][i] = cos_a * lines[i] - sin_a * lines[4+i];
92 self.inner[1][i] = sin_a * lines[i] + cos_a * lines[4+i]; 94 self.inner[1][i] = sin_a * lines[i] + cos_a * lines[4+i];
93 } 95 });
94 } 96 }
95 97
96 /// Translate the matrix by a 3D offset. 98 /// Translate the matrix by a 3D offset.
97 pub fn translate(&mut self, offset: [f32; 3]) { 99 pub const fn translate(&mut self, offset: [f32; 3]) {
98 let mut item: [f32; 3] = [0.; 3]; 100 let mut item: [f32; 3] = [0.; 3];
99 for i in 0..3 { 101 const_for!(i in 0..3 => {
100 item[i] = self.inner[3][i] * offset[i]; 102 item[i] = self.inner[3][i] * offset[i];
101 } 103 });
102 for i in 0..3 { 104 const_for!(i in 0..3 => {
103 for j in 0..4 { 105 const_for!(j in 0..4 => {
104 self.inner[i][j] += item[i]; 106 self.inner[i][j] += item[i];
105 } 107 });
106 } 108 });
107 } 109 }
108 110
109 /// Translate the matrix by a 2D offset. 111 /// Translate the matrix by a 2D offset.
110 pub fn translate_2d(&mut self, x: f32, y: f32) { 112 pub const fn translate_2d(&mut self, x: f32, y: f32) {
111 let offset = [x, y, 0.]; 113 let offset = [x, y, 0.];
112 self.translate(offset); 114 self.translate(offset);
113 } 115 }
114 } 116 }
115 117
116 impl std::ops::Mul<Mat4> for Mat4 { 118 impl std::ops::Mul<Mat4> for Mat4 {
117 type Output = Mat4; 119 type Output = Mat4;
118 fn mul(self, rhs: Mat4) -> Mat4 { 120 fn mul(self, rhs: Mat4) -> Mat4 {
119 let mut tmp = Mat4::zero(); 121 let mut tmp = Mat4::zero();
120 for i in 0..4 { 122 const_for!(i in 0..4 => {
121 for j in 0..4 { 123 const_for!(j in 0..4 => {
122 for k in 0..4 { 124 const_for!(k in 0..4 => {
123 tmp.inner[i][j] += self.inner[i][k] * rhs.inner[k][j]; 125 tmp.inner[i][j] += self.inner[i][k] * rhs.inner[k][j];
124 } 126 });
125 } 127 });
126 } 128 });
127 tmp 129 tmp
128 } 130 }
129 } 131 }
130 132
131 /// Create an orthographic projection matrix. 133 /// Create an orthographic projection matrix.