diff --git a/src/main.rs b/src/main.rs index 630382f..d33dbcd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -213,6 +213,8 @@ fn main() { game.tick(delta); game.server.tick(&mut game.renderer, delta); + game.renderer.update_camera(width, height); + game.server.world.compute_render_list(&mut game.renderer); game.chunk_builder.tick(&mut game.server.world, &mut game.renderer, delta); game.screen_sys.tick(delta, &mut game.renderer, &mut ui_container); diff --git a/src/render/mod.rs b/src/render/mod.rs index 0588e0b..b89fcfd 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -27,7 +27,7 @@ use image; use image::GenericImage; use byteorder::{WriteBytesExt, NativeEndian}; use serde_json; -use cgmath::{self, Vector, Point}; +use cgmath::{self, Vector, Point, SquareMatrix}; use world; use collision; @@ -66,6 +66,9 @@ pub struct Renderer { pub camera: Camera, perspective_matrix: cgmath::Matrix4, + camera_matrix: cgmath::Matrix4, + pub frustum: collision::Frustum, + pub view_vector: cgmath::Vector3, trans: Option, @@ -206,24 +209,17 @@ impl Renderer { yaw: 0.0, pitch: ::std::f64::consts::PI, }, - perspective_matrix: cgmath::Matrix4::zero(), + perspective_matrix: cgmath::Matrix4::identity(), + camera_matrix: cgmath::Matrix4::identity(), + frustum: collision::Frustum::from_matrix4(cgmath::Matrix4::identity()).unwrap(), + view_vector: cgmath::Vector3::zero(), trans: None, } } - pub fn tick(&mut self, world: &mut world::World, delta: f64, width: u32, height: u32) { + pub fn update_camera(&mut self, width: u32, height: u32) { use std::f64::consts::PI as PI64; - { - let rm = self.resources.read().unwrap(); - if rm.version() != self.resource_version { - self.resource_version = rm.version(); - trace!("Updating textures to {}", self.resource_version); - self.textures.write().unwrap().update_textures(self.resource_version); - } - } - - self.update_textures(delta); if self.last_height != height || self.last_width != width { self.last_width = width; @@ -242,6 +238,33 @@ impl Renderer { self.init_trans(width, height); } + self.view_vector = cgmath::Vector3::new( + ((self.camera.yaw - PI64/2.0).cos() * -self.camera.pitch.cos()) as f32, + (-self.camera.pitch.sin()) as f32, + (-(self.camera.yaw - PI64/2.0).sin() * -self.camera.pitch.cos()) as f32 + ); + let camera = cgmath::Point3::new(-self.camera.pos.x as f32, -self.camera.pos.y as f32, self.camera.pos.z as f32); + let camera_matrix = cgmath::Matrix4::look_at( + camera, + camera + cgmath::Point3::new(-self.view_vector.x, -self.view_vector.y, self.view_vector.z).to_vec(), + cgmath::Vector3::new(0.0, -1.0, 0.0) + ); + self.camera_matrix = camera_matrix * cgmath::Matrix4::from_nonuniform_scale(-1.0, 1.0, 1.0); + self.frustum = collision::Frustum::from_matrix4(self.perspective_matrix * self.camera_matrix).unwrap(); + } + + pub fn tick(&mut self, world: &mut world::World, delta: f64, width: u32, height: u32) { + { + let rm = self.resources.read().unwrap(); + if rm.version() != self.resource_version { + self.resource_version = rm.version(); + trace!("Updating textures to {}", self.resource_version); + self.textures.write().unwrap().update_textures(self.resource_version); + } + } + + self.update_textures(delta); + let trans = self.trans.as_mut().unwrap(); trans.main.bind(); @@ -256,28 +279,13 @@ impl Renderer { // Chunk rendering self.chunk_shader.program.use_program(); - let view_vector = cgmath::Vector3::new( - ((self.camera.yaw - PI64/2.0).cos() * -self.camera.pitch.cos()) as f32, - (-self.camera.pitch.sin()) as f32, - (-(self.camera.yaw - PI64/2.0).sin() * -self.camera.pitch.cos()) as f32 - ); - let camera = cgmath::Point3::new(-self.camera.pos.x as f32, -self.camera.pos.y as f32, self.camera.pos.z as f32); - let camera_matrix = cgmath::Matrix4::look_at( - camera, - camera + cgmath::Point3::new(-view_vector.x, -view_vector.y, view_vector.z).to_vec(), - cgmath::Vector3::new(0.0, -1.0, 0.0) - ); - let camera_matrix = camera_matrix * cgmath::Matrix4::from_nonuniform_scale(-1.0, 1.0, 1.0); - self.chunk_shader.perspective_matrix.set_matrix4(&self.perspective_matrix); - self.chunk_shader.camera_matrix.set_matrix4(&camera_matrix); + self.chunk_shader.camera_matrix.set_matrix4(&self.camera_matrix); self.chunk_shader.texture.set_int(0); self.chunk_shader.light_level.set_float(LIGHT_LEVEL); self.chunk_shader.sky_offset.set_float(SKY_OFFSET); - let frustum = collision::Frustum::from_matrix4(self.perspective_matrix * camera_matrix).unwrap(); - - for (pos, info) in world.get_render_list(&frustum) { + for (pos, info) in world.get_render_list() { if let Some(solid) = info.solid.as_ref() { self.chunk_shader.offset.set_int3(pos.0, pos.1 * 4096, pos.2); solid.array.bind(); @@ -292,7 +300,7 @@ impl Renderer { // Trans chunk rendering self.chunk_shader_alpha.program.use_program(); self.chunk_shader_alpha.perspective_matrix.set_matrix4(&self.perspective_matrix); - self.chunk_shader_alpha.camera_matrix.set_matrix4(&camera_matrix); + self.chunk_shader_alpha.camera_matrix.set_matrix4(&self.camera_matrix); self.chunk_shader_alpha.texture.set_int(0); self.chunk_shader_alpha.light_level.set_float(LIGHT_LEVEL); self.chunk_shader_alpha.sky_offset.set_float(SKY_OFFSET); diff --git a/src/world/mod.rs b/src/world/mod.rs index 2789a4f..5f5df0b 100644 --- a/src/world/mod.rs +++ b/src/world/mod.rs @@ -28,12 +28,15 @@ pub mod biome; pub struct World { chunks: HashMap>, + + render_list: Vec<(i32, i32, i32)>, } impl World { pub fn new() -> World { World { chunks: HashMap::with_hasher(BuildHasherDefault::default()), + render_list: vec![], } } @@ -57,21 +60,28 @@ impl World { } } - pub fn get_render_list(&self, frustum: &collision::Frustum) -> Vec<((i32, i32, i32), &render::ChunkBuffer)> { - let mut ret = vec![]; + pub fn compute_render_list(&mut self, renderer: &mut render::Renderer) { + self.render_list.clear(); for (pos, chunk) in &self.chunks { for (y, sec) in chunk.sections.iter().enumerate() { if let Some(sec) = sec.as_ref() { let pos = (pos.0, y as i32, pos.1); let min = cgmath::Point3::new(pos.0 as f32 * 16.0, -pos.1 as f32 * 16.0, pos.2 as f32 * 16.0); let bounds = collision::Aabb3::new(min, min + cgmath::Vector3::new(16.0, -16.0, 16.0)); - if frustum.contains(bounds) != collision::Relation::Out { - ret.push((pos, &sec.render_buffer)); + if renderer.frustum.contains(bounds) != collision::Relation::Out { + self.render_list.push(pos); } } } } - ret + } + + pub fn get_render_list(&self) -> Vec<((i32, i32, i32), &render::ChunkBuffer)> { + self.render_list.iter().map(|v| { + let chunk = self.chunks.get(&CPos(v.0, v.2)).unwrap(); + let sec = chunk.sections[v.1 as usize].as_ref().unwrap(); + (*v, &sec.render_buffer) + }).collect() } pub fn get_section_buffer(&mut self, x: i32, y: i32, z: i32) -> Option<&mut render::ChunkBuffer> {