use glam::*;
use wgpu::util::DeviceExt;
use crate::{BufferWrapper, FixedSizeBufferWrapper, FixedSizeBufferWrapperError};
#[derive(Debug, Clone)]
pub struct ModelTransformBuffer(wgpu::Buffer);
impl ModelTransformBuffer {
pub fn new(device: &wgpu::Device) -> Self {
let buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Model transform Buffer"),
contents: bytemuck::bytes_of(&ModelTransformPod::default()),
usage: Self::DEFAULT_USAGES,
});
Self(buffer)
}
pub fn update(&self, queue: &wgpu::Queue, pos: Vec3, rot: Quat, scale: Vec3) {
self.update_with_pod(queue, &ModelTransformPod::new(pos, rot, scale));
}
pub fn update_with_pod(&self, queue: &wgpu::Queue, pod: &ModelTransformPod) {
queue.write_buffer(&self.0, 0, bytemuck::bytes_of(pod));
}
}
impl BufferWrapper for ModelTransformBuffer {
fn buffer(&self) -> &wgpu::Buffer {
&self.0
}
}
impl From<ModelTransformBuffer> for wgpu::Buffer {
fn from(wrapper: ModelTransformBuffer) -> Self {
wrapper.0
}
}
impl TryFrom<wgpu::Buffer> for ModelTransformBuffer {
type Error = FixedSizeBufferWrapperError;
fn try_from(buffer: wgpu::Buffer) -> Result<Self, Self::Error> {
Self::verify_buffer_size(&buffer).map(|()| Self(buffer))
}
}
impl FixedSizeBufferWrapper for ModelTransformBuffer {
type Pod = ModelTransformPod;
}
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, bytemuck::Pod, bytemuck::Zeroable)]
pub struct ModelTransformPod {
pub pos: Vec3A,
pub rot: Quat,
pub scale: Vec3A,
}
impl ModelTransformPod {
pub const fn new(pos: Vec3, rot: Quat, scale: Vec3) -> Self {
Self {
pos: Vec3A::from_array(pos.to_array()),
rot,
scale: Vec3A::from_array(scale.to_array()),
}
}
}
impl Default for ModelTransformPod {
fn default() -> Self {
Self::new(Vec3::ZERO, Quat::IDENTITY, Vec3::ONE)
}
}