105 lines
3.0 KiB
Rust
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
|
|
}
|
|
}
|
|
|