specs_camera 0.3.6

camera 2d and 3d component for specs
Documentation
use std::ops::{Add, Div, Mul, Neg, Sub};

use mat4;
use num_traits::{Float, FromPrimitive};

use specs::{Component, VecStorage};

pub struct Camera3D<T> {
    fov: T,
    near: T,
    far: T,
    ortho_size: T,
    ortho_mode: bool,
    projection: [T; 16],
    view: [T; 16],
}

impl<T> Component for Camera3D<T>
where
    T: 'static + Sync + Send,
{
    type Storage = VecStorage<Self>;
}

impl<T> Default for Camera3D<T>
where
    T: Float + FromPrimitive,
{
    #[inline(always)]
    fn default() -> Self {
        Camera3D {
            fov: T::from_usize(35).unwrap(),
            near: T::from_f32(::std::f32::EPSILON).unwrap(),
            far: T::from_usize(1024).unwrap(),
            ortho_size: T::from_usize(2).unwrap(),
            ortho_mode: false,
            projection: mat4::new_identity(),
            view: mat4::new_identity(),
        }
    }
}

impl<T> Camera3D<T>
where
    T: Float + FromPrimitive,
    for<'a, 'b> &'a T: Sub<&'b T, Output = T>
        + Add<&'b T, Output = T>
        + Div<&'b T, Output = T>
        + Mul<&'b T, Output = T>
        + Neg<Output = T>,
{
    #[inline(always)]
    pub fn new() -> Self {
        Self::default()
    }

    #[inline(always)]
    pub fn fov(&self) -> T {
        self.ortho_size
    }
    #[inline(always)]
    pub fn set_fov(&mut self, fov: T) {
        self.fov = fov;
    }

    #[inline(always)]
    pub fn near(&self) -> T {
        self.near
    }
    #[inline(always)]
    pub fn set_near(&mut self, near: T) {
        self.near = near;
    }

    #[inline(always)]
    pub fn far(&self) -> T {
        self.far
    }
    #[inline(always)]
    pub fn set_far(&mut self, far: T) {
        self.far = far;
    }

    #[inline(always)]
    pub fn ortho_size(&self) -> T {
        self.ortho_size
    }
    #[inline(always)]
    pub fn set_ortho_size(&mut self, ortho_size: T) {
        self.ortho_size = ortho_size;
    }

    #[inline(always)]
    pub fn ortho_mode(&self) -> bool {
        self.ortho_mode
    }
    #[inline(always)]
    pub fn set_ortho_mode(&mut self, ortho_mode: bool) {
        self.ortho_mode = ortho_mode;
    }

    #[inline(always)]
    pub fn projection(&self) -> &[T; 16] {
        &self.projection
    }

    #[inline(always)]
    pub fn view(&self) -> &[T; 16] {
        &self.view
    }

    #[inline]
    pub fn update_view(&mut self, matrix: &[T; 16]) {
        mat4::inv(&mut self.view, matrix);
    }

    #[inline]
    pub fn update_projection(&mut self, width: usize, height: usize) {
        let w = T::from_usize(width).unwrap();
        let h = T::from_usize(height).unwrap();
        let w_gt_h = &w > &h;
        let aspect = if w_gt_h { &w / &h } else { &h / &w };

        if self.ortho_mode {
            let ortho_size_aspect = &self.ortho_size * &aspect;
            let r = if w_gt_h {
                ortho_size_aspect
            } else {
                self.ortho_size
            };
            let l = -&r;
            let t = if w_gt_h {
                self.ortho_size
            } else {
                ortho_size_aspect
            };
            let b = -&t;
            mat4::orthographic(&mut self.projection, &t, &r, &b, &l, &self.near, &self.far);
        } else {
            mat4::perspective(
                &mut self.projection,
                &self.fov,
                &aspect,
                &self.near,
                &self.far,
            );
        }
    }
}