Move some more world-related stuff to World
This commit is contained in:
parent
0ca35638fc
commit
bd54a1bc14
2 changed files with 89 additions and 131 deletions
|
@ -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::{
|
use wgpu::{
|
||||||
util::{BufferInitDescriptor, DeviceExt},
|
util::{BufferInitDescriptor, DeviceExt},
|
||||||
BufferUsage, CommandEncoder, SwapChainTexture,
|
CommandEncoder, SwapChainTexture,
|
||||||
};
|
};
|
||||||
use winit::{
|
use winit::{
|
||||||
dpi::PhysicalSize,
|
dpi::PhysicalSize,
|
||||||
|
@ -12,8 +12,6 @@ use winit::{
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
camera::{Camera, Projection},
|
camera::{Camera, Projection},
|
||||||
chunk::{Block, BlockType, CHUNK_ISIZE},
|
|
||||||
geometry::GeometryBuffers,
|
|
||||||
render_context::RenderContext,
|
render_context::RenderContext,
|
||||||
texture::{Texture, TextureManager},
|
texture::{Texture, TextureManager},
|
||||||
time::Time,
|
time::Time,
|
||||||
|
@ -215,24 +213,6 @@ impl WorldState {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO Move to World
|
/// 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) {
|
pub fn load_npc_geometry(&mut self, render_context: &RenderContext) {
|
||||||
self.world.npc.vertex_buffer = Some(render_context.device.create_buffer_init(
|
self.world.npc.vertex_buffer = Some(render_context.device.create_buffer_init(
|
||||||
&BufferInitDescriptor {
|
&BufferInitDescriptor {
|
||||||
|
@ -326,7 +306,6 @@ impl WorldState {
|
||||||
creative: true,
|
creative: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
world_state.update_world_geometry(render_context);
|
|
||||||
world_state.load_npc_geometry(render_context);
|
world_state.load_npc_geometry(render_context);
|
||||||
|
|
||||||
world_state
|
world_state
|
||||||
|
@ -367,32 +346,7 @@ impl WorldState {
|
||||||
render_pass.set_bind_group(1, &self.view_bind_group, &[]);
|
render_pass.set_bind_group(1, &self.view_bind_group, &[]);
|
||||||
render_pass.set_bind_group(2, &self.time_bind_group, &[]);
|
render_pass.set_bind_group(2, &self.time_bind_group, &[]);
|
||||||
|
|
||||||
let camera_pos = self.camera.position.to_vec();
|
triangle_count += self.world.render(&mut render_pass, &self.camera);
|
||||||
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
|
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) {
|
pub fn input_mouse_button(&mut self, button: &MouseButton, render_context: &RenderContext) {
|
||||||
let camera = &self.camera;
|
if button == &MouseButton::Left {
|
||||||
|
self.world.break_at_crosshair(render_context, &self.camera);
|
||||||
let world = &mut self.world;
|
} else if button == &MouseButton::Right {
|
||||||
if let Some((pos, face_normal)) = world.raycast(camera.position, camera.direction()) {
|
self.world.place_at_crosshair(render_context, &self.camera);
|
||||||
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);
|
|
||||||
} 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -541,7 +449,6 @@ impl WorldState {
|
||||||
|
|
||||||
pub fn update(&mut self, dt: Duration, render_context: &RenderContext) {
|
pub fn update(&mut self, dt: Duration, render_context: &RenderContext) {
|
||||||
self.update_position(dt);
|
self.update_position(dt);
|
||||||
self.update_aim(render_context);
|
|
||||||
|
|
||||||
self.world.update(render_context, &self.camera);
|
self.world.update(render_context, &self.camera);
|
||||||
|
|
||||||
|
|
111
src/world.rs
111
src/world.rs
|
@ -2,16 +2,14 @@ use std::collections::{HashMap, VecDeque};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
camera::Camera,
|
camera::Camera,
|
||||||
chunk::{Block, Chunk, CHUNK_ISIZE},
|
chunk::{Block, BlockType, Chunk, CHUNK_ISIZE},
|
||||||
geometry::{Geometry, GeometryBuffers},
|
geometry::GeometryBuffers,
|
||||||
npc::Npc,
|
npc::Npc,
|
||||||
render_context::RenderContext,
|
render_context::RenderContext,
|
||||||
vertex::BlockVertex,
|
|
||||||
};
|
};
|
||||||
use ahash::AHashMap;
|
use ahash::AHashMap;
|
||||||
use cgmath::{EuclideanSpace, InnerSpace, Point3, Vector3};
|
use cgmath::{EuclideanSpace, InnerSpace, Point3, Vector2, Vector3};
|
||||||
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
|
use wgpu::{BufferUsage, RenderPass};
|
||||||
use wgpu::BufferUsage;
|
|
||||||
|
|
||||||
pub struct World {
|
pub struct World {
|
||||||
pub chunks: HashMap<Point3<isize>, Chunk>,
|
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_pos: Point3<isize> = camera.position.cast().unwrap();
|
||||||
let camera_chunk: Point3<isize> = camera_pos.map(|n| n.div_euclid(CHUNK_ISIZE));
|
let camera_chunk: Point3<isize> = camera_pos.map(|n| n.div_euclid(CHUNK_ISIZE));
|
||||||
let mut load_queue = Vec::new();
|
let mut load_queue = Vec::new();
|
||||||
|
@ -104,6 +104,33 @@ impl World {
|
||||||
self.chunk_load_queue.extend(load_queue);
|
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(
|
pub fn update_chunk_geometry(
|
||||||
&mut self,
|
&mut self,
|
||||||
render_context: &RenderContext,
|
render_context: &RenderContext,
|
||||||
|
@ -121,6 +148,53 @@ impl World {
|
||||||
self.chunk_buffers.insert(chunk_position, buffers);
|
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(
|
pub fn highlighted_for_chunk(
|
||||||
highlighted: Option<(Point3<isize>, Vector3<i32>)>,
|
highlighted: Option<(Point3<isize>, Vector3<i32>)>,
|
||||||
chunk_position: &Point3<isize>,
|
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> {
|
pub fn get_block(&self, x: isize, y: isize, z: isize) -> Option<&Block> {
|
||||||
let chunk = match self.chunks.get(&Point3::new(
|
let chunk = match self.chunks.get(&Point3::new(
|
||||||
x.div_euclid(CHUNK_ISIZE),
|
x.div_euclid(CHUNK_ISIZE),
|
||||||
|
|
Loading…
Reference in a new issue