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> {
|
||||
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_index_buffer(self.indices.slice(..), wgpu::IndexFormat::Uint32);
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ mod vertex;
|
|||
mod view;
|
||||
mod world;
|
||||
mod utils;
|
||||
mod player;
|
||||
|
||||
use std::time::{Duration, Instant};
|
||||
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(
|
||||
&wgpu::DeviceDescriptor {
|
||||
label: Some("render_device"),
|
||||
features: wgpu::Features::NON_FILL_POLYGON_MODE
|
||||
| wgpu::Features::SAMPLED_TEXTURE_BINDING_ARRAY,
|
||||
features: wgpu::Features::SAMPLED_TEXTURE_BINDING_ARRAY,
|
||||
limits: wgpu::Limits::default(),
|
||||
},
|
||||
None,
|
||||
|
@ -141,7 +140,6 @@ impl State {
|
|||
fn input_keyboard(&mut self, key_code: VirtualKeyCode, state: ElementState) {
|
||||
if state == ElementState::Pressed {
|
||||
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::Key2 => self.hud_state.set_hotbar_cursor(&self.render_context, 1),
|
||||
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) {
|
||||
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);
|
||||
self.hud_state.update(
|
||||
&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 cgmath::{InnerSpace, Point3, Rad, Vector3};
|
||||
use wgpu::{
|
||||
util::{BufferInitDescriptor, DeviceExt},
|
||||
CommandEncoder, SwapChainTexture,
|
||||
|
@ -11,111 +10,28 @@ use winit::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
aabb::Aabb,
|
||||
camera::{Camera, Projection},
|
||||
player::Player,
|
||||
render_context::RenderContext,
|
||||
renderable::Renderable,
|
||||
texture::Texture,
|
||||
time::Time,
|
||||
utils,
|
||||
vertex::{BlockVertex, Vertex},
|
||||
view::View,
|
||||
world::{block::BlockType, World},
|
||||
};
|
||||
|
||||
pub struct WorldState {
|
||||
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 time_bind_group: wgpu::BindGroup,
|
||||
pub world: World,
|
||||
|
||||
time: Time,
|
||||
time_buffer: wgpu::Buffer,
|
||||
wireframe: bool,
|
||||
shader: wgpu::ShaderModule,
|
||||
render_pipeline_layout: wgpu::PipelineLayout,
|
||||
pub time_bind_group: wgpu::BindGroup,
|
||||
|
||||
pub forward_pressed: bool,
|
||||
pub backward_pressed: bool,
|
||||
pub left_pressed: bool,
|
||||
pub right_pressed: bool,
|
||||
|
||||
pub up_speed: f32,
|
||||
pub sprinting: bool,
|
||||
pub creative: bool,
|
||||
pub world: World,
|
||||
pub player: Player,
|
||||
}
|
||||
|
||||
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(
|
||||
render_context: &RenderContext,
|
||||
) -> (Time, wgpu::Buffer, wgpu::BindGroupLayout, wgpu::BindGroup) {
|
||||
|
@ -164,7 +80,6 @@ impl WorldState {
|
|||
render_context: &RenderContext,
|
||||
shader: &wgpu::ShaderModule,
|
||||
pipeline_layout: &wgpu::PipelineLayout,
|
||||
wireframe: bool,
|
||||
) -> wgpu::RenderPipeline {
|
||||
render_context
|
||||
.device
|
||||
|
@ -190,11 +105,7 @@ impl WorldState {
|
|||
}),
|
||||
primitive: wgpu::PrimitiveState {
|
||||
cull_mode: Some(wgpu::Face::Back),
|
||||
polygon_mode: if wireframe {
|
||||
wgpu::PolygonMode::Line
|
||||
} else {
|
||||
wgpu::PolygonMode::Fill
|
||||
},
|
||||
polygon_mode: wgpu::PolygonMode::Fill,
|
||||
..Default::default()
|
||||
},
|
||||
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 {
|
||||
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 player = Player::new(render_context);
|
||||
|
||||
let mut world = World::new();
|
||||
world.npc.load_geometry(render_context);
|
||||
|
@ -246,40 +143,24 @@ impl WorldState {
|
|||
push_constant_ranges: &[],
|
||||
bind_group_layouts: &[
|
||||
&texture_manager.bind_group_layout,
|
||||
&view_bind_group_layout,
|
||||
&player.view.bind_group_layout,
|
||||
&time_layout,
|
||||
],
|
||||
});
|
||||
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");
|
||||
|
||||
Self {
|
||||
render_pipeline,
|
||||
view,
|
||||
view_buffer,
|
||||
view_bind_group,
|
||||
camera,
|
||||
projection,
|
||||
depth_texture,
|
||||
shader,
|
||||
render_pipeline_layout,
|
||||
|
||||
time,
|
||||
time_buffer,
|
||||
time_bind_group,
|
||||
|
||||
world,
|
||||
|
||||
wireframe: false,
|
||||
|
||||
up_speed: 0.0,
|
||||
sprinting: false,
|
||||
forward_pressed: false,
|
||||
backward_pressed: false,
|
||||
left_pressed: false,
|
||||
right_pressed: false,
|
||||
creative: true,
|
||||
player,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -320,26 +201,14 @@ impl WorldState {
|
|||
|
||||
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(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, &[]);
|
||||
|
||||
triangle_count += self.world.render(&mut render_pass, &self.view);
|
||||
triangle_count += self.world.render(&mut render_pass, &self.player.view);
|
||||
|
||||
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(
|
||||
&mut self,
|
||||
button: &MouseButton,
|
||||
|
@ -347,154 +216,60 @@ impl WorldState {
|
|||
selected: Option<BlockType>,
|
||||
) {
|
||||
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 {
|
||||
if let Some(selected) = selected {
|
||||
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) {
|
||||
let pressed = state == ElementState::Pressed;
|
||||
match key_code {
|
||||
VirtualKeyCode::W => self.forward_pressed = pressed,
|
||||
VirtualKeyCode::S => self.backward_pressed = pressed,
|
||||
VirtualKeyCode::A => self.left_pressed = pressed,
|
||||
VirtualKeyCode::D => self.right_pressed = pressed,
|
||||
VirtualKeyCode::F2 if pressed => self.creative = !self.creative,
|
||||
VirtualKeyCode::W => self.player.forward_pressed = pressed,
|
||||
VirtualKeyCode::S => self.player.backward_pressed = pressed,
|
||||
VirtualKeyCode::A => self.player.left_pressed = pressed,
|
||||
VirtualKeyCode::D => self.player.right_pressed = pressed,
|
||||
VirtualKeyCode::F2 if pressed => self.player.creative ^= true,
|
||||
VirtualKeyCode::Space => {
|
||||
// TODO aaaaaaaaaaaaaaaaaa
|
||||
self.up_speed = if pressed {
|
||||
if self.creative {
|
||||
self.player.up_speed = if pressed {
|
||||
if self.player.creative {
|
||||
1.0
|
||||
} else {
|
||||
if self.up_speed.abs() < 0.05 {
|
||||
if self.player.up_speed.abs() < 0.05 {
|
||||
0.6
|
||||
} else {
|
||||
self.up_speed
|
||||
self.player.up_speed
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if self.creative {
|
||||
if self.player.creative {
|
||||
0.0
|
||||
} else {
|
||||
self.up_speed
|
||||
self.player.up_speed
|
||||
}
|
||||
}
|
||||
}
|
||||
VirtualKeyCode::LShift if self.creative => {
|
||||
self.up_speed = if pressed { -1.0 } else { 0.0 }
|
||||
VirtualKeyCode::LShift if self.player.creative => {
|
||||
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) {
|
||||
self.update_position(dt);
|
||||
self.player.update_position(dt, &self.world);
|
||||
|
||||
self.world
|
||||
.update(render_context, dt, render_time, &self.camera);
|
||||
.update(render_context, dt, render_time, &self.player.view.camera);
|
||||
|
||||
self.view
|
||||
.update_view_projection(&self.camera, &self.projection);
|
||||
render_context.queue.write_buffer(
|
||||
&self.view_buffer,
|
||||
0,
|
||||
bytemuck::cast_slice(&[self.view.to_raw()]),
|
||||
);
|
||||
self.player.view.update_view_projection(render_context);
|
||||
|
||||
self.time.time += dt.as_secs_f32();
|
||||
render_context.queue.write_buffer(
|
||||
|
@ -505,7 +280,12 @@ impl WorldState {
|
|||
}
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
|
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 wgpu::{BindGroup, BindGroupLayout, Buffer, BufferDescriptor, BufferUsage};
|
||||
|
||||
use crate::{
|
||||
aabb::Aabb,
|
||||
camera::{Camera, Projection, OPENGL_TO_WGPU_MATRIX},
|
||||
render_context::RenderContext,
|
||||
};
|
||||
|
||||
pub struct View {
|
||||
view_position: Vector4<f32>,
|
||||
view_projection: Matrix4<f32>,
|
||||
pub aabb: Aabb,
|
||||
position_vector: Vector4<f32>,
|
||||
projection_matrix: Matrix4<f32>,
|
||||
pub frustrum_aabb: Aabb,
|
||||
|
||||
pub camera: Camera,
|
||||
pub projection: Projection,
|
||||
|
||||
pub buffer: Buffer,
|
||||
pub bind_group_layout: BindGroupLayout,
|
||||
pub bind_group: BindGroup,
|
||||
}
|
||||
|
||||
impl View {
|
||||
pub fn to_raw(&self) -> ViewRaw {
|
||||
ViewRaw {
|
||||
view_position: self.view_position.into(),
|
||||
view_projection: self.view_projection.into(),
|
||||
view_position: self.position_vector.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 {
|
||||
view_position: Vector4::zero(),
|
||||
view_projection: Matrix4::identity(),
|
||||
aabb: Aabb::default(),
|
||||
position_vector: Vector4::zero(),
|
||||
projection_matrix: Matrix4::identity(),
|
||||
frustrum_aabb: Aabb::default(),
|
||||
camera,
|
||||
projection,
|
||||
|
||||
buffer,
|
||||
bind_group_layout,
|
||||
bind_group,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_view_projection(&mut self, camera: &Camera, projection: &Projection) {
|
||||
self.view_position = camera.position.to_homogeneous();
|
||||
self.view_projection = projection.calculate_matrix() * camera.calculate_matrix();
|
||||
self.aabb = self.frustrum_aabb();
|
||||
pub fn update_view_projection(&mut self, render_context: &RenderContext) {
|
||||
self.position_vector = self.camera.position.to_homogeneous();
|
||||
self.projection_matrix =
|
||||
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 {
|
||||
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 corners = &[
|
||||
|
|
|
@ -412,6 +412,6 @@ impl Chunk {
|
|||
.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;
|
||||
|
||||
impl Renderable for World {
|
||||
#[allow(clippy::collapsible_else_if)]
|
||||
fn update(
|
||||
&mut self,
|
||||
render_context: &RenderContext,
|
||||
|
@ -161,11 +162,9 @@ impl Renderable for World {
|
|||
}
|
||||
}
|
||||
|
||||
{
|
||||
let buffers = self.npc.geometry_buffers.as_ref().unwrap();
|
||||
buffers.set_buffers(render_pass);
|
||||
triangle_count += buffers.draw_indexed(render_pass);
|
||||
}
|
||||
let buffers = self.npc.geometry_buffers.as_ref().unwrap();
|
||||
buffers.apply_buffers(render_pass);
|
||||
triangle_count += buffers.draw_indexed(render_pass);
|
||||
|
||||
triangle_count
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue