use crate::{
core::algebra::Matrix4,
graphics::{
error::FrameworkError,
gpu_texture::{GpuTexture, GpuTextureDescriptor, GpuTextureKind, PixelKind},
server::GraphicsServer,
},
};
pub struct MatrixStorage {
texture: GpuTexture,
matrices: Vec<Matrix4<f32>>,
}
impl MatrixStorage {
pub fn new(server: &dyn GraphicsServer) -> Result<Self, FrameworkError> {
let identity = [Matrix4::<f32>::identity()];
Ok(Self {
texture: server.create_texture(GpuTextureDescriptor {
name: "MatrixStorage",
kind: GpuTextureKind::Rectangle {
width: 4,
height: 1,
},
pixel_kind: PixelKind::RGBA32F,
data: Some(crate::core::array_as_u8_slice(&identity)),
..Default::default()
})?,
matrices: Default::default(),
})
}
pub fn texture(&self) -> &GpuTexture {
&self.texture
}
pub fn upload(
&mut self,
matrices: impl Iterator<Item = Matrix4<f32>>,
) -> Result<(), FrameworkError> {
self.matrices.clear();
self.matrices.extend(matrices);
let matrices_tex_size = 1024;
let actual_matrices_pixel_count = self.matrices.len() * 4;
let matrices_w = actual_matrices_pixel_count.min(matrices_tex_size);
let matrices_h = (actual_matrices_pixel_count as f32 / matrices_w as f32)
.ceil()
.max(1.0) as usize;
for _ in 0..(((matrices_w * matrices_h) - actual_matrices_pixel_count) / 4) {
self.matrices.push(Default::default());
}
if matrices_w != 0 && matrices_h != 0 {
self.texture.set_data(
GpuTextureKind::Rectangle {
width: matrices_w,
height: matrices_h,
},
PixelKind::RGBA32F,
1,
Some(crate::core::array_as_u8_slice(&self.matrices)),
)?;
}
Ok(())
}
}