Performance improvements for terrain watcher

This commit is contained in:
Joshua Barretto 2021-07-19 00:10:55 +01:00
parent 1cfad833c7
commit 5c0026f4a7
5 changed files with 30 additions and 30 deletions

1
Cargo.lock generated
View File

@ -6275,6 +6275,7 @@ dependencies = [
"ordered-float 2.8.0", "ordered-float 2.8.0",
"profiling", "profiling",
"rand 0.8.4", "rand 0.8.4",
"rand_chacha 0.3.1",
"rayon", "rayon",
"rodio", "rodio",
"ron", "ron",

View File

@ -69,6 +69,22 @@ impl<V, S: RectVolSize, M: Clone> Chonk<V, S, M> {
self.sub_chunks.iter().map(SubChunk::num_groups).sum() self.sub_chunks.iter().map(SubChunk::num_groups).sum()
} }
/// Iterate through the voxels in this chunk, attempting to avoid those that are unchanged (i.e: match the `below`
/// and `above` voxels). This is generally useful for performance reasons.
pub fn iter_changed(&self) -> impl Iterator<Item = (Vec3<i32>, &V)> + '_ {
self.sub_chunks
.iter()
.enumerate()
.filter(|(_, sc)| sc.num_groups() > 0)
.map(move |(i, sc)| {
let z_offset = self.z_offset + i as i32 * SubChunkSize::<S>::SIZE.z as i32;
sc
.vol_iter(Vec3::zero(), SubChunkSize::<S>::SIZE.map(|e| e as i32))
.map(move |(pos, vox)| (pos + Vec3::unit_z() * z_offset, vox))
})
.flatten()
}
// Returns the index (in self.sub_chunks) of the SubChunk that contains // Returns the index (in self.sub_chunks) of the SubChunk that contains
// layer z; note that this index changes when more SubChunks are prepended // layer z; note that this index changes when more SubChunks are prepended
fn sub_chunk_idx(&self, z: i32) -> i32 { fn sub_chunk_idx(&self, z: i32) -> i32 {

View File

@ -1,8 +1,5 @@
use crate::hud::CraftingTab; use crate::hud::CraftingTab;
use common::{ use common::terrain::{BlockKind, SpriteKind, TerrainChunk};
terrain::{BlockKind, SpriteKind, TerrainChunk},
vol::{IntoVolIterator, RectRasterableVol},
};
use common_base::span; use common_base::span;
use rand::prelude::*; use rand::prelude::*;
use rand_chacha::ChaCha8Rng; use rand_chacha::ChaCha8Rng;
@ -64,14 +61,7 @@ impl BlocksOfInterest {
let mut rng = ChaCha8Rng::from_seed(thread_rng().gen()); let mut rng = ChaCha8Rng::from_seed(thread_rng().gen());
chunk chunk
.vol_iter( .iter_changed()
Vec3::new(0, 0, chunk.get_min_z()),
Vec3::new(
TerrainChunk::RECT_SIZE.x as i32,
TerrainChunk::RECT_SIZE.y as i32,
chunk.get_max_z(),
),
)
.for_each(|(pos, block)| { .for_each(|(pos, block)| {
match block.kind() { match block.kind() {
BlockKind::Leaves if rng.gen_range(0..16) == 0 => leaves.push(pos), BlockKind::Leaves if rng.gen_range(0..16) == 0 => leaves.push(pos),

View File

@ -607,14 +607,6 @@ pub fn apply_caverns_to<R: Rng>(canvas: &mut Canvas, dynamic_rng: &mut R) {
.mul((cavern_height as f64 - 5.0).mul(0.15).clamped(0.0, 1.0)) .mul((cavern_height as f64 - 5.0).mul(0.15).clamped(0.0, 1.0))
.mul(32.0 + cavern_avg_height as f64 * 0.85); .mul(32.0 + cavern_avg_height as f64 * 0.85);
let lake = info.index().noise.cave_nz
.get(wpos2d.map(|e| e as f64 * 0.01).into_array())
.sub(0.5)
.max(0.0)
.mul(2.0)
.mul(80.0);
let lake = 0.0;
let rugged = 0.25; // How bumpy should the floor be relative to the ceiling? let rugged = 0.25; // How bumpy should the floor be relative to the ceiling?
let cavern_bottom = (cavern_avg_alt - cavern_height * rugged) as i32; let cavern_bottom = (cavern_avg_alt - cavern_height * rugged) as i32;
let cavern_avg_bottom = (cavern_avg_alt - ((height_range.start + height_range.end) * 0.5) * rugged) as i32; let cavern_avg_bottom = (cavern_avg_alt - ((height_range.start + height_range.end) * 0.5) * rugged) as i32;
@ -626,7 +618,7 @@ pub fn apply_caverns_to<R: Rng>(canvas: &mut Canvas, dynamic_rng: &mut R) {
let floor = stalagmite as i32; let floor = stalagmite as i32;
(cavern_bottom, cavern_top, cavern_avg_bottom, cavern_avg_top, floor, lake, stalagtite) (cavern_bottom, cavern_top, cavern_avg_bottom, cavern_avg_top, floor, stalagtite)
}; };
let mut mushroom_cache = HashMap::new(); let mut mushroom_cache = HashMap::new();
@ -644,8 +636,8 @@ pub fn apply_caverns_to<R: Rng>(canvas: &mut Canvas, dynamic_rng: &mut R) {
.entry(wpos2d) .entry(wpos2d)
.or_insert_with(|| { .or_insert_with(|| {
let mut rng = RandomPerm::new(seed); let mut rng = RandomPerm::new(seed);
let (cavern_bottom, _, _, _, floor, _, _) = cavern_at(wpos2d); let (cavern_bottom, cavern_top, _, _, floor, _) = cavern_at(wpos2d);
if rng.gen_bool(0.1) { if rng.gen_bool(0.1) && cavern_top - cavern_bottom > 32 {
Some(Mushroom { Some(Mushroom {
pos: wpos2d.with_z(cavern_bottom + floor), pos: wpos2d.with_z(cavern_bottom + floor),
stalk: rng.gen_range(8.0..26.0), stalk: rng.gen_range(8.0..26.0),
@ -684,7 +676,7 @@ pub fn apply_caverns_to<R: Rng>(canvas: &mut Canvas, dynamic_rng: &mut R) {
return Some(Block::new(BlockKind::GlowingMushroom, mushroom.head_color)); return Some(Block::new(BlockKind::GlowingMushroom, mushroom.head_color));
} else if rpos.z <= mushroom.stalk && rpos.xy().magnitude_squared() < stalk_radius.powi(2) { // Stalk } else if rpos.z <= mushroom.stalk && rpos.xy().magnitude_squared() < stalk_radius.powi(2) { // Stalk
return Some(Block::new(BlockKind::Wood, Rgb::new(50, 120, 180))); return Some(Block::new(BlockKind::Wood, Rgb::new(50, 120, 180)));
} else if ((mushroom.stalk - 1.0)..mushroom.stalk).contains(&rpos.z) // Hanging orbs } else if ((mushroom.stalk - 0.5)..mushroom.stalk).contains(&rpos.z) // Hanging orbs
&& ((head_radius * 0.5)..(head_radius * 0.8)).contains(&dist) && ((head_radius * 0.5)..(head_radius * 0.8)).contains(&dist)
&& dynamic_rng.gen_bool(0.025) && dynamic_rng.gen_bool(0.025)
{ {
@ -697,7 +689,7 @@ pub fn apply_caverns_to<R: Rng>(canvas: &mut Canvas, dynamic_rng: &mut R) {
}; };
canvas.foreach_col(|canvas, wpos2d, _col| { canvas.foreach_col(|canvas, wpos2d, _col| {
let (cavern_bottom, cavern_top, cavern_avg_bottom, cavern_avg_top, floor, lake, stalagtite) = cavern_at(wpos2d); let (cavern_bottom, cavern_top, cavern_avg_bottom, cavern_avg_top, floor, stalagtite) = cavern_at(wpos2d);
let mini_stalagtite = info.index().noise.cave_nz let mini_stalagtite = info.index().noise.cave_nz
.get(wpos2d.map(|e| e as f64 * 0.08).into_array()) .get(wpos2d.map(|e| e as f64 * 0.08).into_array())
@ -708,14 +700,13 @@ pub fn apply_caverns_to<R: Rng>(canvas: &mut Canvas, dynamic_rng: &mut R) {
let stalagtite_height = (stalagtite + mini_stalagtite) as i32; let stalagtite_height = (stalagtite + mini_stalagtite) as i32;
let cavern_top = cavern_top as i32; let cavern_top = cavern_top as i32;
let lower_bound = cavern_bottom - lake as i32;
let mut on_ground = true; let mut on_ground = true;
for z in lower_bound..cavern_top { for z in cavern_bottom..cavern_top {
use SpriteKind::*; use SpriteKind::*;
let wpos = wpos2d.with_z(z); let wpos = wpos2d.with_z(z);
let block = if z < lower_bound + floor { let block = if z < cavern_bottom + floor {
Block::new(BlockKind::WeakRock, Rgb::new(110, 120, 150)) Block::new(BlockKind::WeakRock, Rgb::new(110, 120, 150))
} else if z > cavern_top - stalagtite_height { } else if z > cavern_top - stalagtite_height {
if dynamic_rng.gen_bool(0.0035) { // Glowing rock in stalagtites if dynamic_rng.gen_bool(0.0035) { // Glowing rock in stalagtites

View File

@ -55,6 +55,8 @@ use common_net::msg::{world_msg, WorldMapMsg};
use rand::Rng; use rand::Rng;
use serde::Deserialize; use serde::Deserialize;
use std::time::Duration; use std::time::Duration;
use rand_chacha::ChaCha8Rng;
use rand::prelude::*;
use vek::*; use vek::*;
#[derive(Debug)] #[derive(Debug)]
@ -329,7 +331,7 @@ impl World {
}; };
// Only use for rng affecting dynamic elements like chests and entities! // Only use for rng affecting dynamic elements like chests and entities!
let mut dynamic_rng = rand::thread_rng(); let mut dynamic_rng = ChaCha8Rng::from_seed(thread_rng().gen());
// Apply layers (paths, caves, etc.) // Apply layers (paths, caves, etc.)
let mut canvas = Canvas { let mut canvas = Canvas {
@ -365,7 +367,7 @@ impl World {
entities: canvas.entities, entities: canvas.entities,
}; };
let gen_entity_pos = |dynamic_rng: &mut rand::rngs::ThreadRng| { let gen_entity_pos = |dynamic_rng: &mut ChaCha8Rng| {
let lpos2d = TerrainChunkSize::RECT_SIZE let lpos2d = TerrainChunkSize::RECT_SIZE
.map(|sz| dynamic_rng.gen::<u32>().rem_euclid(sz) as i32); .map(|sz| dynamic_rng.gen::<u32>().rem_euclid(sz) as i32);
let mut lpos = Vec3::new( let mut lpos = Vec3::new(