diff options
| author | HampusM <hampus@hampusmat.com> | 2026-08-02 16:11:30 +0200 |
|---|---|---|
| committer | HampusM <hampus@hampusmat.com> | 2026-08-02 17:52:03 +0200 |
| commit | 7b0edcfc6a07ff4d64e602f2b68d93fedc8b826d (patch) | |
| tree | 6077257d6a920c13ef62c22564343ae952ad81d7 /engine/src/data_types | |
| parent | 3f9750edecad1615348d9ec0995a2fbde468c8a3 (diff) | |
fix(engine): improve portability by making matrices row-major
Diffstat (limited to 'engine/src/data_types')
| -rw-r--r-- | engine/src/data_types/matrix.rs | 243 |
1 files changed, 136 insertions, 107 deletions
diff --git a/engine/src/data_types/matrix.rs b/engine/src/data_types/matrix.rs index cc43e7b..48796bf 100644 --- a/engine/src/data_types/matrix.rs +++ b/engine/src/data_types/matrix.rs @@ -1,12 +1,11 @@ -use std::ops::Mul; +use std::ops::{Index, IndexMut, Mul}; use crate::vector::{Vec3, Vec4}; #[derive(Debug, Clone)] pub struct Matrix<Value, const ROWS: usize, const COLUMNS: usize> { - /// Items must be layed out this way for it to work with OpenGL shaders. - pub items: [[Value; ROWS]; COLUMNS], + items: [[Value; COLUMNS]; ROWS], } impl<Value, const ROWS: usize, const COLUMNS: usize> Matrix<Value, ROWS, COLUMNS> @@ -25,21 +24,32 @@ impl<Value, const ROWS: usize, const COLUMNS: usize> Matrix<Value, ROWS, COLUMNS pub fn from_columns<Column>(columns: [Column; COLUMNS]) -> Self where Column: Into<[Value; ROWS]>, + Value: Default, { - Self { - items: columns.map(|column| column.into()), + let mut items = + std::array::from_fn(|_| std::array::from_fn(|_| Value::default())); + + for (column_index, column) in columns.into_iter().enumerate() { + for (row_index, item) in column.into().into_iter().enumerate() { + items[row_index][column_index] = item; + } } + + Self { items } } - /// Sets the value at the specified cell. - pub fn set_cell(&mut self, row: usize, column: usize, value: Value) + pub fn get_column_copied(&self, column_index: usize) -> [Value; ROWS] + where + Value: Default + Copy, { - self.items[column][row] = value; + std::array::from_fn::<Value, ROWS, _>(|row_index| { + self[CellPos { row: row_index, col: column_index }] + }) } - pub fn items(&self) -> &[[Value; ROWS]; COLUMNS] + pub fn items(&self) -> &[Value] { - &self.items + &self.items.as_flattened() } } @@ -60,19 +70,13 @@ impl<const ROWS_COLS: usize> Matrix<f32, ROWS_COLS, ROWS_COLS> #[must_use] pub fn new_identity() -> Self { - let mut index = 0; - - let items = [(); ROWS_COLS].map(|()| { - let mut columns = [0.0; ROWS_COLS]; + let mut identity = Self::new(); - columns[index] = 1.0; - - index += 1; - - columns - }); + for index in 0..ROWS_COLS { + identity[CellPos { row: index, col: index }] = 1.0; + } - Self { items } + identity } } @@ -80,18 +84,18 @@ impl Matrix<f32, 4, 4> { pub fn translate(&mut self, translation: &Vec3<f32>) { - self.set_cell(0, 3, translation.x); - self.set_cell(1, 3, translation.y); - self.set_cell(2, 3, translation.z); - self.set_cell(3, 3, 1.0); + self[CellPos { row: 0, col: 3 }] = translation.x; + self[CellPos { row: 1, col: 3 }] = translation.y; + self[CellPos { row: 2, col: 3 }] = translation.z; + self[CellPos { row: 3, col: 3 }] = 1.0; } pub fn scale(&mut self, scaling: &Vec3<f32>) { - self.set_cell(0, 0, scaling.x); - self.set_cell(1, 1, scaling.y); - self.set_cell(2, 2, scaling.z); - self.set_cell(3, 3, 1.0); + self[CellPos { row: 0, col: 0 }] = scaling.x; + self[CellPos { row: 1, col: 1 }] = scaling.y; + self[CellPos { row: 2, col: 2 }] = scaling.z; + self[CellPos { row: 3, col: 3 }] = 1.0; } pub fn look_at(&mut self, eye: Vec3<f32>, target: Vec3<f32>, up: Vec3<f32>) @@ -102,17 +106,17 @@ impl Matrix<f32, 4, 4> let camera_up = rev_target_direction.cross(&camera_right); - self.set_cell(0, 0, camera_right.x); - self.set_cell(0, 1, camera_right.y); - self.set_cell(0, 2, camera_right.z); + self[CellPos { row: 0, col: 0 }] = camera_right.x; + self[CellPos { row: 0, col: 1 }] = camera_right.y; + self[CellPos { row: 0, col: 2 }] = camera_right.z; - self.set_cell(1, 0, camera_up.x); - self.set_cell(1, 1, camera_up.y); - self.set_cell(1, 2, camera_up.z); + self[CellPos { row: 1, col: 0 }] = camera_up.x; + self[CellPos { row: 1, col: 1 }] = camera_up.y; + self[CellPos { row: 1, col: 2 }] = camera_up.z; - self.set_cell(2, 0, rev_target_direction.x); - self.set_cell(2, 1, rev_target_direction.y); - self.set_cell(2, 2, rev_target_direction.z); + self[CellPos { row: 2, col: 0 }] = rev_target_direction.x; + self[CellPos { row: 2, col: 1 }] = rev_target_direction.y; + self[CellPos { row: 2, col: 2 }] = rev_target_direction.z; // The vector is negated since we want the world to be translated in the opposite // direction of where we want the camera to move. @@ -122,56 +126,56 @@ impl Matrix<f32, 4, 4> z: rev_target_direction.dot(&eye), }; - self.set_cell(0, 3, camera_pos.x); - self.set_cell(1, 3, camera_pos.y); - self.set_cell(2, 3, camera_pos.z); + self[CellPos { row: 0, col: 3 }] = camera_pos.x; + self[CellPos { row: 1, col: 3 }] = camera_pos.y; + self[CellPos { row: 2, col: 3 }] = camera_pos.z; - self.set_cell(3, 3, 1.0); + self[CellPos { row: 3, col: 3 }] = 1.0; } pub fn inverse(&self) -> Self { - let coef_00 = - self.items[2][2] * self.items[3][3] - self.items[3][2] * self.items[2][3]; - let coef_02 = - self.items[1][2] * self.items[3][3] - self.items[3][2] * self.items[1][3]; - let coef_03 = - self.items[1][2] * self.items[2][3] - self.items[2][2] * self.items[1][3]; - - let coef_04 = - self.items[2][1] * self.items[3][3] - self.items[3][1] * self.items[2][3]; - let coef_06 = - self.items[1][1] * self.items[3][3] - self.items[3][1] * self.items[1][3]; - let coef_07 = - self.items[1][1] * self.items[2][3] - self.items[2][1] * self.items[1][3]; - - let coef_08 = - self.items[2][1] * self.items[3][2] - self.items[3][1] * self.items[2][2]; - let coef_10 = - self.items[1][1] * self.items[3][2] - self.items[3][1] * self.items[1][2]; - let coef_11 = - self.items[1][1] * self.items[2][2] - self.items[2][1] * self.items[1][2]; - - let coef_12 = - self.items[2][0] * self.items[3][3] - self.items[3][0] * self.items[2][3]; - let coef_14 = - self.items[1][0] * self.items[3][3] - self.items[3][0] * self.items[1][3]; - let coef_15 = - self.items[1][0] * self.items[2][3] - self.items[2][0] * self.items[1][3]; - - let coef_16 = - self.items[2][0] * self.items[3][2] - self.items[3][0] * self.items[2][2]; - let coef_18 = - self.items[1][0] * self.items[3][2] - self.items[3][0] * self.items[1][2]; - let coef_19 = - self.items[1][0] * self.items[2][2] - self.items[2][0] * self.items[1][2]; - - let coef_20 = - self.items[2][0] * self.items[3][1] - self.items[3][0] * self.items[2][1]; - let coef_22 = - self.items[1][0] * self.items[3][1] - self.items[3][0] * self.items[1][1]; - let coef_23 = - self.items[1][0] * self.items[2][1] - self.items[2][0] * self.items[1][1]; + let coef_00 = self[CellPos { row: 2, col: 2 }] * self[CellPos { row: 3, col: 3 }] + - self[CellPos { row: 2, col: 3 }] * self[CellPos { row: 3, col: 2 }]; + let coef_02 = self[CellPos { row: 2, col: 1 }] * self[CellPos { row: 3, col: 3 }] + - self[CellPos { row: 2, col: 3 }] * self[CellPos { row: 3, col: 1 }]; + let coef_03 = self[CellPos { row: 2, col: 1 }] * self[CellPos { row: 3, col: 2 }] + - self[CellPos { row: 2, col: 2 }] * self[CellPos { row: 3, col: 1 }]; + + let coef_04 = self[CellPos { row: 1, col: 2 }] * self[CellPos { row: 3, col: 3 }] + - self[CellPos { row: 1, col: 3 }] * self[CellPos { row: 3, col: 2 }]; + let coef_06 = self[CellPos { row: 1, col: 1 }] * self[CellPos { row: 3, col: 3 }] + - self[CellPos { row: 1, col: 3 }] * self[CellPos { row: 3, col: 1 }]; + let coef_07 = self[CellPos { row: 1, col: 1 }] * self[CellPos { row: 3, col: 2 }] + - self[CellPos { row: 1, col: 2 }] * self[CellPos { row: 3, col: 1 }]; + + let coef_08 = self[CellPos { row: 1, col: 2 }] * self[CellPos { row: 2, col: 3 }] + - self[CellPos { row: 1, col: 3 }] * self[CellPos { row: 2, col: 2 }]; + let coef_10 = self[CellPos { row: 1, col: 1 }] * self[CellPos { row: 2, col: 3 }] + - self[CellPos { row: 1, col: 3 }] * self[CellPos { row: 2, col: 1 }]; + let coef_11 = self[CellPos { row: 1, col: 1 }] * self[CellPos { row: 2, col: 2 }] + - self[CellPos { row: 1, col: 2 }] * self[CellPos { row: 2, col: 1 }]; + + let coef_12 = self[CellPos { row: 0, col: 2 }] * self[CellPos { row: 3, col: 3 }] + - self[CellPos { row: 0, col: 3 }] * self[CellPos { row: 3, col: 2 }]; + let coef_14 = self[CellPos { row: 0, col: 1 }] * self[CellPos { row: 3, col: 3 }] + - self[CellPos { row: 0, col: 3 }] * self[CellPos { row: 3, col: 1 }]; + let coef_15 = self[CellPos { row: 0, col: 1 }] * self[CellPos { row: 3, col: 2 }] + - self[CellPos { row: 0, col: 2 }] * self[CellPos { row: 3, col: 1 }]; + + let coef_16 = self[CellPos { row: 0, col: 2 }] * self[CellPos { row: 2, col: 3 }] + - self[CellPos { row: 0, col: 3 }] * self[CellPos { row: 2, col: 2 }]; + let coef_18 = self[CellPos { row: 0, col: 1 }] * self[CellPos { row: 2, col: 3 }] + - self[CellPos { row: 0, col: 3 }] * self[CellPos { row: 2, col: 1 }]; + let coef_19 = self[CellPos { row: 0, col: 1 }] * self[CellPos { row: 2, col: 2 }] + - self[CellPos { row: 0, col: 2 }] * self[CellPos { row: 2, col: 1 }]; + + let coef_20 = self[CellPos { row: 0, col: 2 }] * self[CellPos { row: 1, col: 3 }] + - self[CellPos { row: 0, col: 3 }] * self[CellPos { row: 1, col: 2 }]; + let coef_22 = self[CellPos { row: 0, col: 1 }] * self[CellPos { row: 1, col: 3 }] + - self[CellPos { row: 0, col: 3 }] * self[CellPos { row: 1, col: 1 }]; + let coef_23 = self[CellPos { row: 0, col: 1 }] * self[CellPos { row: 1, col: 2 }] + - self[CellPos { row: 0, col: 2 }] * self[CellPos { row: 1, col: 1 }]; let fac_0 = Vec4 { x: coef_00, @@ -211,28 +215,28 @@ impl Matrix<f32, 4, 4> }; let vec_0 = Vec4 { - x: self.items[1][0], - y: self.items[0][0], - z: self.items[0][0], - w: self.items[0][0], + x: self[CellPos { row: 0, col: 1 }], + y: self[CellPos { row: 0, col: 0 }], + z: self[CellPos { row: 0, col: 0 }], + w: self[CellPos { row: 0, col: 0 }], }; let vec_1 = Vec4 { - x: self.items[1][1], - y: self.items[0][1], - z: self.items[0][1], - w: self.items[0][1], + x: self[CellPos { row: 1, col: 1 }], + y: self[CellPos { row: 1, col: 0 }], + z: self[CellPos { row: 1, col: 0 }], + w: self[CellPos { row: 1, col: 0 }], }; let vec_2 = Vec4 { - x: self.items[1][2], - y: self.items[0][2], - z: self.items[0][2], - w: self.items[0][2], + x: self[CellPos { row: 2, col: 1 }], + y: self[CellPos { row: 2, col: 0 }], + z: self[CellPos { row: 2, col: 0 }], + w: self[CellPos { row: 2, col: 0 }], }; let vec_3 = Vec4 { - x: self.items[1][3], - y: self.items[0][3], - z: self.items[0][3], - w: self.items[0][3], + x: self[CellPos { row: 3, col: 1 }], + y: self[CellPos { row: 3, col: 0 }], + z: self[CellPos { row: 3, col: 0 }], + w: self[CellPos { row: 3, col: 0 }], }; let inv_0 = vec_1 * fac_0 - vec_2 * fac_1 + vec_3 * fac_2; @@ -251,13 +255,13 @@ impl Matrix<f32, 4, 4> ]); let row_0 = Vec4 { - x: inverse.items[0][0], - y: inverse.items[1][0], - z: inverse.items[2][0], - w: inverse.items[3][0], + x: inverse[CellPos { row: 0, col: 0 }], + y: inverse[CellPos { row: 0, col: 1 }], + z: inverse[CellPos { row: 0, col: 2 }], + w: inverse[CellPos { row: 0, col: 3 }], }; - let dot_0 = Vec4::<f32>::from(self.items[0]) * row_0; + let dot_0 = Vec4::<f32>::from(self.get_column_copied(0)) * row_0; let dot_1 = (dot_0.x + dot_0.y) + (dot_0.z + dot_0.w); @@ -274,9 +278,34 @@ impl Mul<f32> for Matrix<f32, 4, 4> fn mul(self, scalar: f32) -> Self::Output { Self { - items: self - .items - .map(|column| (Vec4::from(column) * scalar).into()), + items: self.items.map(|row| (Vec4::from(row) * scalar).into()), } } } + +impl<Value, const ROWS: usize, const COLUMNS: usize> Index<CellPos> + for Matrix<Value, ROWS, COLUMNS> +{ + type Output = Value; + + fn index(&self, cell_pos: CellPos) -> &Self::Output + { + &self.items[cell_pos.row][cell_pos.col] + } +} + +impl<Value, const ROWS: usize, const COLUMNS: usize> IndexMut<CellPos> + for Matrix<Value, ROWS, COLUMNS> +{ + fn index_mut(&mut self, cell_pos: CellPos) -> &mut Self::Output + { + &mut self.items[cell_pos.row][cell_pos.col] + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct CellPos +{ + pub row: usize, + pub col: usize, +} |
