First efforts towards removing world_state and hud_state
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Sijmen 2021-06-08 22:30:57 +02:00
parent ec6978fee9
commit 11348f8086
Signed by: vijfhoek
GPG key ID: 82D05C89B28B0DAE
8 changed files with 271 additions and 284 deletions

View file

@ -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);
} }

View file

@ -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
View 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
}
}

View file

@ -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(),
); );
} }

View file

@ -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");
} }
} }

View file

@ -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 = &[

View file

@ -412,6 +412,6 @@ impl Chunk {
.unwrap(), .unwrap(),
}; };
aabb.intersects(&view.aabb) aabb.intersects(&view.frustrum_aabb)
} }
} }

View file

@ -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
} }