Move some more world-related stuff to World

This commit is contained in:
Sijmen 2021-06-03 11:59:39 +02:00
parent 0ca35638fc
commit bd54a1bc14
Signed by: vijfhoek
GPG key ID: 82D05C89B28B0DAE
2 changed files with 89 additions and 131 deletions

View file

@ -1,9 +1,9 @@
use std::time::{Duration, Instant};
use std::time::Duration;
use cgmath::{EuclideanSpace, InnerSpace, Point3, Rad, Vector2, Vector3};
use cgmath::{InnerSpace, Point3, Rad, Vector3};
use wgpu::{
util::{BufferInitDescriptor, DeviceExt},
BufferUsage, CommandEncoder, SwapChainTexture,
CommandEncoder, SwapChainTexture,
};
use winit::{
dpi::PhysicalSize,
@ -12,8 +12,6 @@ use winit::{
use crate::{
camera::{Camera, Projection},
chunk::{Block, BlockType, CHUNK_ISIZE},
geometry::GeometryBuffers,
render_context::RenderContext,
texture::{Texture, TextureManager},
time::Time,
@ -215,24 +213,6 @@ impl WorldState {
}
/// TODO Move to World
pub fn update_world_geometry(&mut self, render_context: &RenderContext) {
let instant = Instant::now();
let world_geometry = self.world.to_geometry(self.world.highlighted);
self.world.chunk_buffers.clear();
for (chunk_position, chunk_geometry) in world_geometry {
let buffers = GeometryBuffers::from_geometry(
render_context,
&chunk_geometry,
BufferUsage::empty(),
);
self.world.chunk_buffers.insert(chunk_position, buffers);
}
let elapsed = instant.elapsed();
println!("World update took {:?}", elapsed);
}
pub fn load_npc_geometry(&mut self, render_context: &RenderContext) {
self.world.npc.vertex_buffer = Some(render_context.device.create_buffer_init(
&BufferInitDescriptor {
@ -326,7 +306,6 @@ impl WorldState {
creative: true,
};
world_state.update_world_geometry(render_context);
world_state.load_npc_geometry(render_context);
world_state
@ -367,32 +346,7 @@ impl WorldState {
render_pass.set_bind_group(1, &self.view_bind_group, &[]);
render_pass.set_bind_group(2, &self.time_bind_group, &[]);
let camera_pos = self.camera.position.to_vec();
let camera_pos = Vector2::new(camera_pos.x, camera_pos.z);
// TODO Move to World
for (position, buffers) in &self.world.chunk_buffers {
let pos = (position * CHUNK_ISIZE).cast().unwrap();
let pos = Vector2::new(pos.x, pos.z);
if (pos - camera_pos).magnitude() > 300.0 {
continue;
}
buffers.set_buffers(&mut render_pass);
buffers.draw_indexed(&mut render_pass);
triangle_count += buffers.index_count / 3;
}
{
let vertex_buffer = self.world.npc.vertex_buffer.as_ref();
let index_buffer = self.world.npc.index_buffer.as_ref();
render_pass.set_vertex_buffer(0, vertex_buffer.unwrap().slice(..));
render_pass
.set_index_buffer(index_buffer.unwrap().slice(..), wgpu::IndexFormat::Uint32);
render_pass.draw_indexed(0..self.world.npc.indices.len() as u32, 0, 0..1);
triangle_count += self.world.npc.indices.len() / 3;
}
triangle_count += self.world.render(&mut render_pass, &self.camera);
triangle_count
}
@ -409,57 +363,11 @@ impl WorldState {
}
}
/// TODO Move to World
fn update_aim(&mut self, render_context: &RenderContext) {
let camera = &self.camera;
let old = self.world.highlighted;
let new = self.world.raycast(camera.position, camera.direction());
let old_chunk = old.map(|(pos, _)| pos.map(|n| n.div_euclid(CHUNK_ISIZE)));
let new_chunk = new.map(|(pos, _)| pos.map(|n| n.div_euclid(CHUNK_ISIZE)));
if old != new {
self.world.highlighted = new;
if let Some(old_chunk_) = old_chunk {
self.world.update_chunk_geometry(render_context, old_chunk_);
}
if let Some(new_chunk_) = new_chunk {
// Don't update the same chunk twice
if old_chunk != new_chunk {
self.world.update_chunk_geometry(render_context, new_chunk_);
}
}
}
}
/// TODO Move to World
pub fn input_mouse_button(&mut self, button: &MouseButton, render_context: &RenderContext) {
let camera = &self.camera;
let world = &mut self.world;
if let Some((pos, face_normal)) = world.raycast(camera.position, camera.direction()) {
if button == &MouseButton::Left {
world.set_block(pos.x as isize, pos.y as isize, pos.z as isize, None);
self.world
.update_chunk_geometry(render_context, pos / CHUNK_ISIZE);
self.world.break_at_crosshair(render_context, &self.camera);
} else if button == &MouseButton::Right {
let new_pos = pos.cast().unwrap() + face_normal;
world.set_block(
new_pos.x as isize,
new_pos.y as isize,
new_pos.z as isize,
Some(Block {
block_type: BlockType::Cobblestone,
}),
);
self.world
.update_chunk_geometry(render_context, pos / CHUNK_ISIZE);
}
self.world.place_at_crosshair(render_context, &self.camera);
}
}
@ -541,7 +449,6 @@ impl WorldState {
pub fn update(&mut self, dt: Duration, render_context: &RenderContext) {
self.update_position(dt);
self.update_aim(render_context);
self.world.update(render_context, &self.camera);

View file

@ -2,16 +2,14 @@ use std::collections::{HashMap, VecDeque};
use crate::{
camera::Camera,
chunk::{Block, Chunk, CHUNK_ISIZE},
geometry::{Geometry, GeometryBuffers},
chunk::{Block, BlockType, Chunk, CHUNK_ISIZE},
geometry::GeometryBuffers,
npc::Npc,
render_context::RenderContext,
vertex::BlockVertex,
};
use ahash::AHashMap;
use cgmath::{EuclideanSpace, InnerSpace, Point3, Vector3};
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
use wgpu::BufferUsage;
use cgmath::{EuclideanSpace, InnerSpace, Point3, Vector2, Vector3};
use wgpu::{BufferUsage, RenderPass};
pub struct World {
pub chunks: HashMap<Point3<isize>, Chunk>,
@ -81,7 +79,9 @@ impl World {
}
}
// Load new chunks, if necessary
self.update_highlight(render_context, camera);
// Queue up new chunks for loading, if necessary
let camera_pos: Point3<isize> = camera.position.cast().unwrap();
let camera_chunk: Point3<isize> = camera_pos.map(|n| n.div_euclid(CHUNK_ISIZE));
let mut load_queue = Vec::new();
@ -104,6 +104,33 @@ impl World {
self.chunk_load_queue.extend(load_queue);
}
pub fn render<'a>(&'a self, render_pass: &mut RenderPass<'a>, camera: &Camera) -> usize {
let camera_pos = camera.position.to_vec();
let camera_pos = Vector2::new(camera_pos.x, camera_pos.z);
let mut triangle_count = 0;
for (position, buffers) in &self.chunk_buffers {
let pos = (position * CHUNK_ISIZE).cast().unwrap();
let pos = Vector2::new(pos.x, pos.z);
if (pos - camera_pos).magnitude() > 300.0 {
continue;
}
buffers.set_buffers(render_pass);
buffers.draw_indexed(render_pass);
triangle_count += buffers.index_count / 3;
}
{
let buffers = self.npc.geometry_buffers.as_ref().unwrap();
buffers.set_buffers(render_pass);
render_pass.draw_indexed(0..self.npc.indices.len() as u32, 0, 0..1);
triangle_count += self.npc.indices.len() / 3;
}
triangle_count
}
pub fn update_chunk_geometry(
&mut self,
render_context: &RenderContext,
@ -121,6 +148,53 @@ impl World {
self.chunk_buffers.insert(chunk_position, buffers);
}
fn update_highlight(&mut self, render_context: &RenderContext, camera: &Camera) {
let old = self.highlighted;
let new = self.raycast(camera.position, camera.direction());
let old_chunk = old.map(|(pos, _)| pos.map(|n| n.div_euclid(CHUNK_ISIZE)));
let new_chunk = new.map(|(pos, _)| pos.map(|n| n.div_euclid(CHUNK_ISIZE)));
if old != new {
self.highlighted = new;
if let Some(old_chunk_) = old_chunk {
self.update_chunk_geometry(render_context, old_chunk_);
}
if let Some(new_chunk_) = new_chunk {
// Don't update the same chunk twice
if old_chunk != new_chunk {
self.update_chunk_geometry(render_context, new_chunk_);
}
}
}
}
pub fn break_at_crosshair(&mut self, render_context: &RenderContext, camera: &Camera) {
if let Some((pos, _)) = self.raycast(camera.position, camera.direction()) {
self.set_block(pos.x as isize, pos.y as isize, pos.z as isize, None);
self.update_chunk_geometry(render_context, pos / CHUNK_ISIZE);
}
}
pub fn place_at_crosshair(&mut self, render_context: &RenderContext, camera: &Camera) {
if let Some((pos, face_normal)) = self.raycast(camera.position, camera.direction()) {
let new_pos = pos.cast().unwrap() + face_normal;
self.set_block(
new_pos.x as isize,
new_pos.y as isize,
new_pos.z as isize,
Some(Block {
block_type: BlockType::Cobblestone,
}),
);
self.update_chunk_geometry(render_context, pos / CHUNK_ISIZE);
}
}
pub fn highlighted_for_chunk(
highlighted: Option<(Point3<isize>, Vector3<i32>)>,
chunk_position: &Point3<isize>,
@ -144,29 +218,6 @@ impl World {
}
}
pub fn to_geometry(
&self,
highlighted: Option<(Point3<isize>, Vector3<i32>)>,
) -> Vec<(Point3<isize>, Geometry<BlockVertex>)> {
let instant = std::time::Instant::now();
let chunks = &self.chunks;
let geometry = chunks
.par_iter()
.map(|(chunk_position, chunk)| {
let position = (chunk_position * CHUNK_ISIZE).cast().unwrap();
let h = Self::highlighted_for_chunk(highlighted, chunk_position);
let geometry = chunk.to_geometry(position, h.as_ref());
(*chunk_position, geometry)
})
.collect();
let elapsed = instant.elapsed();
println!("Generating world geometry took {:?}", elapsed);
geometry
}
pub fn get_block(&self, x: isize, y: isize, z: isize) -> Option<&Block> {
let chunk = match self.chunks.get(&Point3::new(
x.div_euclid(CHUNK_ISIZE),