qqx 0.0.4

qqx is a 3d library for rust based on OpenGL
Documentation
use glium::{
    glutin::dpi::PhysicalSize,
    vertex::{Attribute, AttributeType}
};
use core::convert::From;

macro_rules! vec {
    ($($ty:ident : $uniform:ident : $size:literal : $($elem:ident $count:literal)* : $i8:ident : $u8:ident : $i16:ident : $u16:ident : $i32:ident : $u32:ident : $i64:ident : $u64:ident : $f32:ident : $f64:ident,)*) => {$(
        #[derive(Debug)]
        pub struct $ty <T> {
            $(pub $elem : T,)*
        }

        impl <T> Clone for $ty <T> where T: Clone {
            fn clone(&self) -> Self {
                Self { $($elem: self.$elem.clone(),)* }
            }
        }

        impl <T> Copy for $ty <T> where T: Copy { }

        impl <T> Default for $ty <T> where T: Default {
            fn default() -> Self {
                Self { $($elem: T::default(),)* }
            }
        }

        vec!{ @op $ty, Add, AddAssign, add, add_assign, +, $($elem)* }
        vec!{ @op $ty, Sub, SubAssign, sub, sub_assign, -, $($elem)* }
        vec!{ @op $ty, Mul, MulAssign, mul, mul_assign, *, $($elem)* }
        vec!{ @op $ty, Div, DivAssign, div, div_assign, /, $($elem)* }
        vec!{ @op $ty, Rem, RemAssign, rem, rem_assign, %, $($elem)* }

        impl <T> core::ops::Neg for $ty <T> where T: core::ops::Neg <Output = T> {
            type Output = Self;

            fn neg(self) -> Self::Output {
                Self { $($elem: -self.$elem,)* }
            }
        }

        impl <T> From <[T; $size]> for $ty <T> where T: Copy {
            fn from(x: [T; $size]) -> Self {
                Self { $($elem: x[$count],)* }
            }
        }

        impl <T> From <$ty <T>> for [T; $size] where T: Copy {
            fn from(x: $ty <T>) -> Self {
                [$(x.$elem,)*]
            }
        }

        impl glium::uniforms::AsUniformValue for $ty <f32> {
            fn as_uniform_value(&self) -> glium::uniforms::UniformValue <'_> {
                glium::uniforms::UniformValue::$uniform((*self).into())
            }
        }

        impl <T> $ty <T> {
            pub fn new($($elem: T,)*) -> Self {
                Self { $($elem,)* }
            }
        }

        vec!{ @at $ty i8 $i8 }
        vec!{ @at $ty u8 $u8 }
        vec!{ @at $ty i16 $i16 }
        vec!{ @at $ty u16 $u16 }
        vec!{ @at $ty i32 $i32 }
        vec!{ @at $ty u32 $u32 }
        vec!{ @at $ty i64 $i64 }
        vec!{ @at $ty u64 $u64 }
        vec!{ @at $ty f32 $f32 }
        vec!{ @at $ty f64 $f64 }

    )*};

    (@op $ty:ident, $big:ident, $big_assign:ident, $low:ident, $low_assign:ident, $op:tt, $($elem:ident)*) => {
        impl <T> core::ops::$big for $ty <T> where T: core::ops::$big <Output = T> {
            type Output = Self;

            fn $low(self, rhs: Self) -> Self::Output {
                Self::Output { $($elem: self.$elem $op rhs.$elem,)* }
            }
        }

        impl <T> core::ops::$big_assign for $ty <T> where T: core::ops::$big <Output = T> + Copy {
            fn $low_assign(&mut self, rhs: Self) {
                *self = *self $op rhs
            }
        }

        impl <T> core::ops::$big <T> for $ty <T> where T: core::ops::$big <Output = T> + Copy {
            type Output = Self;

            fn $low(self, rhs: T) -> Self::Output {
                Self::Output { $($elem: self.$elem $op rhs,)* }
            }
        }

        impl <T> core::ops::$big_assign <T> for $ty <T> where T: core::ops::$big <Output = T> + Copy {
            fn $low_assign(&mut self, rhs: T) {
                *self = *self $op rhs
            }
        }
    };

    (@at $name:ident $ty:ident $id:ident) => {
        unsafe impl Attribute for $name <$ty> {
            #[inline]
            fn get_type() -> AttributeType {
                AttributeType::$id
            }
        }
    };
}

vec! {
    Vec1 : Float : 1 : x 0             : I8       : U8       : I16          : U16          : I32          : U32          : I64          : U64          : F32          : F64,
    Vec2 : Vec2  : 2 : x 0 y 1         : I8I8     : U8U8     : I16I16       : U16U16       : I32I32       : U32U32       : I64I64       : U64U64       : F32F32       : F64F64,
    Vec3 : Vec3  : 3 : x 0 y 1 z 2     : I8I8I8   : U8U8U8   : I16I16I16    : U16U16U16    : I32I32I32    : U32U32U32    : I64I64I64    : U64U64U64    : F32F32F32    : F64F64F64,
    Vec4 : Vec4  : 4 : x 0 y 1 z 2 w 3 : I8I8I8I8 : U8U8U8U8 : I16I16I16I16 : U16U16U16U16 : I32I32I32I32 : U32U32U32U32 : I64I64I64I64 : U64U64U64U64 : F32F32F32F32 : F64F64F64F64,
}

impl <T> From <T> for Vec1 <T> {
    fn from(x: T) -> Self {
        Self { x }
    }
}

impl From <Vec1 <f32>> for f32 {
    fn from(x: Vec1 <f32>) -> Self {
        x.x
    }
}

impl <T> From <PhysicalSize <T>> for Vec2 <T> {
    fn from(x: PhysicalSize <T>) -> Self {
        Self {
            x: x.width,
            y: x.height
        }
    }
}

impl <T> From <Vec2 <T>> for PhysicalSize <T> {
    fn from(x: Vec2 <T>) -> Self {
        Self {
            width:  x.x,
            height: x.y
        }
    }
}