use crate::core::{math::vec3::Vec3, Float};
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Mat3 {
e: [[Float; 3]; 3],
}
impl Mat3 {
#[allow(clippy::too_many_arguments)]
pub fn new(
e00: Float,
e01: Float,
e02: Float,
e10: Float,
e11: Float,
e12: Float,
e20: Float,
e21: Float,
e22: Float,
) -> Self {
Self {
e: [[e00, e01, e02], [e10, e11, e12], [e20, e21, e22]],
}
}
pub fn transpose(&self) -> Self {
Self::new(
self.e[0][0],
self.e[1][0],
self.e[2][0],
self.e[0][1],
self.e[1][1],
self.e[2][1],
self.e[0][2],
self.e[1][2],
self.e[2][2],
)
}
pub fn from_euler_angles(k: Float, l: Float, m: Float) -> Self {
let (sin_k, cos_k) = k.sin_cos();
let (sin_l, cos_l) = l.sin_cos();
let (sin_m, cos_m) = m.sin_cos();
Self::new(
cos_l * cos_m,
sin_k * sin_l * cos_m - cos_k * sin_m,
cos_k * sin_l * cos_m + sin_k * sin_m,
cos_l * sin_m,
sin_k * sin_l * sin_m + cos_k * cos_m,
cos_k * sin_l * sin_m - sin_k * cos_m,
-sin_l,
sin_k * cos_l,
cos_k * cos_l,
)
}
}
impl std::ops::Mul<Vec3> for Mat3 {
type Output = Vec3;
fn mul(self, rhs: Vec3) -> Vec3 {
Vec3::new(
self.e[0][0] * rhs.x() + self.e[0][1] * rhs.y() + self.e[0][2] * rhs.z(),
self.e[1][0] * rhs.x() + self.e[1][1] * rhs.y() + self.e[1][2] * rhs.z(),
self.e[2][0] * rhs.x() + self.e[2][1] * rhs.y() + self.e[2][2] * rhs.z(),
)
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_mat3_mul_vec3() {
use super::*;
let mat = Mat3::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7., 8.0, 9.0);
let vec = Vec3::new(1.0, 2.0, 3.0);
let res = mat * vec;
assert_eq!(res, Vec3::new(14.0, 32.0, 50.0));
}
#[test]
fn test_mat3_transpose() {
use super::*;
let mat = Mat3::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7., 8.0, 9.0);
let res = mat.transpose();
assert_eq!(res, Mat3::new(1.0, 4.0, 7.0, 2.0, 5.0, 8.0, 3., 6.0, 9.0));
}
#[test]
fn test_mat3_from_euler_angles() {
let (k, l, m) = (0.0, 0.0, 0.0); let mat = Mat3::from_euler_angles(k, l, m);
assert_eq!(mat, Mat3::new(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0));
}
}