summaryrefslogtreecommitdiff
path: root/src/gfx/camera.rs
blob: 874c9fc303327893a37d04d2ed1aa98e741fe819 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
use super::{gpu::Gpu, util::MatrixUniform};
use cgmath::{prelude::*, Deg, Matrix4, Rad};
use collision::Frustum;
use fps_camera::{FirstPerson, FirstPersonSettings};
use std::time::Duration;

pub struct Camera {
    pub fov: Rad<f32>,
    pub view: Matrix4<f32>,
    pub proj: Matrix4<f32>,
    pub frustum: Frustum<f32>,
    pub first_person: FirstPerson,
    pub uniform: MatrixUniform,
    pub layout: wgpu::BindGroupLayout,
}

impl Camera {
    pub fn new(gpu: &Gpu) -> Self {
        let first_person = FirstPerson::new(
            [0.0, 0.0, 0.0],
            FirstPersonSettings {
                speed_horizontal: 10.0,
                speed_vertical: 10.0,
                mouse_sensitivity_horizontal: 1.0,
                mouse_sensitivity_vertical: 1.0,
            },
        );

        let layout = MatrixUniform::layout(&gpu.device, "camera");
        let uniform = MatrixUniform::new(&gpu.device, &layout, Matrix4::identity(), "camera", true);

        Self {
            fov: Deg(90.0).into(),
            proj: Matrix4::identity(),
            view: Matrix4::identity(),
            frustum: Frustum::from_matrix4(Matrix4::identity()).unwrap(),
            first_person,
            uniform,
            layout,
        }
    }

    pub fn update(&mut self, gpu: &Gpu, dt: Duration) {
        self.first_person.yaw += Rad::from(Deg(180.0)).0;
        self.first_person.yaw *= -1.0;

        let cam = self.first_person.camera(dt.as_secs_f32());

        self.first_person.yaw *= -1.0;
        self.first_person.yaw -= Rad::from(Deg(180.0)).0;

        self.first_person.position = cam.position;

        self.view = Matrix4::from(cam.orthogonal());
        self.uniform.set(&gpu.queue, self.proj * self.view);
    }

    pub fn resize(&mut self, size: winit::dpi::PhysicalSize<u32>) {
        self.proj = cgmath::perspective(
            self.fov,
            size.width as f32 / size.height as f32,
            0.1,
            100000.0,
        );
        self.frustum = Frustum::from_matrix4(self.proj).unwrap();
    }
}