aluminium 0.1.0

vulkan-based graphics engine
use ash::vk;
use bytemuck::{Pod, Zeroable};

use crate::core::{Device, GpuBuffer, GpuBufferBuilder, VulkanResult};
use crate::per_frame::{PerFrameBuffer, PerFrameBufferBuilder};

#[repr(C)]
#[derive(Clone, Copy, Pod, Zeroable)]
pub struct CameraData {
    view: [[f32; 4]; 4],
    proj: [[f32; 4]; 4],
    view_proj: [[f32; 4]; 4],
    inv_view: [[f32; 4]; 4],
    inv_proj: [[f32; 4]; 4],
    inv_view_proj: [[f32; 4]; 4],
}

impl CameraData {
    pub fn identity() -> Self {
        Self {
            view: [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]],
            proj: [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]],
            view_proj: [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]],
            inv_view: [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]],
            inv_proj: [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]],
            inv_view_proj: [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]],
        }
    }
}

pub struct Camera {
    pub(crate) is_dirty: bool,
    pub(crate) buffer: PerFrameBuffer,
    pub(crate) data: CameraData,
}

impl Camera {

    pub fn proj(&mut self) -> &[[f32; 4]; 4] {
        &self.data.proj
    }

    pub fn view(&mut self) -> &[[f32; 4]; 4] {
        &self.data.view
    }

    pub fn view_mut(&mut self) -> &mut [[f32; 4]; 4] {
        self.is_dirty = true;
        &mut self.data.view
    }

    pub fn proj_mut(&mut self) -> &mut [[f32; 4]; 4] {
        self.is_dirty = true;
        &mut self.data.proj
    }

    pub fn new(device: &Device, frame_count: usize) -> VulkanResult<Self> {
        let size = size_of::<CameraData>() as u64;

        let mut buffer = PerFrameBufferBuilder::new(device)
            .buffer_size(size)
            .frame_count(frame_count)
            .usage(vk::BufferUsageFlags::UNIFORM_BUFFER)
            .build()?;

        let data = CameraData::identity();

        for i in 0..frame_count {
            let buffer = buffer.get_mut(i as u32);
            buffer.upload_data(device, &[data])?;
        }

        Ok(Self { 
            is_dirty: false, 
            buffer, 
            data 
        })
    }
}