Implement placing blocks

This commit is contained in:
Sijmen 2021-05-30 03:48:26 +02:00
parent b30ee9ec3b
commit ea31c2d4dd
Signed by: vijfhoek
GPG key ID: 82D05C89B28B0DAE
5 changed files with 103 additions and 30 deletions

View file

@ -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<f32>, direction: Vector3<f32>) -> Option<Vector3<usize>> {
pub fn raycast(
&self,
origin: Vector3<f32>,
direction: Vector3<f32>,
) -> Option<(Vector3<usize>, Vector3<i32>)> {
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));
}
}

View file

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

View file

@ -70,7 +70,7 @@ fn main(in: VertexOutput) -> [[location(0)]] vec4<f32> {
var result: vec3<f32> = (ambient_color + diffuse_color + specular_color) * object_color.xyz;
if (in.highlighted != 0) {
result = result + 0.5;
result = result + 0.3;
}
return vec4<f32>(result, object_color.a);

View file

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

View file

@ -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::<Instance>() * 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(