glem 0.1.1

Linear algebra transformation adaptors
Documentation
use glam::f32::Mat4;


pub mod prelude {
    pub use super::Mat;
}

pub fn build_inverse(a: impl Inverse) -> Mat4 {
    let mut m = Mat4::IDENTITY;
    a.apply_inverse(&mut m);
    m
}

pub fn build(a: impl Mat) -> Mat4 {
    let mut m = Mat4::IDENTITY;
    a.apply(&mut m);
    m
}

pub trait Inverse: Mat {
    fn apply_inverse(&self, a: &mut Mat4);
}

impl<T: Inverse> Inverse for &T {
    fn apply_inverse(&self, m: &mut Mat4) {
        (**self).apply_inverse(m)
    }
}

impl Mat for Mat4 {
    fn apply(&self, m: &mut Mat4) {
        *m *= *self;
    }
}

impl Inverse for Mat4 {
    fn apply_inverse(&self, a: &mut Mat4) {
        *a *= self.inverse()
    }
}

impl<T: Mat> Mat for &T {
    fn apply(&self, m: &mut Mat4) {
        (**self).apply(m)
    }
}

pub trait Mat {
    fn apply(&self, m: &mut Mat4);

    fn chain<K: Mat>(self, other: K) -> Chain<Self, K>
    where
        Self: Sized,
    {
        Chain { a: self, b: other }
    }
}

#[derive(Copy, Clone, Debug)]
pub struct Chain<A, B> {
    a: A,
    b: B,
}
impl<A: Inverse, B: Inverse> Inverse for Chain<A, B> {
    fn apply_inverse(&self, a: &mut Mat4) {
        self.b.apply_inverse(a);
        self.a.apply_inverse(a);
    }
}
impl<A: Mat, B: Mat> Mat for Chain<A, B> {
    fn apply(&self, m: &mut Mat4) {
        self.a.apply(m);
        self.b.apply(m);
    }
}

#[derive(Copy, Clone, Debug)]
pub struct Scale {
    pub tx: f32,
    pub ty: f32,
    pub tz: f32,
}

impl Inverse for Scale {
    fn apply_inverse(&self, m: &mut Mat4) {
        scale(1.0 / self.tx, 1.0 / self.ty, 1.0 / self.tz).apply(m)
    }
}
impl Mat for Scale {
    fn apply(&self, m: &mut Mat4) {
        *m *= Mat4::from_cols_array(&[
            self.tx, 0., 0., 0., 0., self.ty, 0., 0., 0., 0., self.tz, 0., 0., 0., 0., 1.0,
        ])
    }
}

#[derive(Copy, Clone, Debug)]
pub struct XRot {
    pub angle_rad: f32,
}
impl Inverse for XRot {
    fn apply_inverse(&self, m: &mut Mat4) {
        rotate_x(-self.angle_rad).apply(m)
    }
}
impl Mat for XRot {
    fn apply(&self, m: &mut Mat4) {
        let c = self.angle_rad.cos();
        let s = self.angle_rad.sin();

        *m *= Mat4::from_cols_array(&[1., 0., 0., 0., 0., c, s, 0., 0., -s, c, 0., 0., 0., 0., 1.])
    }
}

#[derive(Copy, Clone, Debug)]
pub struct YRot {
    pub angle_rad: f32,
}
impl Inverse for YRot {
    fn apply_inverse(&self, m: &mut Mat4) {
        rotate_y(-self.angle_rad).apply(m)
    }
}
impl Mat for YRot {
    fn apply(&self, m: &mut Mat4) {
        let c = self.angle_rad.cos();
        let s = self.angle_rad.sin();

        *m *= Mat4::from_cols_array(&[c, 0., -s, 0., 0., 1., 0., 0., s, 0., c, 0., 0., 0., 0., 1.])
    }
}

#[derive(Copy, Clone, Debug)]
pub struct ZRot {
    pub angle_rad: f32,
}
impl Inverse for ZRot {
    fn apply_inverse(&self, m: &mut Mat4) {
        rotate_z(-self.angle_rad).apply(m)
    }
}
impl Mat for ZRot {
    fn apply(&self, m: &mut Mat4) {
        let c = self.angle_rad.cos();
        let s = self.angle_rad.sin();

        *m *= Mat4::from_cols_array(&[c, s, 0., 0., -s, c, 0., 0., 0., 0., 1., 0., 0., 0., 0., 1.])
    }
}

pub fn rotate_x(angle_rad: f32) -> XRot {
    XRot { angle_rad }
}
pub fn rotate_y(angle_rad: f32) -> YRot {
    YRot { angle_rad }
}
pub fn rotate_z(angle_rad: f32) -> ZRot {
    ZRot { angle_rad }
}

pub fn scale(x: f32, y: f32, z: f32) -> Scale {
    Scale {
        tx: x,
        ty: y,
        tz: z,
    }
}
pub fn translate(tx: f32, ty: f32, tz: f32) -> Translation {
    Translation { tx, ty, tz }
}

#[derive(Copy, Clone, Debug)]
pub struct Translation {
    tx: f32,
    ty: f32,
    tz: f32,
}

impl Inverse for Translation {
    fn apply_inverse(&self, m: &mut Mat4) {
        translate(-self.tx, -self.ty, -self.tz).apply(m)
    }
}
impl Mat for Translation {
    fn apply(&self, m: &mut Mat4) {
        let tx = self.tx;
        let ty = self.ty;
        let tz = self.tz;
        *m *= Mat4::from_cols_array(&[
            1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., tx, ty, tz, 1.,
        ])
    }
}


#[macro_export]
macro_rules! combine {
    ($a:expr)=>{
        $a
    };
    ( $a:expr,$( $x:expr ),* ) => {
        {
            use $crate::Mat;
            let mut a=$a;
            $(
                let a=a.chain($x);
            )*

            a
        }
    };
}