Implement placing blocks
This commit is contained in:
parent
b30ee9ec3b
commit
ea31c2d4dd
5 changed files with 103 additions and 30 deletions
23
src/chunk.rs
23
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<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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
10
src/main.rs
10
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();
|
||||
|
|
|
@ -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);
|
||||
|
|
56
src/state.rs
56
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,
|
||||
},
|
||||
}],
|
||||
|
|
|
@ -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(
|
||||
|
|
Loading…
Reference in a new issue