First efforts towards removing world_state and hud_state
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
ec6978fee9
commit
11348f8086
8 changed files with 271 additions and 284 deletions
|
@ -84,7 +84,7 @@ impl GeometryBuffers<u16> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GeometryBuffers<u32> {
|
impl GeometryBuffers<u32> {
|
||||||
pub fn set_buffers<'a>(&'a self, render_pass: &mut RenderPass<'a>) {
|
pub fn apply_buffers<'a>(&'a self, render_pass: &mut RenderPass<'a>) {
|
||||||
render_pass.set_vertex_buffer(0, self.vertices.slice(..));
|
render_pass.set_vertex_buffer(0, self.vertices.slice(..));
|
||||||
render_pass.set_index_buffer(self.indices.slice(..), wgpu::IndexFormat::Uint32);
|
render_pass.set_index_buffer(self.indices.slice(..), wgpu::IndexFormat::Uint32);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ mod vertex;
|
||||||
mod view;
|
mod view;
|
||||||
mod world;
|
mod world;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
mod player;
|
||||||
|
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
use wgpu::SwapChainError;
|
use wgpu::SwapChainError;
|
||||||
|
|
138
src/player.rs
Normal file
138
src/player.rs
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use cgmath::{InnerSpace, Point3, Rad, Vector3};
|
||||||
|
|
||||||
|
use crate::{aabb::Aabb, render_context::RenderContext, utils, view::View, world::World};
|
||||||
|
|
||||||
|
pub struct Player {
|
||||||
|
pub sprinting: bool,
|
||||||
|
pub creative: bool,
|
||||||
|
|
||||||
|
pub forward_pressed: bool,
|
||||||
|
pub backward_pressed: bool,
|
||||||
|
pub left_pressed: bool,
|
||||||
|
pub right_pressed: bool,
|
||||||
|
pub up_speed: f32,
|
||||||
|
|
||||||
|
pub view: View,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Player {
|
||||||
|
pub fn new(render_context: &RenderContext) -> Self {
|
||||||
|
let view = View::new(render_context);
|
||||||
|
|
||||||
|
Self {
|
||||||
|
sprinting: false,
|
||||||
|
creative: false,
|
||||||
|
view,
|
||||||
|
forward_pressed: false,
|
||||||
|
backward_pressed: false,
|
||||||
|
left_pressed: false,
|
||||||
|
right_pressed: false,
|
||||||
|
up_speed: 0.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Update the camera based on mouse dx and dy.
|
||||||
|
pub fn update_camera(&mut self, dx: f64, dy: f64) {
|
||||||
|
let camera = &mut self.view.camera;
|
||||||
|
camera.yaw += Rad(dx as f32 * 0.003);
|
||||||
|
camera.pitch -= Rad(dy as f32 * 0.003);
|
||||||
|
|
||||||
|
if camera.pitch < Rad::from(cgmath::Deg(-80.0)) {
|
||||||
|
camera.pitch = Rad::from(cgmath::Deg(-80.0));
|
||||||
|
} else if camera.pitch > Rad::from(cgmath::Deg(89.9)) {
|
||||||
|
camera.pitch = Rad::from(cgmath::Deg(89.9));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Updates the player's position by their velocity, checks for and
|
||||||
|
/// resolves any subsequent collisions, and then adds the jumping speed to
|
||||||
|
/// the velocity.
|
||||||
|
pub fn update_position(&mut self, dt: Duration, world: &World) {
|
||||||
|
let (yaw_sin, yaw_cos) = self.view.camera.yaw.0.sin_cos();
|
||||||
|
|
||||||
|
let speed = 10.0 * (self.sprinting as i32 * 2 + 1) as f32 * dt.as_secs_f32();
|
||||||
|
|
||||||
|
let forward_speed = self.forward_pressed as i32 - self.backward_pressed as i32;
|
||||||
|
let forward = Vector3::new(yaw_cos, 0.0, yaw_sin) * forward_speed as f32;
|
||||||
|
|
||||||
|
let right_speed = self.right_pressed as i32 - self.left_pressed as i32;
|
||||||
|
let right = Vector3::new(-yaw_sin, 0.0, yaw_cos) * right_speed as f32;
|
||||||
|
|
||||||
|
let mut velocity = forward + right;
|
||||||
|
if velocity.magnitude2() > 1.0 {
|
||||||
|
velocity = velocity.normalize();
|
||||||
|
}
|
||||||
|
velocity *= speed;
|
||||||
|
velocity.y = self.up_speed * 10.0 * dt.as_secs_f32();
|
||||||
|
|
||||||
|
let mut new_position = self.view.camera.position;
|
||||||
|
|
||||||
|
// y component (jumping)
|
||||||
|
new_position.y += velocity.y;
|
||||||
|
if let Some(aabb) = self.check_collision(new_position, world) {
|
||||||
|
if self.up_speed < 0.0 {
|
||||||
|
new_position.y = aabb.min.y.ceil() + 1.62;
|
||||||
|
new_position.y = utils::f32_successor(new_position.y);
|
||||||
|
} else if self.up_speed > 0.0 {
|
||||||
|
new_position.y = aabb.max.y.floor() - 0.18;
|
||||||
|
new_position.y = utils::f32_predecessor(new_position.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.up_speed = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// x component
|
||||||
|
new_position.x += velocity.x;
|
||||||
|
if let Some(aabb) = self.check_collision(new_position, world) {
|
||||||
|
if velocity.x < 0.0 {
|
||||||
|
new_position.x = aabb.min.x.ceil() + 0.3;
|
||||||
|
new_position.x = utils::f32_successor(new_position.x);
|
||||||
|
} else if velocity.x > 0.0 {
|
||||||
|
new_position.x = aabb.max.x.floor() - 0.3;
|
||||||
|
new_position.x = utils::f32_predecessor(new_position.x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// z component
|
||||||
|
new_position.z += velocity.z;
|
||||||
|
if let Some(aabb) = self.check_collision(new_position, world) {
|
||||||
|
if velocity.z < 0.0 {
|
||||||
|
new_position.z = aabb.min.z.ceil() + 0.3;
|
||||||
|
new_position.z = utils::f32_successor(new_position.z);
|
||||||
|
} else if velocity.z > 0.0 {
|
||||||
|
new_position.z = aabb.max.z.floor() - 0.3;
|
||||||
|
new_position.z = utils::f32_predecessor(new_position.z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.view.camera.position = new_position;
|
||||||
|
|
||||||
|
if !self.creative {
|
||||||
|
self.up_speed -= 1.6 * dt.as_secs_f32();
|
||||||
|
self.up_speed *= 0.98_f32.powf(dt.as_secs_f32() / 20.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_collision(&self, position: Point3<f32>, world: &World) -> Option<Aabb> {
|
||||||
|
let aabb = Aabb {
|
||||||
|
min: position + Vector3::new(-0.3, -1.62, -0.3),
|
||||||
|
max: position + Vector3::new(0.3, 0.18, 0.3),
|
||||||
|
};
|
||||||
|
|
||||||
|
for corner in &aabb.get_corners() {
|
||||||
|
let block = world.get_block(
|
||||||
|
corner.x.floor() as isize,
|
||||||
|
corner.y.floor() as isize,
|
||||||
|
corner.z.floor() as isize,
|
||||||
|
);
|
||||||
|
|
||||||
|
if block.is_some() {
|
||||||
|
return Some(aabb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
|
@ -53,8 +53,7 @@ impl State {
|
||||||
.request_device(
|
.request_device(
|
||||||
&wgpu::DeviceDescriptor {
|
&wgpu::DeviceDescriptor {
|
||||||
label: Some("render_device"),
|
label: Some("render_device"),
|
||||||
features: wgpu::Features::NON_FILL_POLYGON_MODE
|
features: wgpu::Features::SAMPLED_TEXTURE_BINDING_ARRAY,
|
||||||
| wgpu::Features::SAMPLED_TEXTURE_BINDING_ARRAY,
|
|
||||||
limits: wgpu::Limits::default(),
|
limits: wgpu::Limits::default(),
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
|
@ -141,7 +140,6 @@ impl State {
|
||||||
fn input_keyboard(&mut self, key_code: VirtualKeyCode, state: ElementState) {
|
fn input_keyboard(&mut self, key_code: VirtualKeyCode, state: ElementState) {
|
||||||
if state == ElementState::Pressed {
|
if state == ElementState::Pressed {
|
||||||
match key_code {
|
match key_code {
|
||||||
VirtualKeyCode::F1 => self.world_state.toggle_wireframe(&self.render_context),
|
|
||||||
VirtualKeyCode::Key1 => self.hud_state.set_hotbar_cursor(&self.render_context, 0),
|
VirtualKeyCode::Key1 => self.hud_state.set_hotbar_cursor(&self.render_context, 0),
|
||||||
VirtualKeyCode::Key2 => self.hud_state.set_hotbar_cursor(&self.render_context, 1),
|
VirtualKeyCode::Key2 => self.hud_state.set_hotbar_cursor(&self.render_context, 1),
|
||||||
VirtualKeyCode::Key3 => self.hud_state.set_hotbar_cursor(&self.render_context, 2),
|
VirtualKeyCode::Key3 => self.hud_state.set_hotbar_cursor(&self.render_context, 2),
|
||||||
|
@ -160,7 +158,7 @@ impl State {
|
||||||
|
|
||||||
fn input_mouse(&mut self, dx: f64, dy: f64) {
|
fn input_mouse(&mut self, dx: f64, dy: f64) {
|
||||||
if self.mouse_grabbed {
|
if self.mouse_grabbed {
|
||||||
self.world_state.update_camera(dx, dy);
|
self.world_state.player.update_camera(dx, dy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,7 +200,7 @@ impl State {
|
||||||
.update(dt, render_time, &self.render_context);
|
.update(dt, render_time, &self.render_context);
|
||||||
self.hud_state.update(
|
self.hud_state.update(
|
||||||
&self.render_context,
|
&self.render_context,
|
||||||
&self.world_state.camera.position.to_vec(),
|
&self.world_state.player.view.camera.position.to_vec(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use cgmath::{InnerSpace, Point3, Rad, Vector3};
|
|
||||||
use wgpu::{
|
use wgpu::{
|
||||||
util::{BufferInitDescriptor, DeviceExt},
|
util::{BufferInitDescriptor, DeviceExt},
|
||||||
CommandEncoder, SwapChainTexture,
|
CommandEncoder, SwapChainTexture,
|
||||||
|
@ -11,111 +10,28 @@ use winit::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
aabb::Aabb,
|
player::Player,
|
||||||
camera::{Camera, Projection},
|
|
||||||
render_context::RenderContext,
|
render_context::RenderContext,
|
||||||
renderable::Renderable,
|
renderable::Renderable,
|
||||||
texture::Texture,
|
texture::Texture,
|
||||||
time::Time,
|
time::Time,
|
||||||
utils,
|
|
||||||
vertex::{BlockVertex, Vertex},
|
vertex::{BlockVertex, Vertex},
|
||||||
view::View,
|
|
||||||
world::{block::BlockType, World},
|
world::{block::BlockType, World},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct WorldState {
|
pub struct WorldState {
|
||||||
pub render_pipeline: wgpu::RenderPipeline,
|
pub render_pipeline: wgpu::RenderPipeline,
|
||||||
pub view: View,
|
|
||||||
pub view_buffer: wgpu::Buffer,
|
|
||||||
pub view_bind_group: wgpu::BindGroup,
|
|
||||||
pub camera: Camera,
|
|
||||||
pub projection: Projection,
|
|
||||||
pub depth_texture: Texture,
|
pub depth_texture: Texture,
|
||||||
pub time_bind_group: wgpu::BindGroup,
|
|
||||||
pub world: World,
|
|
||||||
|
|
||||||
time: Time,
|
time: Time,
|
||||||
time_buffer: wgpu::Buffer,
|
time_buffer: wgpu::Buffer,
|
||||||
wireframe: bool,
|
pub time_bind_group: wgpu::BindGroup,
|
||||||
shader: wgpu::ShaderModule,
|
|
||||||
render_pipeline_layout: wgpu::PipelineLayout,
|
|
||||||
|
|
||||||
pub forward_pressed: bool,
|
pub world: World,
|
||||||
pub backward_pressed: bool,
|
pub player: Player,
|
||||||
pub left_pressed: bool,
|
|
||||||
pub right_pressed: bool,
|
|
||||||
|
|
||||||
pub up_speed: f32,
|
|
||||||
pub sprinting: bool,
|
|
||||||
pub creative: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WorldState {
|
impl WorldState {
|
||||||
fn create_camera(render_context: &RenderContext) -> (Camera, Projection) {
|
|
||||||
let camera = Camera::new(
|
|
||||||
(10.0, 140.0, 10.0).into(),
|
|
||||||
cgmath::Deg(45.0).into(),
|
|
||||||
cgmath::Deg(-20.0).into(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let projection = Projection::new(
|
|
||||||
render_context.swap_chain_descriptor.width,
|
|
||||||
render_context.swap_chain_descriptor.height,
|
|
||||||
cgmath::Deg(45.0),
|
|
||||||
0.1,
|
|
||||||
300.0,
|
|
||||||
);
|
|
||||||
|
|
||||||
(camera, projection)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_view(
|
|
||||||
camera: &Camera,
|
|
||||||
projection: &Projection,
|
|
||||||
render_context: &RenderContext,
|
|
||||||
) -> (View, wgpu::Buffer, wgpu::BindGroupLayout, wgpu::BindGroup) {
|
|
||||||
let mut view = View::new();
|
|
||||||
view.update_view_projection(camera, projection);
|
|
||||||
|
|
||||||
let view_buffer = render_context
|
|
||||||
.device
|
|
||||||
.create_buffer_init(&BufferInitDescriptor {
|
|
||||||
label: Some("view_buffer"),
|
|
||||||
contents: bytemuck::cast_slice(&[view.to_raw()]),
|
|
||||||
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
|
|
||||||
});
|
|
||||||
|
|
||||||
let view_bind_group_layout =
|
|
||||||
render_context
|
|
||||||
.device
|
|
||||||
.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
|
||||||
entries: &[wgpu::BindGroupLayoutEntry {
|
|
||||||
binding: 0,
|
|
||||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
|
||||||
ty: wgpu::BindingType::Buffer {
|
|
||||||
ty: wgpu::BufferBindingType::Uniform,
|
|
||||||
has_dynamic_offset: false,
|
|
||||||
min_binding_size: None,
|
|
||||||
},
|
|
||||||
count: None,
|
|
||||||
}],
|
|
||||||
label: Some("view_bind_group_layout"),
|
|
||||||
});
|
|
||||||
|
|
||||||
let view_bind_group = render_context
|
|
||||||
.device
|
|
||||||
.create_bind_group(&wgpu::BindGroupDescriptor {
|
|
||||||
layout: &view_bind_group_layout,
|
|
||||||
entries: &[wgpu::BindGroupEntry {
|
|
||||||
binding: 0,
|
|
||||||
resource: view_buffer.as_entire_binding(),
|
|
||||||
}],
|
|
||||||
label: Some("view_bind_group"),
|
|
||||||
});
|
|
||||||
|
|
||||||
(view, view_buffer, view_bind_group_layout, view_bind_group)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_time(
|
fn create_time(
|
||||||
render_context: &RenderContext,
|
render_context: &RenderContext,
|
||||||
) -> (Time, wgpu::Buffer, wgpu::BindGroupLayout, wgpu::BindGroup) {
|
) -> (Time, wgpu::Buffer, wgpu::BindGroupLayout, wgpu::BindGroup) {
|
||||||
|
@ -164,7 +80,6 @@ impl WorldState {
|
||||||
render_context: &RenderContext,
|
render_context: &RenderContext,
|
||||||
shader: &wgpu::ShaderModule,
|
shader: &wgpu::ShaderModule,
|
||||||
pipeline_layout: &wgpu::PipelineLayout,
|
pipeline_layout: &wgpu::PipelineLayout,
|
||||||
wireframe: bool,
|
|
||||||
) -> wgpu::RenderPipeline {
|
) -> wgpu::RenderPipeline {
|
||||||
render_context
|
render_context
|
||||||
.device
|
.device
|
||||||
|
@ -190,11 +105,7 @@ impl WorldState {
|
||||||
}),
|
}),
|
||||||
primitive: wgpu::PrimitiveState {
|
primitive: wgpu::PrimitiveState {
|
||||||
cull_mode: Some(wgpu::Face::Back),
|
cull_mode: Some(wgpu::Face::Back),
|
||||||
polygon_mode: if wireframe {
|
polygon_mode: wgpu::PolygonMode::Fill,
|
||||||
wgpu::PolygonMode::Line
|
|
||||||
} else {
|
|
||||||
wgpu::PolygonMode::Fill
|
|
||||||
},
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
depth_stencil: Some(wgpu::DepthStencilState {
|
depth_stencil: Some(wgpu::DepthStencilState {
|
||||||
|
@ -208,23 +119,9 @@ impl WorldState {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toggle_wireframe(&mut self, render_context: &RenderContext) {
|
|
||||||
self.wireframe = !self.wireframe;
|
|
||||||
self.render_pipeline = Self::create_render_pipeline(
|
|
||||||
render_context,
|
|
||||||
&self.shader,
|
|
||||||
&self.render_pipeline_layout,
|
|
||||||
self.wireframe,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new(render_context: &RenderContext) -> WorldState {
|
pub fn new(render_context: &RenderContext) -> WorldState {
|
||||||
let (camera, projection) = Self::create_camera(render_context);
|
|
||||||
|
|
||||||
let (view, view_buffer, view_bind_group_layout, view_bind_group) =
|
|
||||||
Self::create_view(&camera, &projection, render_context);
|
|
||||||
|
|
||||||
let (time, time_buffer, time_layout, time_bind_group) = Self::create_time(render_context);
|
let (time, time_buffer, time_layout, time_bind_group) = Self::create_time(render_context);
|
||||||
|
let player = Player::new(render_context);
|
||||||
|
|
||||||
let mut world = World::new();
|
let mut world = World::new();
|
||||||
world.npc.load_geometry(render_context);
|
world.npc.load_geometry(render_context);
|
||||||
|
@ -246,40 +143,24 @@ impl WorldState {
|
||||||
push_constant_ranges: &[],
|
push_constant_ranges: &[],
|
||||||
bind_group_layouts: &[
|
bind_group_layouts: &[
|
||||||
&texture_manager.bind_group_layout,
|
&texture_manager.bind_group_layout,
|
||||||
&view_bind_group_layout,
|
&player.view.bind_group_layout,
|
||||||
&time_layout,
|
&time_layout,
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
let render_pipeline =
|
let render_pipeline =
|
||||||
Self::create_render_pipeline(&render_context, &shader, &render_pipeline_layout, false);
|
Self::create_render_pipeline(render_context, &shader, &render_pipeline_layout);
|
||||||
let depth_texture = Texture::create_depth_texture(render_context, "depth_texture");
|
let depth_texture = Texture::create_depth_texture(render_context, "depth_texture");
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
render_pipeline,
|
render_pipeline,
|
||||||
view,
|
|
||||||
view_buffer,
|
|
||||||
view_bind_group,
|
|
||||||
camera,
|
|
||||||
projection,
|
|
||||||
depth_texture,
|
depth_texture,
|
||||||
shader,
|
|
||||||
render_pipeline_layout,
|
|
||||||
|
|
||||||
time,
|
time,
|
||||||
time_buffer,
|
time_buffer,
|
||||||
time_bind_group,
|
time_bind_group,
|
||||||
|
|
||||||
world,
|
world,
|
||||||
|
player,
|
||||||
wireframe: false,
|
|
||||||
|
|
||||||
up_speed: 0.0,
|
|
||||||
sprinting: false,
|
|
||||||
forward_pressed: false,
|
|
||||||
backward_pressed: false,
|
|
||||||
left_pressed: false,
|
|
||||||
right_pressed: false,
|
|
||||||
creative: true,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,26 +201,14 @@ impl WorldState {
|
||||||
|
|
||||||
let texture_manager = render_context.texture_manager.as_ref().unwrap();
|
let texture_manager = render_context.texture_manager.as_ref().unwrap();
|
||||||
render_pass.set_bind_group(0, texture_manager.bind_group.as_ref().unwrap(), &[]);
|
render_pass.set_bind_group(0, texture_manager.bind_group.as_ref().unwrap(), &[]);
|
||||||
render_pass.set_bind_group(1, &self.view_bind_group, &[]);
|
render_pass.set_bind_group(1, &self.player.view.bind_group, &[]);
|
||||||
render_pass.set_bind_group(2, &self.time_bind_group, &[]);
|
render_pass.set_bind_group(2, &self.time_bind_group, &[]);
|
||||||
|
|
||||||
triangle_count += self.world.render(&mut render_pass, &self.view);
|
triangle_count += self.world.render(&mut render_pass, &self.player.view);
|
||||||
|
|
||||||
triangle_count
|
triangle_count
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_camera(&mut self, dx: f64, dy: f64) {
|
|
||||||
let camera = &mut self.camera;
|
|
||||||
camera.yaw += Rad(dx as f32 * 0.003);
|
|
||||||
camera.pitch -= Rad(dy as f32 * 0.003);
|
|
||||||
|
|
||||||
if camera.pitch < Rad::from(cgmath::Deg(-80.0)) {
|
|
||||||
camera.pitch = Rad::from(cgmath::Deg(-80.0));
|
|
||||||
} else if camera.pitch > Rad::from(cgmath::Deg(89.9)) {
|
|
||||||
camera.pitch = Rad::from(cgmath::Deg(89.9));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn input_mouse_button(
|
pub fn input_mouse_button(
|
||||||
&mut self,
|
&mut self,
|
||||||
button: &MouseButton,
|
button: &MouseButton,
|
||||||
|
@ -347,154 +216,60 @@ impl WorldState {
|
||||||
selected: Option<BlockType>,
|
selected: Option<BlockType>,
|
||||||
) {
|
) {
|
||||||
if button == &MouseButton::Left {
|
if button == &MouseButton::Left {
|
||||||
self.world.break_at_crosshair(render_context, &self.camera);
|
self.world
|
||||||
|
.break_at_crosshair(render_context, &self.player.view.camera);
|
||||||
} else if button == &MouseButton::Right {
|
} else if button == &MouseButton::Right {
|
||||||
if let Some(selected) = selected {
|
if let Some(selected) = selected {
|
||||||
self.world
|
self.world
|
||||||
.place_at_crosshair(render_context, &self.camera, selected);
|
.place_at_crosshair(render_context, &self.player.view.camera, selected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::collapsible_else_if)]
|
||||||
pub fn input_keyboard(&mut self, key_code: VirtualKeyCode, state: ElementState) {
|
pub fn input_keyboard(&mut self, key_code: VirtualKeyCode, state: ElementState) {
|
||||||
let pressed = state == ElementState::Pressed;
|
let pressed = state == ElementState::Pressed;
|
||||||
match key_code {
|
match key_code {
|
||||||
VirtualKeyCode::W => self.forward_pressed = pressed,
|
VirtualKeyCode::W => self.player.forward_pressed = pressed,
|
||||||
VirtualKeyCode::S => self.backward_pressed = pressed,
|
VirtualKeyCode::S => self.player.backward_pressed = pressed,
|
||||||
VirtualKeyCode::A => self.left_pressed = pressed,
|
VirtualKeyCode::A => self.player.left_pressed = pressed,
|
||||||
VirtualKeyCode::D => self.right_pressed = pressed,
|
VirtualKeyCode::D => self.player.right_pressed = pressed,
|
||||||
VirtualKeyCode::F2 if pressed => self.creative = !self.creative,
|
VirtualKeyCode::F2 if pressed => self.player.creative ^= true,
|
||||||
VirtualKeyCode::Space => {
|
VirtualKeyCode::Space => {
|
||||||
// TODO aaaaaaaaaaaaaaaaaa
|
// TODO aaaaaaaaaaaaaaaaaa
|
||||||
self.up_speed = if pressed {
|
self.player.up_speed = if pressed {
|
||||||
if self.creative {
|
if self.player.creative {
|
||||||
1.0
|
1.0
|
||||||
} else {
|
} else {
|
||||||
if self.up_speed.abs() < 0.05 {
|
if self.player.up_speed.abs() < 0.05 {
|
||||||
0.6
|
0.6
|
||||||
} else {
|
} else {
|
||||||
self.up_speed
|
self.player.up_speed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if self.creative {
|
if self.player.creative {
|
||||||
0.0
|
0.0
|
||||||
} else {
|
} else {
|
||||||
self.up_speed
|
self.player.up_speed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VirtualKeyCode::LShift if self.creative => {
|
VirtualKeyCode::LShift if self.player.creative => {
|
||||||
self.up_speed = if pressed { -1.0 } else { 0.0 }
|
self.player.up_speed = if pressed { -1.0 } else { 0.0 }
|
||||||
}
|
}
|
||||||
VirtualKeyCode::LControl => self.sprinting = pressed,
|
VirtualKeyCode::LControl => self.player.sprinting = pressed,
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_collision(&self, position: Point3<f32>) -> Option<Aabb> {
|
|
||||||
let aabb = Aabb {
|
|
||||||
min: position + Vector3::new(-0.3, -1.62, -0.3),
|
|
||||||
max: position + Vector3::new(0.3, 0.18, 0.3),
|
|
||||||
};
|
|
||||||
|
|
||||||
for corner in &aabb.get_corners() {
|
|
||||||
let block = self.world.get_block(
|
|
||||||
corner.x.floor() as isize,
|
|
||||||
corner.y.floor() as isize,
|
|
||||||
corner.z.floor() as isize,
|
|
||||||
);
|
|
||||||
|
|
||||||
if block.is_some() {
|
|
||||||
return Some(aabb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Updates the player's position by their velocity, checks for and
|
|
||||||
/// resolves any subsequent collisions, and then adds the jumping speed to
|
|
||||||
/// the velocity.
|
|
||||||
fn update_position(&mut self, dt: Duration) {
|
|
||||||
let (yaw_sin, yaw_cos) = self.camera.yaw.0.sin_cos();
|
|
||||||
|
|
||||||
let speed = 10.0 * (self.sprinting as i32 * 2 + 1) as f32 * dt.as_secs_f32();
|
|
||||||
|
|
||||||
let forward_speed = self.forward_pressed as i32 - self.backward_pressed as i32;
|
|
||||||
let forward = Vector3::new(yaw_cos, 0.0, yaw_sin) * forward_speed as f32;
|
|
||||||
|
|
||||||
let right_speed = self.right_pressed as i32 - self.left_pressed as i32;
|
|
||||||
let right = Vector3::new(-yaw_sin, 0.0, yaw_cos) * right_speed as f32;
|
|
||||||
|
|
||||||
let mut velocity = forward + right;
|
|
||||||
if velocity.magnitude2() > 1.0 {
|
|
||||||
velocity = velocity.normalize();
|
|
||||||
}
|
|
||||||
velocity *= speed;
|
|
||||||
velocity.y = self.up_speed * 10.0 * dt.as_secs_f32();
|
|
||||||
|
|
||||||
let mut new_position = self.camera.position;
|
|
||||||
|
|
||||||
// y component (jumping)
|
|
||||||
new_position.y += velocity.y;
|
|
||||||
if let Some(aabb) = self.check_collision(new_position) {
|
|
||||||
if self.up_speed < 0.0 {
|
|
||||||
new_position.y = aabb.min.y.ceil() + 1.62;
|
|
||||||
new_position.y = utils::f32_successor(new_position.y);
|
|
||||||
} else if self.up_speed > 0.0 {
|
|
||||||
new_position.y = aabb.max.y.floor() - 0.18;
|
|
||||||
new_position.y = utils::f32_predecessor(new_position.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.up_speed = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// x component
|
|
||||||
new_position.x += velocity.x;
|
|
||||||
if let Some(aabb) = self.check_collision(new_position) {
|
|
||||||
if velocity.x < 0.0 {
|
|
||||||
new_position.x = aabb.min.x.ceil() + 0.3;
|
|
||||||
new_position.x = utils::f32_successor(new_position.x);
|
|
||||||
} else if velocity.x > 0.0 {
|
|
||||||
new_position.x = aabb.max.x.floor() - 0.3;
|
|
||||||
new_position.x = utils::f32_predecessor(new_position.x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// z component
|
|
||||||
new_position.z += velocity.z;
|
|
||||||
if let Some(aabb) = self.check_collision(new_position) {
|
|
||||||
if velocity.z < 0.0 {
|
|
||||||
new_position.z = aabb.min.z.ceil() + 0.3;
|
|
||||||
new_position.z = utils::f32_successor(new_position.z);
|
|
||||||
} else if velocity.z > 0.0 {
|
|
||||||
new_position.z = aabb.max.z.floor() - 0.3;
|
|
||||||
new_position.z = utils::f32_predecessor(new_position.z);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.camera.position = new_position;
|
|
||||||
|
|
||||||
if !self.creative {
|
|
||||||
self.up_speed -= 1.6 * dt.as_secs_f32();
|
|
||||||
self.up_speed *= 0.98_f32.powf(dt.as_secs_f32() / 20.0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update(&mut self, dt: Duration, render_time: Duration, render_context: &RenderContext) {
|
pub fn update(&mut self, dt: Duration, render_time: Duration, render_context: &RenderContext) {
|
||||||
self.update_position(dt);
|
self.player.update_position(dt, &self.world);
|
||||||
|
|
||||||
self.world
|
self.world
|
||||||
.update(render_context, dt, render_time, &self.camera);
|
.update(render_context, dt, render_time, &self.player.view.camera);
|
||||||
|
|
||||||
self.view
|
self.player.view.update_view_projection(render_context);
|
||||||
.update_view_projection(&self.camera, &self.projection);
|
|
||||||
render_context.queue.write_buffer(
|
|
||||||
&self.view_buffer,
|
|
||||||
0,
|
|
||||||
bytemuck::cast_slice(&[self.view.to_raw()]),
|
|
||||||
);
|
|
||||||
|
|
||||||
self.time.time += dt.as_secs_f32();
|
self.time.time += dt.as_secs_f32();
|
||||||
render_context.queue.write_buffer(
|
render_context.queue.write_buffer(
|
||||||
|
@ -505,7 +280,12 @@ impl WorldState {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resize(&mut self, render_context: &RenderContext, new_size: PhysicalSize<u32>) {
|
pub fn resize(&mut self, render_context: &RenderContext, new_size: PhysicalSize<u32>) {
|
||||||
self.projection.resize(new_size.width, new_size.height);
|
// TODO Move this to View
|
||||||
|
self.player
|
||||||
|
.view
|
||||||
|
.projection
|
||||||
|
.resize(new_size.width, new_size.height);
|
||||||
|
|
||||||
self.depth_texture = Texture::create_depth_texture(render_context, "depth_texture");
|
self.depth_texture = Texture::create_depth_texture(render_context, "depth_texture");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
99
src/view.rs
99
src/view.rs
|
@ -1,40 +1,111 @@
|
||||||
|
use std::mem::size_of;
|
||||||
|
|
||||||
use cgmath::{EuclideanSpace, Matrix4, Point3, SquareMatrix, Vector4, Zero};
|
use cgmath::{EuclideanSpace, Matrix4, Point3, SquareMatrix, Vector4, Zero};
|
||||||
|
use wgpu::{BindGroup, BindGroupLayout, Buffer, BufferDescriptor, BufferUsage};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
aabb::Aabb,
|
aabb::Aabb,
|
||||||
camera::{Camera, Projection, OPENGL_TO_WGPU_MATRIX},
|
camera::{Camera, Projection, OPENGL_TO_WGPU_MATRIX},
|
||||||
|
render_context::RenderContext,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct View {
|
pub struct View {
|
||||||
view_position: Vector4<f32>,
|
position_vector: Vector4<f32>,
|
||||||
view_projection: Matrix4<f32>,
|
projection_matrix: Matrix4<f32>,
|
||||||
pub aabb: Aabb,
|
pub frustrum_aabb: Aabb,
|
||||||
|
|
||||||
|
pub camera: Camera,
|
||||||
|
pub projection: Projection,
|
||||||
|
|
||||||
|
pub buffer: Buffer,
|
||||||
|
pub bind_group_layout: BindGroupLayout,
|
||||||
|
pub bind_group: BindGroup,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl View {
|
impl View {
|
||||||
pub fn to_raw(&self) -> ViewRaw {
|
pub fn to_raw(&self) -> ViewRaw {
|
||||||
ViewRaw {
|
ViewRaw {
|
||||||
view_position: self.view_position.into(),
|
view_position: self.position_vector.into(),
|
||||||
view_projection: self.view_projection.into(),
|
view_projection: self.projection_matrix.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new() -> Self {
|
pub fn new(render_context: &RenderContext) -> Self {
|
||||||
|
let camera = Camera::new(
|
||||||
|
(10.0, 140.0, 10.0).into(),
|
||||||
|
cgmath::Deg(45.0).into(),
|
||||||
|
cgmath::Deg(-20.0).into(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let projection = Projection::new(
|
||||||
|
render_context.swap_chain_descriptor.width,
|
||||||
|
render_context.swap_chain_descriptor.height,
|
||||||
|
cgmath::Deg(45.0),
|
||||||
|
0.1,
|
||||||
|
300.0,
|
||||||
|
);
|
||||||
|
|
||||||
|
let buffer = render_context.device.create_buffer(&BufferDescriptor {
|
||||||
|
label: Some("view buffer"),
|
||||||
|
size: size_of::<ViewRaw>() as u64,
|
||||||
|
usage: BufferUsage::UNIFORM | BufferUsage::COPY_DST,
|
||||||
|
mapped_at_creation: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
let bind_group_layout =
|
||||||
|
render_context
|
||||||
|
.device
|
||||||
|
.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||||
|
entries: &[wgpu::BindGroupLayoutEntry {
|
||||||
|
binding: 0,
|
||||||
|
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||||
|
ty: wgpu::BindingType::Buffer {
|
||||||
|
ty: wgpu::BufferBindingType::Uniform,
|
||||||
|
has_dynamic_offset: false,
|
||||||
|
min_binding_size: None,
|
||||||
|
},
|
||||||
|
count: None,
|
||||||
|
}],
|
||||||
|
label: Some("view_bind_group_layout"),
|
||||||
|
});
|
||||||
|
|
||||||
|
let bind_group = render_context
|
||||||
|
.device
|
||||||
|
.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||||
|
layout: &bind_group_layout,
|
||||||
|
entries: &[wgpu::BindGroupEntry {
|
||||||
|
binding: 0,
|
||||||
|
resource: buffer.as_entire_binding(),
|
||||||
|
}],
|
||||||
|
label: Some("view_bind_group"),
|
||||||
|
});
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
view_position: Vector4::zero(),
|
position_vector: Vector4::zero(),
|
||||||
view_projection: Matrix4::identity(),
|
projection_matrix: Matrix4::identity(),
|
||||||
aabb: Aabb::default(),
|
frustrum_aabb: Aabb::default(),
|
||||||
|
camera,
|
||||||
|
projection,
|
||||||
|
|
||||||
|
buffer,
|
||||||
|
bind_group_layout,
|
||||||
|
bind_group,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_view_projection(&mut self, camera: &Camera, projection: &Projection) {
|
pub fn update_view_projection(&mut self, render_context: &RenderContext) {
|
||||||
self.view_position = camera.position.to_homogeneous();
|
self.position_vector = self.camera.position.to_homogeneous();
|
||||||
self.view_projection = projection.calculate_matrix() * camera.calculate_matrix();
|
self.projection_matrix =
|
||||||
self.aabb = self.frustrum_aabb();
|
self.projection.calculate_matrix() * self.camera.calculate_matrix();
|
||||||
|
self.frustrum_aabb = self.frustrum_aabb();
|
||||||
|
|
||||||
|
render_context
|
||||||
|
.queue
|
||||||
|
.write_buffer(&self.buffer, 0, bytemuck::cast_slice(&[self.to_raw()]));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn frustrum_aabb(&self) -> Aabb {
|
fn frustrum_aabb(&self) -> Aabb {
|
||||||
let projection = OPENGL_TO_WGPU_MATRIX.invert().unwrap() * self.view_projection;
|
let projection = OPENGL_TO_WGPU_MATRIX.invert().unwrap() * self.projection_matrix;
|
||||||
let inverse_matrix = projection.invert().unwrap();
|
let inverse_matrix = projection.invert().unwrap();
|
||||||
|
|
||||||
let corners = &[
|
let corners = &[
|
||||||
|
|
|
@ -412,6 +412,6 @@ impl Chunk {
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
};
|
};
|
||||||
|
|
||||||
aabb.intersects(&view.aabb)
|
aabb.intersects(&view.frustrum_aabb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@ pub const WORLD_HEIGHT: isize = 16 * 16 / CHUNK_ISIZE;
|
||||||
const DEBUG_IO: bool = false;
|
const DEBUG_IO: bool = false;
|
||||||
|
|
||||||
impl Renderable for World {
|
impl Renderable for World {
|
||||||
|
#[allow(clippy::collapsible_else_if)]
|
||||||
fn update(
|
fn update(
|
||||||
&mut self,
|
&mut self,
|
||||||
render_context: &RenderContext,
|
render_context: &RenderContext,
|
||||||
|
@ -161,11 +162,9 @@ impl Renderable for World {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
let buffers = self.npc.geometry_buffers.as_ref().unwrap();
|
||||||
let buffers = self.npc.geometry_buffers.as_ref().unwrap();
|
buffers.apply_buffers(render_pass);
|
||||||
buffers.set_buffers(render_pass);
|
triangle_count += buffers.draw_indexed(render_pass);
|
||||||
triangle_count += buffers.draw_indexed(render_pass);
|
|
||||||
}
|
|
||||||
|
|
||||||
triangle_count
|
triangle_count
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue