summaryrefslogtreecommitdiff
path: root/engine/src/data_types
diff options
context:
space:
mode:
Diffstat (limited to 'engine/src/data_types')
-rw-r--r--engine/src/data_types/matrix.rs170
-rw-r--r--engine/src/data_types/vector.rs141
2 files changed, 306 insertions, 5 deletions
diff --git a/engine/src/data_types/matrix.rs b/engine/src/data_types/matrix.rs
index b754b62..39aeea0 100644
--- a/engine/src/data_types/matrix.rs
+++ b/engine/src/data_types/matrix.rs
@@ -1,4 +1,6 @@
-use crate::vector::Vec3;
+use std::ops::Mul;
+
+use crate::vector::{Vec3, Vec4, VecN};
#[derive(Debug, Clone)]
pub struct Matrix<Value, const ROWS: usize, const COLUMNS: usize>
@@ -20,17 +22,24 @@ impl<Value, const ROWS: usize, const COLUMNS: usize> Matrix<Value, ROWS, COLUMNS
}
}
+ pub fn from_columns<ColumnVec>(columns: [ColumnVec; COLUMNS]) -> Self
+ where
+ ColumnVec: VecN<Value, ROWS>,
+ {
+ Self {
+ items: columns.map(|column| column.into_array()),
+ }
+ }
+
/// Sets the value at the specified cell.
pub fn set_cell(&mut self, row: usize, column: usize, value: Value)
{
self.items[column][row] = value;
}
- /// Returns the internal 2D array as a pointer.
- #[must_use]
- pub fn as_ptr(&self) -> *const Value
+ pub fn items(&self) -> &[[Value; ROWS]; COLUMNS]
{
- self.items[0].as_ptr()
+ &self.items
}
}
@@ -119,4 +128,155 @@ impl Matrix<f32, 4, 4>
self.set_cell(3, 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 fac_0 = Vec4 {
+ x: coef_00,
+ y: coef_00,
+ z: coef_02,
+ w: coef_03,
+ };
+ let fac_1 = Vec4 {
+ x: coef_04,
+ y: coef_04,
+ z: coef_06,
+ w: coef_07,
+ };
+ let fac_2 = Vec4 {
+ x: coef_08,
+ y: coef_08,
+ z: coef_10,
+ w: coef_11,
+ };
+ let fac_3 = Vec4 {
+ x: coef_12,
+ y: coef_12,
+ z: coef_14,
+ w: coef_15,
+ };
+ let fac_4 = Vec4 {
+ x: coef_16,
+ y: coef_16,
+ z: coef_18,
+ w: coef_19,
+ };
+ let fac_5 = Vec4 {
+ x: coef_20,
+ y: coef_20,
+ z: coef_22,
+ w: coef_23,
+ };
+
+ let vec_0 = Vec4 {
+ x: self.items[1][0],
+ y: self.items[0][0],
+ z: self.items[0][0],
+ w: self.items[0][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],
+ };
+ let vec_2 = Vec4 {
+ x: self.items[1][2],
+ y: self.items[0][2],
+ z: self.items[0][2],
+ w: self.items[0][2],
+ };
+ let vec_3 = Vec4 {
+ x: self.items[1][3],
+ y: self.items[0][3],
+ z: self.items[0][3],
+ w: self.items[0][3],
+ };
+
+ let inv_0 = vec_1 * fac_0 - vec_2 * fac_1 + vec_3 * fac_2;
+ let inv_1 = vec_0 * fac_0 - vec_2 * fac_3 + vec_3 * fac_4;
+ let inv_2 = vec_0 * fac_1 - vec_1 * fac_3 + vec_3 * fac_5;
+ let inv_3 = vec_0 * fac_2 - vec_1 * fac_4 + vec_2 * fac_5;
+
+ let sign_a = Vec4 { x: 1.0, y: -1.0, z: 1.0, w: -1.0 };
+ let sign_b = Vec4 { x: -1.0, y: 1.0, z: -1.0, w: 1.0 };
+
+ let inverse = Self::from_columns([
+ inv_0 * sign_a,
+ inv_1 * sign_b,
+ inv_2 * sign_a,
+ inv_3 * sign_b,
+ ]);
+
+ let row_0 = Vec4 {
+ x: inverse.items[0][0],
+ y: inverse.items[1][0],
+ z: inverse.items[2][0],
+ w: inverse.items[3][0],
+ };
+
+ let dot_0 = Vec4::<f32>::from(self.items[0]) * row_0;
+
+ let dot_1 = (dot_0.x + dot_0.y) + (dot_0.z + dot_0.w);
+
+ let one_over_determinant = 1.0 / dot_1;
+
+ inverse * one_over_determinant
+ }
+}
+
+impl Mul<f32> for Matrix<f32, 4, 4>
+{
+ type Output = Self;
+
+ fn mul(self, scalar: f32) -> Self::Output
+ {
+ Self {
+ items: self
+ .items
+ .map(|column| (Vec4::from(column) * scalar).into_array()),
+ }
+ }
}
diff --git a/engine/src/data_types/vector.rs b/engine/src/data_types/vector.rs
index dc6df30..1a4e49e 100644
--- a/engine/src/data_types/vector.rs
+++ b/engine/src/data_types/vector.rs
@@ -2,6 +2,12 @@ use std::ops::{Add, AddAssign, Div, Mul, Neg, Sub, SubAssign};
use crate::color::Color;
+/// A vector of `Value`s with `N` number of elements.
+pub trait VecN<Value, const N: usize>: sealed::Sealed
+{
+ fn into_array(self) -> [Value; N];
+}
+
#[derive(Debug, Default, Clone, Copy, PartialEq)]
pub struct Vec2<Value>
{
@@ -97,6 +103,16 @@ where
}
}
+impl<Value> VecN<Value, 2> for Vec2<Value>
+{
+ fn into_array(self) -> [Value; 2]
+ {
+ [self.x, self.y]
+ }
+}
+
+impl<Value> sealed::Sealed for Vec2<Value> {}
+
#[derive(Debug, Default, Clone, Copy, PartialEq)]
pub struct Vec3<Value>
{
@@ -365,3 +381,128 @@ impl<Value> From<Color<Value>> for Vec3<Value>
}
}
}
+
+impl<Value> VecN<Value, 3> for Vec3<Value>
+{
+ fn into_array(self) -> [Value; 3]
+ {
+ [self.x, self.y, self.z]
+ }
+}
+
+impl<Value> sealed::Sealed for Vec3<Value> {}
+
+#[derive(Debug, Default, Clone, Copy, PartialEq)]
+pub struct Vec4<Value>
+{
+ pub x: Value,
+ pub y: Value,
+ pub z: Value,
+ pub w: Value,
+}
+
+impl<Value> Mul for Vec4<Value>
+where
+ Value: Mul<Value, Output = Value>,
+{
+ type Output = Self;
+
+ fn mul(self, rhs: Self) -> Self::Output
+ {
+ Self::Output {
+ x: self.x * rhs.x,
+ y: self.y * rhs.y,
+ z: self.z * rhs.z,
+ w: self.w * rhs.w,
+ }
+ }
+}
+
+impl<Value> Add for Vec4<Value>
+where
+ Value: Add<Value, Output = Value>,
+{
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self::Output
+ {
+ Self::Output {
+ x: self.x + rhs.x,
+ y: self.y + rhs.y,
+ z: self.z + rhs.z,
+ w: self.w + rhs.w,
+ }
+ }
+}
+
+impl<Value> Sub for Vec4<Value>
+where
+ Value: Sub<Value, Output = Value>,
+{
+ type Output = Self;
+
+ fn sub(self, rhs: Self) -> Self::Output
+ {
+ Self::Output {
+ x: self.x - rhs.x,
+ y: self.y - rhs.y,
+ z: self.z - rhs.z,
+ w: self.w - rhs.w,
+ }
+ }
+}
+
+impl<Value> Mul<Value> for Vec4<Value>
+where
+ Value: Mul<Value, Output = Value> + Clone,
+{
+ type Output = Self;
+
+ fn mul(mut self, rhs: Value) -> Self::Output
+ {
+ self.x = self.x * rhs.clone();
+ self.y = self.y * rhs.clone();
+ self.z = self.z * rhs.clone();
+ self.w = self.w * rhs.clone();
+
+ self
+ }
+}
+
+impl<Value: Clone> From<Value> for Vec4<Value>
+{
+ fn from(value: Value) -> Self
+ {
+ Self {
+ x: value.clone(),
+ y: value.clone(),
+ z: value.clone(),
+ w: value,
+ }
+ }
+}
+
+impl<Value> From<[Value; 4]> for Vec4<Value>
+{
+ fn from(values: [Value; 4]) -> Self
+ {
+ let [x, y, z, w] = values;
+
+ Self { x, y, z, w }
+ }
+}
+
+impl<Value> VecN<Value, 4> for Vec4<Value>
+{
+ fn into_array(self) -> [Value; 4]
+ {
+ [self.x, self.y, self.z, self.w]
+ }
+}
+
+impl<Value> sealed::Sealed for Vec4<Value> {}
+
+mod sealed
+{
+ pub trait Sealed {}
+}