From ea31c2d4dd4c7abf2d83fbd81dbc062a1304c870 Mon Sep 17 00:00:00 2001 From: Vijfhoek Date: Sun, 30 May 2021 03:48:26 +0200 Subject: [PATCH] Implement placing blocks --- src/chunk.rs | 23 ++++++++++++++--- src/main.rs | 10 +++++--- src/shaders/world.wgsl | 2 +- src/state.rs | 56 ++++++++++++++++++++++++++++++++++++------ src/world_state.rs | 42 ++++++++++++++++++++----------- 5 files changed, 103 insertions(+), 30 deletions(-) diff --git a/src/chunk.rs b/src/chunk.rs index a27d0f3..3b4d640 100644 --- a/src/chunk.rs +++ b/src/chunk.rs @@ -43,7 +43,15 @@ impl Chunk { map.drain().collect() } - fn get_block(&self, x: usize, y: usize, z: usize) -> Option<&Block> { + pub fn get_mut_block(&mut self, x: usize, y: usize, z: usize) -> Option<&mut Block> { + self.blocks + .get_mut(y) + .and_then(|blocks| blocks.get_mut(z)) + .and_then(|blocks| blocks.get_mut(x)) + .and_then(|block| block.as_mut()) + } + + pub fn get_block(&self, x: usize, y: usize, z: usize) -> Option<&Block> { self.blocks .get(y) .and_then(|blocks| blocks.get(z)) @@ -59,7 +67,11 @@ impl Chunk { } } - pub fn raycast(&self, origin: Vector3, direction: Vector3) -> Option> { + pub fn raycast( + &self, + origin: Vector3, + direction: Vector3, + ) -> Option<(Vector3, Vector3)> { let scale = Vector3::new( Self::calc_scale(direction, direction.x), Self::calc_scale(direction, direction.y), @@ -89,16 +101,21 @@ impl Chunk { }, }; + let mut face; + while lengths.magnitude() < 100.0 { if lengths.x <= lengths.y && lengths.x <= lengths.z { lengths.x += scale.x; position.x += step.x; + face = Vector3::unit_x() * step.x; } else if lengths.y <= lengths.x && lengths.y <= lengths.z { lengths.y += scale.y; position.y += step.y; + face = Vector3::unit_y() * step.y; } else if lengths.z <= lengths.x && lengths.z <= lengths.y { lengths.z += scale.z; position.z += step.z; + face = Vector3::unit_z() * step.z; } else { return None; } @@ -109,7 +126,7 @@ impl Chunk { position.z as usize, ) { // Intersection occurred - return Some(position.map(|x| x as usize)); + return Some((position.map(|x| x as usize), face)); } } diff --git a/src/main.rs b/src/main.rs index 76cd123..f9014b8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -81,11 +81,15 @@ fn main() { }, Event::RedrawRequested(_) => { frames += 1; - if frames % 1000 == 0 { - let frametime = instant.elapsed() / 1000; + if instant.elapsed().as_secs() >= 1 { + let frametime = instant.elapsed() / frames; let fps = 1_000_000 / frametime.as_micros(); - println!("{:?} - {} fps", frametime, fps); + println!( + "{} frames | frametime {:?} | fps {}", + frames, frametime, fps + ); instant = Instant::now(); + frames = 0; } let now = Instant::now(); diff --git a/src/shaders/world.wgsl b/src/shaders/world.wgsl index 961a274..5f82c95 100644 --- a/src/shaders/world.wgsl +++ b/src/shaders/world.wgsl @@ -70,7 +70,7 @@ fn main(in: VertexOutput) -> [[location(0)]] vec4 { var result: vec3 = (ambient_color + diffuse_color + specular_color) * object_color.xyz; if (in.highlighted != 0) { - result = result + 0.5; + result = result + 0.3; } return vec4(result, object_color.a); diff --git a/src/state.rs b/src/state.rs index 6b04e59..84386bb 100644 --- a/src/state.rs +++ b/src/state.rs @@ -7,7 +7,13 @@ use winit::{ window::Window, }; -use crate::{cube, texture::Texture, vertex::Vertex, world_state::WorldState}; +use crate::{ + chunk::{Block, BlockType}, + cube, + texture::Texture, + vertex::Vertex, + world_state::WorldState, +}; const UI_SCALE_X: f32 = 0.0045; const UI_SCALE_Y: f32 = 0.008; @@ -358,10 +364,11 @@ impl State { fn update_aim(&mut self) { let camera = &self.world_state.camera; let chunk = &mut self.world_state.chunk; - - let coords = chunk.raycast(camera.position.to_vec(), camera.direction()); - if coords != chunk.highlighted { - chunk.highlighted = coords; + let position = chunk + .raycast(camera.position.to_vec(), camera.direction()) + .map(|(position, _)| position); + if position != chunk.highlighted { + chunk.highlighted = position; self.world_state.update_chunk(&self.render_queue); } } @@ -369,7 +376,6 @@ impl State { fn input_mouse(&mut self, dx: f64, dy: f64) { if self.mouse_grabbed { self.update_camera(dx, dy); - self.update_aim(); } } @@ -380,6 +386,34 @@ impl State { state, .. }) => self.input_keyboard(key, state), + + DeviceEvent::Button { + button, + state: ElementState::Pressed, + } if self.mouse_grabbed => { + let camera = &self.world_state.camera; + + if let Some((pos, axis)) = self + .world_state + .chunk + .raycast(camera.position.to_vec(), camera.direction()) + { + if *button == 1 { + self.world_state.chunk.blocks[pos.y][pos.z][pos.x].take(); + dbg!(&pos); + self.world_state.update_chunk(&self.render_queue); + } else if *button == 3 { + let new_pos = pos.map(|x| x as i32) - axis; + dbg!(&axis, &new_pos); + self.world_state.chunk.blocks[new_pos.y as usize][new_pos.z as usize] + [new_pos.x as usize] = Some(Block { + block_type: BlockType::Cobblestone, + }); + self.world_state.update_chunk(&self.render_queue); + } + } + } + DeviceEvent::MouseMotion { delta: (dx, dy) } => self.input_mouse(*dx, *dy), _ => (), } @@ -388,7 +422,6 @@ impl State { pub fn update(&mut self, dt: Duration) { let dt_secs = dt.as_secs_f32(); - // Move forward/backward and left/right let (yaw_sin, yaw_cos) = self.world_state.camera.yaw.0.sin_cos(); let forward = cgmath::Vector3::new(yaw_cos, 0.0, yaw_sin).normalize(); @@ -400,6 +433,8 @@ impl State { let up = cgmath::Vector3::new(0.0, 1.0, 0.0).normalize(); self.world_state.camera.position += up * self.up_speed * 6.0 * dt_secs; + self.update_aim(); + self.world_state .uniforms .update_view_projection(&self.world_state.camera, &self.world_state.projection); @@ -426,7 +461,12 @@ impl State { view: &frame.view, resolve_target: None, ops: wgpu::Operations { - load: wgpu::LoadOp::Clear(wgpu::Color::BLUE), + load: wgpu::LoadOp::Clear(wgpu::Color { + r: 0.05, + g: 0.05, + b: 0.05, + a: 1.0, + }), store: true, }, }], diff --git a/src/world_state.rs b/src/world_state.rs index 47023bb..0db6c71 100644 --- a/src/world_state.rs +++ b/src/world_state.rs @@ -1,6 +1,9 @@ -use std::collections::HashMap; +use std::{mem::size_of, time::Instant}; -use wgpu::util::{BufferInitDescriptor, DeviceExt}; +use wgpu::{ + util::{BufferInitDescriptor, DeviceExt}, + BufferAddress, BufferDescriptor, +}; use winit::dpi::PhysicalSize; use crate::{ @@ -300,15 +303,15 @@ impl WorldState { let instance_buffers = instance_lists .iter() - .map(|(block_type, instance_list)| { - ( - *block_type, - render_device.create_buffer_init(&BufferInitDescriptor { + .map(|(block_type, _)| { + let buffer = render_device.create_buffer(&BufferDescriptor { label: Some("instance_buffer"), - contents: bytemuck::cast_slice(&instance_list), + size: (size_of::() * 16 * 16 * 16) as BufferAddress, usage: wgpu::BufferUsage::VERTEX | wgpu::BufferUsage::COPY_DST, - }), - ) + mapped_at_creation: false, + }); + + (*block_type, buffer) }) .collect(); @@ -316,20 +319,25 @@ impl WorldState { } pub fn update_chunk(&mut self, render_queue: &wgpu::Queue) { - let instance_lists = self.chunk.to_instances(); + let instant = Instant::now(); - for (block_type, instance_list) in instance_lists { + self.instance_lists = self.chunk.to_instances(); + + for (block_type, instance_list) in &self.instance_lists { if let Some(instance_buffer) = self.instance_buffers.get_mut(&block_type) { render_queue.write_buffer(instance_buffer, 0, bytemuck::cast_slice(&instance_list)); } else { todo!(); } } + + let elapsed = instant.elapsed(); + println!("Chunk update took {:?}", elapsed); } pub fn new( render_device: &wgpu::Device, - queue: &wgpu::Queue, + render_queue: &wgpu::Queue, swap_chain_descriptor: &wgpu::SwapChainDescriptor, ) -> WorldState { let chunk = Chunk { @@ -359,7 +367,7 @@ impl WorldState { }; let (world_texture_layout, texture_bind_groups) = - Self::create_textures(&render_device, &queue); + Self::create_textures(&render_device, &render_queue); let (camera, projection) = Self::create_camera(&swap_chain_descriptor); @@ -395,7 +403,7 @@ impl WorldState { let depth_texture = Texture::create_depth_texture(&render_device, &swap_chain_descriptor, "depth_texture"); - WorldState { + let mut world_state = Self { render_pipeline, uniforms, uniform_buffer, @@ -410,7 +418,11 @@ impl WorldState { depth_texture, light_bind_group, chunk, - } + }; + + world_state.update_chunk(&render_queue); + + world_state } pub fn resize(