make camera follow player
This commit is contained in:
parent
fb86f3a038
commit
56c05ccfdf
@ -1,11 +1,12 @@
|
||||
use cgmath::{Vector3, Point3, InnerSpace, Deg, Rad};
|
||||
use cgmath::{Vector3, Point3, InnerSpace, Deg, Rad, Matrix4};
|
||||
|
||||
use crate::input::Input;
|
||||
use crate::{input::Input, player::Player};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Camera {
|
||||
pub position: Point3<f32>,
|
||||
pub rot_x: Deg<f32>,
|
||||
pub target: Point3<f32>,
|
||||
|
||||
pub rot_y: Deg<f32>,
|
||||
|
||||
aspect: f32,
|
||||
@ -14,6 +15,10 @@ pub struct Camera {
|
||||
zfar: f32,
|
||||
}
|
||||
|
||||
fn pitch_clamp(pitch: f32) -> Deg<f32> {
|
||||
const PITCH_LIM: f32 = 90.0 - 0.0001;
|
||||
return Deg(pitch.clamp(-PITCH_LIM, PITCH_LIM));
|
||||
}
|
||||
impl Camera {
|
||||
pub fn new<
|
||||
V: Into<Point3<f32>>,
|
||||
@ -21,63 +26,50 @@ impl Camera {
|
||||
dimensions: winit::dpi::PhysicalSize<u32>,
|
||||
|
||||
position: V,
|
||||
rot_x: Deg<f32>,
|
||||
rot_y: Deg<f32>
|
||||
rot_y: Deg<f32>,
|
||||
) -> Self {
|
||||
return Self {
|
||||
position: position.into(),
|
||||
rot_x: rot_x,
|
||||
rot_y: rot_y,
|
||||
target: (0.0, 0.0, 0.0).into(),
|
||||
rot_y: pitch_clamp(rot_y.0),
|
||||
|
||||
aspect: dimensions.width as f32 / dimensions.height as f32,
|
||||
fovy: Deg(45.0),
|
||||
fovy: Deg(40.0),
|
||||
znear: 0.1,
|
||||
zfar: 100.0,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl Camera {
|
||||
pub fn reconfigure(&mut self, dimensions: winit::dpi::PhysicalSize<u32>) {
|
||||
self.aspect = dimensions.width as f32 / dimensions.height as f32;
|
||||
return;
|
||||
}
|
||||
|
||||
pub fn update_pos(&mut self, input: &Input, dt: f32) {
|
||||
let (yaw_sin, yaw_cos) = Rad::from(self.rot_x).0.sin_cos();
|
||||
let forward = Vector3::new(yaw_cos, 0.0, yaw_sin).normalize();
|
||||
let right = Vector3::new(-yaw_sin, 0.0, yaw_cos).normalize();
|
||||
self.position += forward * (input.amount_forward - input.amount_backward) * (input.speed * dt);
|
||||
self.position += right * (input.amount_right - input.amount_left) * (input.speed * dt);
|
||||
pub fn update_pos(&mut self, player: &Player) {
|
||||
self.target = player.position;
|
||||
|
||||
self.position.y += (input.amount_up - input.amount_down) * (input.speed * dt);
|
||||
let (sin_yaw, cos_yaw) = Rad::from(player.rot_x).0.sin_cos();
|
||||
let (sin_pitch, cos_pitch) = Rad::from(self.rot_y).0.sin_cos();
|
||||
|
||||
let v = Vector3::new(
|
||||
cos_pitch * cos_yaw,
|
||||
sin_pitch,
|
||||
cos_pitch * sin_yaw
|
||||
).normalize();
|
||||
|
||||
self.position = self.target - v;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
pub fn update_rot(&mut self, input: &Input, sf: f32) {
|
||||
// doesn't need dt because the input is not continuous.
|
||||
let (dx, dy) = input.mouse_moved;
|
||||
let (_, dy) = input.mouse_moved;
|
||||
|
||||
self.rot_x += Deg((dx / input.dots_per_deg) * sf);
|
||||
let pitch_lim = 90.0 - 0.0001;
|
||||
let pitch = self.rot_y.0 + ((-dy / input.dots_per_deg) * sf);
|
||||
self.rot_y = Deg(pitch.clamp(-pitch_lim, pitch_lim));
|
||||
self.rot_y = pitch_clamp(self.rot_y.0 + ((-dy / input.dots_per_deg) * sf));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
pub fn position(&self, t: f32) -> Point3<f32> {
|
||||
let (sin_yaw, cos_yaw) = Rad::from(self.rot_x).0.sin_cos();
|
||||
let (sin_pitch, cos_pitch) = Rad::from(self.rot_y).0.sin_cos();
|
||||
|
||||
let target = Vector3::new(
|
||||
cos_pitch * cos_yaw,
|
||||
sin_pitch,
|
||||
cos_pitch * sin_yaw
|
||||
).normalize();
|
||||
return self.position + (target * t);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CameraUniform {
|
||||
@ -105,16 +97,15 @@ impl<'a> CameraUniform {
|
||||
};
|
||||
}
|
||||
pub fn set_view_projection_matrix(&self, queue: &wgpu::Queue, camera: &Camera) {
|
||||
let (sin_yaw, cos_yaw) = Rad::from(camera.rot_x).0.sin_cos();
|
||||
let (sin_pitch, cos_pitch) = Rad::from(camera.rot_y).0.sin_cos();
|
||||
|
||||
/*let (sin_yaw, cos_yaw) = Rad::from(camera.rot.x).0.sin_cos();
|
||||
let (sin_pitch, cos_pitch) = Rad::from(camera.rot.y).0.sin_cos();
|
||||
let target = Vector3::new(
|
||||
cos_pitch * cos_yaw,
|
||||
sin_pitch,
|
||||
cos_pitch * sin_yaw
|
||||
).normalize();
|
||||
).normalize();*/
|
||||
|
||||
let view = cgmath::Matrix4::look_to_rh(camera.position, target, Vector3::unit_y());
|
||||
let view = Matrix4::look_to_rh(camera.position, camera.target - camera.position, Vector3::unit_y());
|
||||
let proj = cgmath::perspective(camera.fovy, camera.aspect, camera.znear, camera.zfar);
|
||||
let transformed_proj: [[f32; 4]; 4] = (Self::OPENGL_TO_WGPU_MATRIX * proj * view).into();
|
||||
queue.write_buffer(&(self.buffer), 0, bytemuck::cast_slice(&(transformed_proj)));
|
||||
|
@ -1,7 +1,30 @@
|
||||
use cgmath::{Point3, Deg};
|
||||
use cgmath::{Point3, Deg, Vector3, Rad, InnerSpace};
|
||||
use crate::input::Input;
|
||||
|
||||
pub struct Player {
|
||||
pub position: Point3<f32>,
|
||||
pub rot_x: Deg<f32>,
|
||||
|
||||
pub buffer: wgpu::Buffer,
|
||||
}
|
||||
|
||||
impl Player {
|
||||
pub fn update_pos(&mut self, input: &Input, dt: f32) {
|
||||
let (sin, cos) = Rad::from(self.rot_x).0.sin_cos();
|
||||
let forward = Vector3::new(cos, 0.0, sin).normalize();
|
||||
let right = Vector3::new(-sin, 0.0, cos).normalize();
|
||||
self.position += forward * (input.amount_forward - input.amount_backward) * (input.speed * dt);
|
||||
self.position += right * (input.amount_right - input.amount_left) * (input.speed * dt);
|
||||
|
||||
self.position.y += (input.amount_up - input.amount_down) * (input.speed * dt);
|
||||
|
||||
return;
|
||||
}
|
||||
pub fn update_rot(&mut self, input: &Input, sf: f32) {
|
||||
// doesn't need dt because the input is not continuous.
|
||||
let (dx, _) = input.mouse_moved;
|
||||
self.rot_x += Deg((dx / input.dots_per_deg) * sf);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
20
src/state.rs
20
src/state.rs
@ -1,4 +1,4 @@
|
||||
use cgmath::{Deg, Vector3, Matrix3, Quaternion, Rad, Point3, EuclideanSpace};
|
||||
use cgmath::{Deg, Rad, Point3, EuclideanSpace};
|
||||
use winit::window::Window;
|
||||
use wgpu::{util::DeviceExt, BufferAddress};
|
||||
|
||||
@ -128,7 +128,7 @@ impl State {
|
||||
mapped_at_creation: false,
|
||||
}));
|
||||
|
||||
let camera = Camera::new(size, (0.25, 1.0, 0.0), Deg(0.0), Deg(-90.0));
|
||||
let camera = Camera::new(size, (0.25, 1.0, 0.0), Deg(-90.0));
|
||||
|
||||
let camera_bind_group_layout = &(device.create_bind_group_layout(&(wgpu::BindGroupLayoutDescriptor {
|
||||
entries: &[
|
||||
@ -217,7 +217,8 @@ impl State {
|
||||
}));
|
||||
|
||||
let player = Player {
|
||||
position: (0.0, 0.0, 0.0).into(),
|
||||
position: (1.0, 0.0, -1.0).into(),
|
||||
rot_x: Deg(0.0),
|
||||
buffer: device.create_buffer(&(wgpu::BufferDescriptor {
|
||||
label: Some("player_buffer"),
|
||||
usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
|
||||
@ -396,7 +397,7 @@ impl State {
|
||||
vertices[0],
|
||||
];
|
||||
}
|
||||
// render the player in-front of the camera
|
||||
// (USED TO) render the player in-front of the camera
|
||||
// this should really be done the other way
|
||||
// around though; the camera should be placed
|
||||
// *behind the player*, and the camera should
|
||||
@ -405,9 +406,9 @@ impl State {
|
||||
// (the camera should rotate around the player,
|
||||
// and the player should also rotate so that
|
||||
// its back is facing the camera.)
|
||||
self.queue.write_buffer(&(&self.player.buffer), 0, bytemuck::cast_slice(&(rot_rect(
|
||||
0.1, 0.2, Rad::from(self.camera.rot_x)
|
||||
).map(|point| Vertex { position: (self.camera.position(1.0) + point.to_vec()).into(), color: [1.0, 1.0, 1.0] }))));
|
||||
self.queue.write_buffer(&(self.player.buffer), 0, bytemuck::cast_slice(&(rot_rect(
|
||||
0.1, 0.2, Rad::from(self.player.rot_x)
|
||||
).map(|point| Vertex { position: (self.player.position + point.to_vec()).into(), color: [1.0, 1.0, 1.0] }))));
|
||||
render_pass.set_vertex_buffer(0, self.player.buffer.slice(..));
|
||||
render_pass.draw(0..6, 0..1);
|
||||
|
||||
@ -441,8 +442,11 @@ impl State {
|
||||
}
|
||||
|
||||
pub fn update_camera(&mut self, dt: f32, sf: f32) {
|
||||
self.camera.update_pos(&(self.input), dt);
|
||||
self.player.update_pos(&(self.input), dt);
|
||||
self.player.update_rot(&(self.input), sf);
|
||||
|
||||
self.camera.update_rot(&(self.input), sf);
|
||||
self.camera.update_pos(&(self.player));
|
||||
return;
|
||||
}
|
||||
pub fn process_key(&mut self, key: winit::event::VirtualKeyCode, state: winit::event::ElementState) {
|
||||
|
Loading…
Reference in New Issue
Block a user