From 1641c4f788c21ab4f8723657905527a33593cec0 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Wed, 3 Jul 2019 00:10:56 +0100 Subject: [PATCH 01/12] Added mesh worker queue limit to prevent throttling of meshing queue --- voxygen/src/scene/terrain.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index ed6544eb8c..463884ac47 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -50,6 +50,8 @@ fn mesh_worker( } } +const MAX_WORKERS_QUEUED: usize = 32; + pub struct Terrain { chunks: HashMap, TerrainChunk>, @@ -58,6 +60,7 @@ pub struct Terrain { mesh_send_tmp: mpsc::Sender, mesh_recv: mpsc::Receiver, mesh_todo: HashMap, ChunkMeshState>, + workers_queued: usize, } impl Terrain { @@ -72,6 +75,7 @@ impl Terrain { mesh_send_tmp: send, mesh_recv: recv, mesh_todo: HashMap::new(), + workers_queued: 0, } } @@ -149,6 +153,10 @@ impl Terrain { // Only spawn workers for meshing jobs without an active worker already. .filter(|todo| !todo.active_worker) { + if self.workers_queued >= MAX_WORKERS_QUEUED { + break; + } + // Find the area of the terrain we want. Because meshing needs to compute things like // ambient occlusion and edge elision, we also need the borders of the chunk's // neighbours too (hence the `- 1` and `+ 1`). @@ -199,6 +207,7 @@ impl Terrain { )); }); todo.active_worker = true; + self.workers_queued += 1; } // Receive a chunk mesh from a worker thread and upload it to the GPU, then store it. @@ -236,6 +245,8 @@ impl Terrain { // since it's either out of date or no longer needed. _ => {} } + + self.workers_queued -= 1; } // Construct view frustum From 61568eac7c789e33be0f21ce7560028218068a62 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Wed, 3 Jul 2019 10:47:23 +0100 Subject: [PATCH 02/12] Better grass colour --- world/src/column/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/world/src/column/mod.rs b/world/src/column/mod.rs index dff31775a0..d34ee14ef5 100644 --- a/world/src/column/mod.rs +++ b/world/src/column/mod.rs @@ -95,11 +95,11 @@ impl<'a> Sampler for ColumnGen<'a> { .mul(0.75) .add(1.0) .mul(0.5) - .add(marble_small.mul(0.25)); + .add(marble_small.sub(0.5).mul(0.25)); // Colours - let cold_grass = Rgb::new(0.05, 0.2, 0.1); - let warm_grass = Rgb::new(0.15, 0.65, 0.05); + let cold_grass = Rgb::new(0.0, 0.25, 0.13); + let warm_grass = Rgb::new(0.18, 0.65, 0.0); let cold_stone = Rgb::new(0.55, 0.7, 0.75); let warm_stone = Rgb::new(0.65, 0.65, 0.35); let beach_sand = Rgb::new(0.93, 0.84, 0.4); From 6fc2096daea71de7d3ba3355b73ad4853e1d3605 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Wed, 3 Jul 2019 20:58:09 +0100 Subject: [PATCH 03/12] Reenabled towns, lighter days --- voxygen/shaders/include/sky.glsl | 4 ++-- voxygen/src/scene/terrain.rs | 11 ----------- world/src/column/mod.rs | 2 -- world/src/sim/mod.rs | 4 ++-- 4 files changed, 4 insertions(+), 17 deletions(-) diff --git a/voxygen/shaders/include/sky.glsl b/voxygen/shaders/include/sky.glsl index 48b926ab1d..42346f26b3 100644 --- a/voxygen/shaders/include/sky.glsl +++ b/voxygen/shaders/include/sky.glsl @@ -3,7 +3,7 @@ const float PI = 3.141592; const vec3 SKY_DAY_TOP = vec3(0.2, 0.3, 0.9); const vec3 SKY_DAY_MID = vec3(0.15, 0.2, 0.8); const vec3 SKY_DAY_BOT = vec3(0.02, 0.1, 0.3); -const vec3 DAY_LIGHT = vec3(0.5, 0.5, 0.8); +const vec3 DAY_LIGHT = vec3(0.5, 0.5, 1.0); const vec3 SKY_DUSK_TOP = vec3(0.1, 0.15, 0.3); const vec3 SKY_DUSK_MID = vec3(0.9, 0.3, 0.2); @@ -25,7 +25,7 @@ vec3 get_sun_dir(float time_of_day) { } float get_sun_brightness(vec3 sun_dir) { - return max(-sun_dir.z + 0.6, 0.0) * 0.8; + return max(-sun_dir.z + 0.6, 0.0); } const float PERSISTENT_AMBIANCE = 0.008; diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 463884ac47..ed6544eb8c 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -50,8 +50,6 @@ fn mesh_worker( } } -const MAX_WORKERS_QUEUED: usize = 32; - pub struct Terrain { chunks: HashMap, TerrainChunk>, @@ -60,7 +58,6 @@ pub struct Terrain { mesh_send_tmp: mpsc::Sender, mesh_recv: mpsc::Receiver, mesh_todo: HashMap, ChunkMeshState>, - workers_queued: usize, } impl Terrain { @@ -75,7 +72,6 @@ impl Terrain { mesh_send_tmp: send, mesh_recv: recv, mesh_todo: HashMap::new(), - workers_queued: 0, } } @@ -153,10 +149,6 @@ impl Terrain { // Only spawn workers for meshing jobs without an active worker already. .filter(|todo| !todo.active_worker) { - if self.workers_queued >= MAX_WORKERS_QUEUED { - break; - } - // Find the area of the terrain we want. Because meshing needs to compute things like // ambient occlusion and edge elision, we also need the borders of the chunk's // neighbours too (hence the `- 1` and `+ 1`). @@ -207,7 +199,6 @@ impl Terrain { )); }); todo.active_worker = true; - self.workers_queued += 1; } // Receive a chunk mesh from a worker thread and upload it to the GPU, then store it. @@ -245,8 +236,6 @@ impl Terrain { // since it's either out of date or no longer needed. _ => {} } - - self.workers_queued -= 1; } // Construct view frustum diff --git a/world/src/column/mod.rs b/world/src/column/mod.rs index d34ee14ef5..44836c72cb 100644 --- a/world/src/column/mod.rs +++ b/world/src/column/mod.rs @@ -165,7 +165,6 @@ impl<'a> Sampler for ColumnGen<'a> { // Cities // TODO: In a later MR - /* let building = match &sim_chunk.location { Some(loc) => { let loc = &sim.locations[loc.loc_idx]; @@ -184,7 +183,6 @@ impl<'a> Sampler for ColumnGen<'a> { }; let alt = alt + building; - */ // Caves let cave_at = |wposf: Vec2| { diff --git a/world/src/sim/mod.rs b/world/src/sim/mod.rs index fac42e2ff5..6014db6726 100644 --- a/world/src/sim/mod.rs +++ b/world/src/sim/mod.rs @@ -120,9 +120,9 @@ impl WorldSim { pub fn seed_elements(&mut self) { let mut rng = self.rng.clone(); - let cell_size = 32; + let cell_size = 16; let grid_size = WORLD_SIZE / cell_size; - let loc_count = 250; + let loc_count = 100; let mut loc_grid = vec![None; grid_size.product()]; let mut locations = Vec::new(); From ef973faadf12c1b7b18ccb2c9e6ba768a1ce7d5f Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Thu, 4 Jul 2019 15:38:55 +0100 Subject: [PATCH 04/12] Throttled mesh scheduling to improve remesh performance --- voxygen/src/scene/terrain.rs | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index ed6544eb8c..740a649dd8 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -23,7 +23,7 @@ struct TerrainChunk { struct ChunkMeshState { pos: Vec2, started_tick: u64, - active_worker: bool, + active_worker: Option, } /// A type produced by mesh worker threads corresponding to the position and mesh of a chunk. @@ -129,7 +129,7 @@ impl Terrain { ChunkMeshState { pos, started_tick: current_tick, - active_worker: false, + active_worker: None, }, ); } @@ -147,8 +147,16 @@ impl Terrain { .mesh_todo .values_mut() // Only spawn workers for meshing jobs without an active worker already. - .filter(|todo| !todo.active_worker) + .filter(|todo| { + todo.active_worker + .map(|worker_tick| worker_tick < todo.started_tick) + .unwrap_or(true) + }) { + if client.thread_pool().queued_count() > 0 { + break; + } + // Find the area of the terrain we want. Because meshing needs to compute things like // ambient occlusion and edge elision, we also need the borders of the chunk's // neighbours too (hence the `- 1` and `+ 1`). @@ -189,16 +197,17 @@ impl Terrain { let pos = todo.pos; // Queue the worker thread. + let started_tick = todo.started_tick; client.thread_pool().execute(move || { let _ = send.send(mesh_worker( pos, (min_z as f32, max_z as f32), - current_tick, + started_tick, volume, aabb, )); }); - todo.active_worker = true; + todo.active_worker = Some(todo.started_tick); } // Receive a chunk mesh from a worker thread and upload it to the GPU, then store it. @@ -208,7 +217,7 @@ impl Terrain { match self.mesh_todo.get(&response.pos) { // It's the mesh we want, insert the newly finished model into the terrain model // data structure (convert the mesh to a model first of course). - Some(todo) if response.started_tick == todo.started_tick => { + Some(todo) if response.started_tick <= todo.started_tick => { self.chunks.insert( response.pos, TerrainChunk { @@ -230,7 +239,9 @@ impl Terrain { }, ); - self.mesh_todo.remove(&response.pos); + if response.started_tick == todo.started_tick { + self.mesh_todo.remove(&response.pos); + } } // Chunk must have been removed, or it was spawned on an old tick. Drop the mesh // since it's either out of date or no longer needed. From 6709b18cb64feca1211c71da958360655aa0cf83 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Thu, 4 Jul 2019 16:29:32 +0100 Subject: [PATCH 05/12] Made shadows darker --- voxygen/shaders/include/sky.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/voxygen/shaders/include/sky.glsl b/voxygen/shaders/include/sky.glsl index 42346f26b3..2cddb38394 100644 --- a/voxygen/shaders/include/sky.glsl +++ b/voxygen/shaders/include/sky.glsl @@ -31,7 +31,7 @@ float get_sun_brightness(vec3 sun_dir) { const float PERSISTENT_AMBIANCE = 0.008; vec3 get_sun_diffuse(vec3 norm, float time_of_day) { - const float SUN_AMBIANCE = 0.2; + const float SUN_AMBIANCE = 0.1; vec3 sun_dir = get_sun_dir(time_of_day); From 51ad1f199511852a6d0795f20d3da25a66c23243 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Thu, 4 Jul 2019 17:33:59 +0100 Subject: [PATCH 06/12] Improved remeshing performance --- Cargo.lock | 1 + voxygen/Cargo.toml | 1 + voxygen/src/scene/terrain.rs | 17 ++++++++--------- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4be83ee31a..62f282fd31 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2665,6 +2665,7 @@ dependencies = [ "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "frustum_query 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "gfx 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)", "gfx_device_gl 0.15.5 (registry+https://github.com/rust-lang/crates.io-index)", "gfx_window_glutin 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index d7c4129cf1..d47ec82782 100644 --- a/voxygen/Cargo.toml +++ b/voxygen/Cargo.toml @@ -55,3 +55,4 @@ rand = "0.5" frustum_query = "0.1.2" rodio = { git = "https://github.com/desttinghim/rodio.git", rev = "dd93f905c1afefaac03c496a666ecab27d3e391b" } crossbeam = "^0.7.1" +fxhash = "0.2" diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 740a649dd8..f7a00d4afc 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -9,7 +9,8 @@ use common::{ volumes::vol_map_2d::VolMap2dErr, }; use frustum_query::frustum::Frustum; -use std::{collections::HashMap, i32, ops::Mul, sync::mpsc, time::Duration}; +use std::{i32, ops::Mul, sync::mpsc, time::Duration}; +use fxhash::FxHashMap; use vek::*; struct TerrainChunk { @@ -51,13 +52,13 @@ fn mesh_worker( } pub struct Terrain { - chunks: HashMap, TerrainChunk>, + chunks: FxHashMap, TerrainChunk>, // The mpsc sender and receiver used for talking to meshing worker threads. // We keep the sender component for no reason other than to clone it and send it to new workers. mesh_send_tmp: mpsc::Sender, mesh_recv: mpsc::Receiver, - mesh_todo: HashMap, ChunkMeshState>, + mesh_todo: FxHashMap, ChunkMeshState>, } impl Terrain { @@ -67,11 +68,10 @@ impl Terrain { let (send, recv) = mpsc::channel(); Self { - chunks: HashMap::new(), - + chunks: FxHashMap::default(), mesh_send_tmp: send, mesh_recv: recv, - mesh_todo: HashMap::new(), + mesh_todo: FxHashMap::default(), } } @@ -143,15 +143,14 @@ impl Terrain { self.mesh_todo.remove(pos); } - for todo in self - .mesh_todo + for todo in self.mesh_todo .values_mut() - // Only spawn workers for meshing jobs without an active worker already. .filter(|todo| { todo.active_worker .map(|worker_tick| worker_tick < todo.started_tick) .unwrap_or(true) }) + .min_by_key(|todo| todo.active_worker.unwrap_or(0)) { if client.thread_pool().queued_count() > 0 { break; From 0c9843999baaea884aaeb12843c5a6d26abab4c6 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Thu, 4 Jul 2019 18:13:29 +0100 Subject: [PATCH 07/12] fmt --- voxygen/src/scene/terrain.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index f7a00d4afc..261ae1873b 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -9,8 +9,8 @@ use common::{ volumes::vol_map_2d::VolMap2dErr, }; use frustum_query::frustum::Frustum; -use std::{i32, ops::Mul, sync::mpsc, time::Duration}; use fxhash::FxHashMap; +use std::{i32, ops::Mul, sync::mpsc, time::Duration}; use vek::*; struct TerrainChunk { @@ -143,7 +143,8 @@ impl Terrain { self.mesh_todo.remove(pos); } - for todo in self.mesh_todo + for todo in self + .mesh_todo .values_mut() .filter(|todo| { todo.active_worker From d2ccbafe593d7f3ba4c392136c2a8ac4ada3bd26 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Thu, 4 Jul 2019 19:03:44 +0100 Subject: [PATCH 08/12] Made mesh scheduling fairer --- voxygen/src/scene/terrain.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 261ae1873b..a673050b6e 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -151,7 +151,7 @@ impl Terrain { .map(|worker_tick| worker_tick < todo.started_tick) .unwrap_or(true) }) - .min_by_key(|todo| todo.active_worker.unwrap_or(0)) + .min_by_key(|todo| todo.active_worker.unwrap_or(todo.started_tick)) { if client.thread_pool().queued_count() > 0 { break; From 33b7e729c98680a27d1a3084090b46df3af54b59 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Thu, 4 Jul 2019 20:59:57 +0100 Subject: [PATCH 09/12] Added block picking --- voxygen/src/session.rs | 43 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index 216632fd03..e46a7410e1 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -8,9 +8,7 @@ use crate::{ Direction, Error, GlobalState, PlayState, PlayStateResult, }; use client::{self, Client}; -use common::{ - clock::Clock, comp, comp::Pos, msg::ClientState, terrain::block::Block, vol::ReadVol, -}; +use common::{clock::Clock, comp, comp::Pos, msg::ClientState, terrain::Block, vol::ReadVol}; use log::{error, warn}; use std::{cell::RefCell, rc::Rc, time::Duration}; use vek::*; @@ -21,6 +19,7 @@ pub struct SessionState { hud: Hud, key_state: KeyState, controller: comp::Controller, + selected_block: Block, } /// Represents an active game session (i.e., the one being played). @@ -35,6 +34,7 @@ impl SessionState { key_state: KeyState::new(), controller: comp::Controller::default(), hud: Hud::new(window), + selected_block: Block::new(1, Rgb::broadcast(255)), } } } @@ -127,7 +127,8 @@ impl PlayState for SessionState { if b { let pos = (cam_pos + cam_dir * (d - 0.01)).map(|e| e.floor() as i32); - client.place_block(pos, Block::new(1, Rgb::broadcast(255))); // TODO: Handle block color with a command + client.place_block(pos, self.selected_block); // TODO: Handle block color with a command + } } else { self.controller.attack = state @@ -164,7 +165,39 @@ impl PlayState for SessionState { } } Event::InputUpdate(GameInput::Roll, state) => { - self.controller.roll = state; + let client = self.client.borrow(); + if client + .state() + .read_storage::() + .get(client.entity()) + .is_some() + { + if state { + let cam_pos = self.scene.camera().compute_dependents(&client).2; + let cam_dir = + (self.scene.camera().get_focus_pos() - cam_pos).normalized(); + + let (d, block) = { + let terrain = client.state().terrain(); + let ray = + terrain.ray(cam_pos, cam_pos + cam_dir * 100.0).cast(); + ( + ray.0, + if let Ok(Some(b)) = ray.1 { + Some(*b) + } else { + None + }, + ) + }; + + if let Some(block) = block { + self.selected_block = block; + } + } + } else { + self.controller.roll = state; + } } Event::InputUpdate(GameInput::Jump, state) => { self.controller.jump = state; From 6a484ce162b7b1aa7658baaa72c5deb65b9758bb Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Thu, 4 Jul 2019 22:54:43 +0100 Subject: [PATCH 10/12] fmt --- voxygen/src/session.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index e46a7410e1..1552edce71 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -128,7 +128,6 @@ impl PlayState for SessionState { let pos = (cam_pos + cam_dir * (d - 0.01)).map(|e| e.floor() as i32); client.place_block(pos, self.selected_block); // TODO: Handle block color with a command - } } else { self.controller.attack = state From 362387177558926a5c27857239d6688b3e80383a Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Fri, 5 Jul 2019 00:14:55 +0100 Subject: [PATCH 11/12] Initial implementation of z cache --- world/src/block/mod.rs | 68 +++++++++++++++++++++++++++++++----------- world/src/lib.rs | 6 ++-- 2 files changed, 55 insertions(+), 19 deletions(-) diff --git a/world/src/block/mod.rs b/world/src/block/mod.rs index 2ec165464c..301a79b221 100644 --- a/world/src/block/mod.rs +++ b/world/src/block/mod.rs @@ -74,20 +74,40 @@ impl<'a> BlockGen<'a> { }, ) } -} -impl<'a> SamplerMut for BlockGen<'a> { - type Index = Vec3; - type Sample = Option; - - fn get(&mut self, wpos: Vec3) -> Option { + pub fn get_z_cache(&mut self, wpos: Vec2) -> Option> { let BlockGen { world, column_cache, column_gen, } = self; - let ColumnSample { + let sample = Self::sample_column(column_gen, column_cache, wpos)?; + + let mut tree_samples = [None, None, None, None, None, None, None, None, None]; + + for i in 0..tree_samples.len() { + tree_samples[i] = Self::sample_column( + column_gen, + column_cache, + Vec2::from(sample.close_trees[i].0), + ); + } + + Some(ZCache { + sample, + tree_samples, + }) + } + + pub fn get_with_z_cache(&mut self, wpos: Vec3, z_cache: Option<&ZCache>) -> Option { + let BlockGen { + world, + column_cache, + column_gen, + } = self; + + let &ColumnSample { alt, chaos, water_level, @@ -105,7 +125,9 @@ impl<'a> SamplerMut for BlockGen<'a> { close_cliffs, //temp, .. - } = Self::sample_column(column_gen, column_cache, Vec2::from(wpos))?; + } = &z_cache?.sample; + + let tree_samples = &z_cache?.tree_samples; let wposf = wpos.map(|e| e as f64); @@ -285,17 +307,13 @@ impl<'a> SamplerMut for BlockGen<'a> { } else { match block { Some(block) => block, - None => (&close_trees) - .iter() - .fold(air, |block, (tree_pos, tree_seed)| { + None => (&close_trees).iter().enumerate().fold( + air, + |block, (tree_idx, (tree_pos, tree_seed))| { if !block.is_empty() { block } else { - match Self::sample_column( - column_gen, - column_cache, - Vec2::from(*tree_pos), - ) { + match &tree_samples[tree_idx] { Some(tree_sample) if tree_sample.tree_density > 0.5 + (*tree_seed as f32 / 1000.0).fract() * 0.2 @@ -332,10 +350,26 @@ impl<'a> SamplerMut for BlockGen<'a> { _ => block, } } - }), + }, + ), } }; Some(block) } } + +pub struct ZCache<'a> { + sample: ColumnSample<'a>, + tree_samples: [Option>; 9], +} + +impl<'a> SamplerMut for BlockGen<'a> { + type Index = Vec3; + type Sample = Option; + + fn get(&mut self, wpos: Vec3) -> Option { + let z_cache = self.get_z_cache(wpos.into()); + self.get_with_z_cache(wpos, z_cache.as_ref()) + } +} diff --git a/world/src/lib.rs b/world/src/lib.rs index f54460d297..15c691f0d9 100644 --- a/world/src/lib.rs +++ b/world/src/lib.rs @@ -52,7 +52,7 @@ impl World { ColumnGen::new(self) } - pub fn sample_blocks(&self) -> impl SamplerMut, Sample = Option> + '_ { + pub fn sample_blocks(&self) -> BlockGen { BlockGen::new(self, ColumnGen::new(self)) } @@ -96,12 +96,14 @@ impl World { .get_interpolated(wpos2d, |chunk| chunk.get_max_z()) .unwrap_or(0.0) as i32; + let z_cache = sampler.get_z_cache(wpos2d); + for z in min_z..max_z { let lpos = Vec3::new(x, y, z); let wpos = lpos + Vec3::from(chunk_pos) * TerrainChunkSize::SIZE.map(|e| e as i32); - if let Some(block) = sampler.get(wpos) { + if let Some(block) = sampler.get_with_z_cache(wpos, z_cache.as_ref()) { let _ = chunk.set(lpos, block); } } From abd07aea09bef8e783e1ed6852975bb44ca604ed Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Fri, 5 Jul 2019 21:37:38 +0100 Subject: [PATCH 12/12] Improved z caching --- world/src/block/mod.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/world/src/block/mod.rs b/world/src/block/mod.rs index 301a79b221..be6a98a5fc 100644 --- a/world/src/block/mod.rs +++ b/world/src/block/mod.rs @@ -82,10 +82,11 @@ impl<'a> BlockGen<'a> { column_gen, } = self; + // Main sample let sample = Self::sample_column(column_gen, column_cache, wpos)?; + // Tree samples let mut tree_samples = [None, None, None, None, None, None, None, None, None]; - for i in 0..tree_samples.len() { tree_samples[i] = Self::sample_column( column_gen, @@ -129,6 +130,7 @@ impl<'a> BlockGen<'a> { let tree_samples = &z_cache?.tree_samples; + let wpos2d = Vec2::from(wpos); let wposf = wpos.map(|e| e as f64); let (definitely_underground, height, water_height) = @@ -318,7 +320,8 @@ impl<'a> BlockGen<'a> { if tree_sample.tree_density > 0.5 + (*tree_seed as f32 / 1000.0).fract() * 0.2 && tree_sample.alt > tree_sample.water_level - && tree_sample.spawn_rate > 0.5 => + && tree_sample.spawn_rate > 0.5 + && wpos2d.distance_squared(*tree_pos) < 20 * 20 => { let cliff_height = Self::get_cliff_height( column_gen,