Skip to main content

wgpu_3dgs_viewer/buffer/
camera.rs

1use glam::*;
2
3use crate::{
4    CameraTrait,
5    core::{self, BufferWrapper, FixedSizeBufferWrapper},
6};
7
8/// The camera buffer.
9#[derive(Debug, Clone)]
10pub struct CameraBuffer(wgpu::Buffer);
11
12impl CameraBuffer {
13    /// Create a new camera buffer.
14    pub fn new(device: &wgpu::Device) -> Self {
15        let buffer = device.create_buffer(&wgpu::BufferDescriptor {
16            label: Some("Camera Buffer"),
17            size: std::mem::size_of::<CameraPod>() as u64,
18            usage: Self::DEFAULT_USAGES,
19            mapped_at_creation: false,
20        });
21
22        Self(buffer)
23    }
24
25    /// Update the camera buffer.
26    pub fn update(&self, queue: &wgpu::Queue, camera: &impl CameraTrait, size: UVec2) {
27        self.update_with_pod(queue, &CameraPod::new(camera, size));
28    }
29
30    /// Update the camera buffer with [`CameraPod`].
31    pub fn update_with_pod(&self, queue: &wgpu::Queue, pod: &CameraPod) {
32        queue.write_buffer(&self.0, 0, bytemuck::bytes_of(pod));
33    }
34}
35
36impl BufferWrapper for CameraBuffer {
37    fn buffer(&self) -> &wgpu::Buffer {
38        &self.0
39    }
40}
41
42impl From<CameraBuffer> for wgpu::Buffer {
43    fn from(wrapper: CameraBuffer) -> Self {
44        wrapper.0
45    }
46}
47
48impl TryFrom<wgpu::Buffer> for CameraBuffer {
49    type Error = core::FixedSizeBufferWrapperError;
50
51    fn try_from(buffer: wgpu::Buffer) -> Result<Self, Self::Error> {
52        Self::verify_buffer_size(&buffer).map(|()| Self(buffer))
53    }
54}
55
56impl FixedSizeBufferWrapper for CameraBuffer {
57    type Pod = CameraPod;
58}
59
60/// The POD representation of camera.
61#[repr(C)]
62#[derive(Debug, Clone, Copy, PartialEq, bytemuck::Pod, bytemuck::Zeroable)]
63pub struct CameraPod {
64    pub view: Mat4,
65    pub proj: Mat4,
66    pub size: Vec2,
67    pub _padding: [u32; 2],
68}
69
70impl CameraPod {
71    /// Create a new camera.
72    pub fn new(camera: &impl CameraTrait, size: UVec2) -> Self {
73        Self {
74            view: camera.view(),
75            proj: camera.projection(size.x as f32 / size.y as f32),
76            size: size.as_vec2(),
77            _padding: [0; 2],
78        }
79    }
80}