canvas/src/renderer/matrix.rs

105 lines
3.0 KiB
Rust

#[allow(unused_imports)]
use log::{debug, error, info, trace, warn};
use crate:: utils::Position;
use super::{Uniform, WgpuRenderer};
use cgmath::{
Deg,
Vector2,
Matrix3,
};
pub const MATRIX_SIZE: usize = 48;//std::mem::size_of::<Matrix3<f32>>();
//--ModelMatrix struct------------------------------------------------------------------------------
pub struct ModelMatrix {
position: Position,
rotation: Deg<f32>,
scale: f32,
aspect_matrix: Matrix3<f32>,
uniform: Uniform<MATRIX_SIZE>,
is_synced: bool,
}
impl ModelMatrix {
pub fn new(renderer: &WgpuRenderer,
pos: Position,
rot: f32,
scale: f32)
-> Self
{
let surface_size: Vector2<f32> = renderer.get_surface_size().into();
//A factor 2 is used so scales and offsets can be in sync with the translations wich are
//smaller by a factor 2, and I have no idea why.
let aspect_matrix = Matrix3::from_nonuniform_scale(2.0/surface_size.x, 2.0/surface_size.y)
* Matrix3::from_translation(-surface_size/2.0);
Self {
position: pos,
rotation: Deg (rot),
scale,
aspect_matrix,
uniform: Uniform::create(renderer, &renderer.matrix_layout),
is_synced: false,
}
}
pub fn default(renderer: &WgpuRenderer) -> Self {
Self::new(renderer, Position::origin(), 0.0, 1.0)
}
pub fn set_position(&mut self, pos: Position) {
self.position = pos;
self.is_synced = false;
}
pub fn set_rotation(&mut self, rot: f32) {
self.rotation = Deg (rot);
self.is_synced = false;
}
pub fn set_scale(&mut self, scale: f32) {
self.scale = scale;
self.is_synced = false;
}
pub fn get_uniform(&mut self) -> &mut Uniform<MATRIX_SIZE> {
use cgmath::{Basis3, Rotation3};
if self.is_synced == false {
let translation_mat = Matrix3::from_translation(self.position.into());
let rotation_mat = Matrix3::from(Basis3::from_angle_z(self.rotation));
//same factor 2 as for the aspect ratio and the offset, no idea why its needed either
let scale_mat = Matrix3::from_scale(self.scale/2.0);
let matrix = self.aspect_matrix * translation_mat * scale_mat * rotation_mat;
let mat_bytes: [u8; 36] = bytemuck::bytes_of(&matrix).try_into().unwrap();
//wgsl uses 16 bytes-aligned matrixes, but ours is 12 bytes-aligned. Fix that by adding
//4 paddings bytes after each 12 bytes
let mut bytes = [0; 48];
for i in 0..12 {
bytes[i] = mat_bytes[i];
}
for i in 0..12 {
bytes[i+16] = mat_bytes[i+12];
}
for i in 0..12 {
bytes[i+32] = mat_bytes[i+24];
}
self.uniform.update(bytes);
self.is_synced = true;
}
&mut self.uniform
}
}