mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Improved worldgen performance with more precise z bound checks
This commit is contained in:
parent
71f4704502
commit
c2a11ed6b2
@ -1,7 +1,7 @@
|
||||
use super::Block;
|
||||
use crate::{
|
||||
assets::{self, Asset},
|
||||
vol::{BaseVol, ReadVol, Vox, WriteVol},
|
||||
vol::{BaseVol, ReadVol, SizedVol, Vox, WriteVol},
|
||||
volumes::dyna::{Dyna, DynaErr},
|
||||
};
|
||||
use dot_vox::DotVoxData;
|
||||
@ -44,6 +44,13 @@ impl Structure {
|
||||
self.center = center;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn get_bounds(&self) -> Aabb<i32> {
|
||||
Aabb {
|
||||
min: -self.center,
|
||||
max: self.vol.get_size().map(|e| e as i32) - self.center,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BaseVol for Structure {
|
||||
|
@ -84,7 +84,7 @@ impl Server {
|
||||
let mut state = State::default();
|
||||
state
|
||||
.ecs_mut()
|
||||
.add_resource(SpawnPoint(Vec3::new(16_384.0, 16_384.0, 305.0)));
|
||||
.add_resource(SpawnPoint(Vec3::new(16_384.0, 16_384.0, 380.0)));
|
||||
|
||||
let this = Self {
|
||||
state,
|
||||
|
@ -6,7 +6,7 @@ const vec3 SKY_DAY_BOT = vec3(0.02, 0.1, 0.3);
|
||||
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);
|
||||
const vec3 SKY_DUSK_MID = vec3(0.75, 0.3, 0.25);
|
||||
const vec3 SKY_DUSK_BOT = vec3(0.01, 0.05, 0.15);
|
||||
const vec3 DUSK_LIGHT = vec3(0.9, 0.2, 0.1);
|
||||
|
||||
|
@ -3,7 +3,7 @@ mod natural;
|
||||
use crate::{
|
||||
column::{ColumnGen, ColumnSample},
|
||||
util::{HashCache, RandomField, Sampler, SamplerMut},
|
||||
World,
|
||||
World, CONFIG,
|
||||
};
|
||||
use common::{
|
||||
terrain::{structure::StructureBlock, Block, Structure},
|
||||
@ -52,7 +52,7 @@ impl<'a> BlockGen<'a> {
|
||||
cache,
|
||||
Vec2::from(*cliff_pos),
|
||||
) {
|
||||
Some(cliff_sample) if cliff_sample.cliffs && cliff_sample.spawn_rate > 0.5 => {
|
||||
Some(cliff_sample) if cliff_sample.is_cliffs && cliff_sample.spawn_rate > 0.5 => {
|
||||
let cliff_pos3d = Vec3::from(*cliff_pos);
|
||||
|
||||
let height = RandomField::new(seed + 1).get(cliff_pos3d) % 48;
|
||||
@ -113,7 +113,11 @@ impl<'a> BlockGen<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
Some(ZCache { sample, structures })
|
||||
Some(ZCache {
|
||||
wpos,
|
||||
sample,
|
||||
structures,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_with_z_cache(&mut self, wpos: Vec3<i32>, z_cache: Option<&ZCache>) -> Option<Block> {
|
||||
@ -354,10 +358,44 @@ impl<'a> BlockGen<'a> {
|
||||
}
|
||||
|
||||
pub struct ZCache<'a> {
|
||||
wpos: Vec2<i32>,
|
||||
sample: ColumnSample<'a>,
|
||||
structures: [Option<(StructureInfo, ColumnSample<'a>)>; 9],
|
||||
}
|
||||
|
||||
impl<'a> ZCache<'a> {
|
||||
pub fn get_z_limits(&self) -> (f32, f32) {
|
||||
let cave_depth = if self.sample.cave_xy.abs() > 0.9 {
|
||||
(self.sample.alt - self.sample.cave_alt) + 8.0
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
|
||||
let min = self.sample.alt - (self.sample.chaos * 48.0 + cave_depth) - 4.0;
|
||||
|
||||
let cliff = if self.sample.near_cliffs { 48.0 } else { 0.0 };
|
||||
let warp = self.sample.chaos * 48.0;
|
||||
let structure = self.structures.iter().filter_map(|st| st.as_ref()).fold(
|
||||
0,
|
||||
|a, (st_info, st_sample)| {
|
||||
let bounds = st_info.volume.get_bounds();
|
||||
let min = Vec2::from(bounds.min + st_info.pos);
|
||||
let max = Vec2::from(bounds.max + st_info.pos);
|
||||
if (Aabr { min, max }).contains_point(self.wpos) {
|
||||
a.max(bounds.max.z)
|
||||
} else {
|
||||
a
|
||||
}
|
||||
},
|
||||
) as f32;
|
||||
|
||||
let max =
|
||||
(self.sample.alt + cliff + structure + warp + 8.0).max(self.sample.water_level + 2.0);
|
||||
|
||||
(min, max)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct StructureInfo {
|
||||
pos: Vec3<i32>,
|
||||
seed: u32,
|
||||
|
@ -9,9 +9,9 @@ use lazy_static::lazy_static;
|
||||
use std::sync::Arc;
|
||||
use vek::*;
|
||||
|
||||
static VOLUME_RAND: RandomPerm = RandomPerm::new(0);
|
||||
static UNIT_RAND: RandomPerm = RandomPerm::new(1);
|
||||
static QUIRKY_RAND: RandomPerm = RandomPerm::new(2);
|
||||
static VOLUME_RAND: RandomPerm = RandomPerm::new(0xDB21C052);
|
||||
static UNIT_RAND: RandomPerm = RandomPerm::new(0x700F4EC7);
|
||||
static QUIRKY_RAND: RandomPerm = RandomPerm::new(0xA634460F);
|
||||
|
||||
pub fn structure_gen<'a>(
|
||||
column_gen: &ColumnGen<'a>,
|
||||
@ -42,26 +42,43 @@ pub fn structure_gen<'a>(
|
||||
let wheight = st_sample.alt.max(cliff_height);
|
||||
let st_pos3d = Vec3::new(st_pos.x, st_pos.y, wheight as i32);
|
||||
|
||||
let volumes: &'static [_] = match st_sample.forest_kind {
|
||||
ForestKind::Palm => &PALMS,
|
||||
ForestKind::Savannah => &PALMS,
|
||||
ForestKind::Oak if QUIRKY_RAND.get(st_seed) % 64 == 0 => &QUIRKY,
|
||||
ForestKind::Oak if QUIRKY_RAND.get(st_seed) % 16 == 0 => &OAK_STUMPS,
|
||||
ForestKind::Oak => &OAKS,
|
||||
ForestKind::Pine => &PINES,
|
||||
ForestKind::SnowPine => &SNOW_PINES,
|
||||
let volumes: &'static [_] = if QUIRKY_RAND.get(st_seed) % 64 == 17 {
|
||||
&QUIRKY
|
||||
} else {
|
||||
match st_sample.forest_kind {
|
||||
ForestKind::Palm => &PALMS,
|
||||
ForestKind::Savannah => &PALMS,
|
||||
ForestKind::Oak if QUIRKY_RAND.get(st_seed) % 16 == 7 => &OAK_STUMPS,
|
||||
ForestKind::Oak => &OAKS,
|
||||
ForestKind::Pine => &PINES,
|
||||
ForestKind::SnowPine => &SNOW_PINES,
|
||||
}
|
||||
};
|
||||
|
||||
const UNIT_CHOICES: [(Vec2<i32>, Vec2<i32>); 1] = [(Vec2 { x: 1, y: 0 }, Vec2 { x: 0, y: 1 })];
|
||||
const UNIT_CHOICES: [(Vec2<i32>, Vec2<i32>); 8] = [
|
||||
(Vec2 { x: 1, y: 0 }, Vec2 { x: 0, y: 1 }),
|
||||
(Vec2 { x: 1, y: 0 }, Vec2 { x: 0, y: -1 }),
|
||||
(Vec2 { x: -1, y: 0 }, Vec2 { x: 0, y: 1 }),
|
||||
(Vec2 { x: -1, y: 0 }, Vec2 { x: 0, y: -1 }),
|
||||
(Vec2 { x: 0, y: 1 }, Vec2 { x: 1, y: 0 }),
|
||||
(Vec2 { x: 0, y: 1 }, Vec2 { x: -1, y: 0 }),
|
||||
(Vec2 { x: 0, y: -1 }, Vec2 { x: 1, y: 0 }),
|
||||
(Vec2 { x: 0, y: -1 }, Vec2 { x: -1, y: 0 }),
|
||||
];
|
||||
|
||||
Some(StructureInfo {
|
||||
pos: st_pos3d,
|
||||
seed: st_seed,
|
||||
units: UNIT_CHOICES[UNIT_RAND.get(st_seed) as usize % UNIT_CHOICES.len()],
|
||||
volume: &volumes[VOLUME_RAND.get(st_seed) as usize % volumes.len()],
|
||||
volume: &volumes[(VOLUME_RAND.get(st_seed) / 13) as usize % volumes.len()],
|
||||
})
|
||||
}
|
||||
|
||||
fn st_asset(path: &str, offset: impl Into<Vec3<i32>>) -> Arc<Structure> {
|
||||
assets::load_map(path, |s: Structure| s.with_center(offset.into()))
|
||||
.expect("Failed to load structure asset")
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref OAKS: Vec<Arc<Structure>> = vec![
|
||||
// green oaks
|
||||
@ -330,30 +347,14 @@ lazy_static! {
|
||||
|
||||
pub static ref SNOW_PINES: Vec<Arc<Structure>> = vec![
|
||||
// snow pines
|
||||
assets::load_map("world/tree/snow_pine/1.vox", |s: Structure| s
|
||||
.with_center(Vec3::new(15, 15, 14)))
|
||||
.unwrap(),
|
||||
assets::load_map("world/tree/snow_pine/2.vox", |s: Structure| s
|
||||
.with_center(Vec3::new(15, 15, 14)))
|
||||
.unwrap(),
|
||||
assets::load_map("world/tree/snow_pine/3.vox", |s: Structure| s
|
||||
.with_center(Vec3::new(17, 15, 12)))
|
||||
.unwrap(),
|
||||
assets::load_map("world/tree/snow_pine/4.vox", |s: Structure| s
|
||||
.with_center(Vec3::new(10, 8, 12)))
|
||||
.unwrap(),
|
||||
assets::load_map("world/tree/snow_pine/5.vox", |s: Structure| s
|
||||
.with_center(Vec3::new(12, 12, 12)))
|
||||
.unwrap(),
|
||||
assets::load_map("world/tree/snow_pine/6.vox", |s: Structure| s
|
||||
.with_center(Vec3::new(11, 10, 12)))
|
||||
.unwrap(),
|
||||
assets::load_map("world/tree/snow_pine/7.vox", |s: Structure| s
|
||||
.with_center(Vec3::new(16, 15, 12)))
|
||||
.unwrap(),
|
||||
assets::load_map("world/tree/snow_pine/8.vox", |s: Structure| s
|
||||
.with_center(Vec3::new(12, 10, 12)))
|
||||
.unwrap(),
|
||||
st_asset("world/tree/snow_pine/1.vox", (15, 15, 14)),
|
||||
st_asset("world/tree/snow_pine/2.vox", (15, 15, 14)),
|
||||
st_asset("world/tree/snow_pine/3.vox", (17, 15, 12)),
|
||||
st_asset("world/tree/snow_pine/4.vox", (10, 8, 12)),
|
||||
st_asset("world/tree/snow_pine/5.vox", (12, 12, 12)),
|
||||
st_asset("world/tree/snow_pine/6.vox", (11, 10, 12)),
|
||||
st_asset("world/tree/snow_pine/7.vox", (16, 15, 12)),
|
||||
st_asset("world/tree/snow_pine/8.vox", (12, 10, 12)),
|
||||
];
|
||||
/*
|
||||
// snow birches -> need roots!
|
||||
@ -404,8 +405,7 @@ lazy_static! {
|
||||
*/
|
||||
|
||||
pub static ref QUIRKY: Vec<Arc<Structure>> = vec![
|
||||
assets::load_map("world/structure/natural/tower_ruin.vox", |s: Structure| s
|
||||
.with_center(Vec3::new(11, 14, 7)))
|
||||
.unwrap(),
|
||||
st_asset("world/structure/natural/tower-ruin.vox", (11, 14, 5)),
|
||||
st_asset("world/structure/natural/witch-hut.vox", (10, 13, 3)),
|
||||
];
|
||||
}
|
||||
|
@ -64,7 +64,8 @@ impl<'a> Sampler for ColumnGen<'a> {
|
||||
.mul(chaos.max(0.15))
|
||||
.mul(64.0);
|
||||
|
||||
let cliffs = sim_chunk.cliffs;
|
||||
let is_cliffs = sim_chunk.is_cliffs;
|
||||
let near_cliffs = sim_chunk.near_cliffs;
|
||||
|
||||
let alt = riverless_alt
|
||||
- (1.0 - river)
|
||||
@ -249,7 +250,8 @@ impl<'a> Sampler for ColumnGen<'a> {
|
||||
cave_xy,
|
||||
cave_alt,
|
||||
rock,
|
||||
cliffs,
|
||||
is_cliffs,
|
||||
near_cliffs,
|
||||
cliff_hill,
|
||||
close_cliffs: sim.gen_ctx.cliff_gen.get(wpos),
|
||||
temp,
|
||||
@ -273,7 +275,8 @@ pub struct ColumnSample<'a> {
|
||||
pub cave_xy: f32,
|
||||
pub cave_alt: f32,
|
||||
pub rock: f32,
|
||||
pub cliffs: bool,
|
||||
pub is_cliffs: bool,
|
||||
pub near_cliffs: bool,
|
||||
pub cliff_hill: f32,
|
||||
pub close_cliffs: [(Vec2<i32>, u32); 9],
|
||||
pub temp: f32,
|
||||
|
@ -84,8 +84,8 @@ impl World {
|
||||
for y in 0..TerrainChunkSize::SIZE.y as i32 {
|
||||
let wpos2d = Vec2::new(x, y)
|
||||
+ Vec3::from(chunk_pos) * TerrainChunkSize::SIZE.map(|e| e as i32);
|
||||
let _wposf2d = wpos2d.map(|e| e as f64);
|
||||
|
||||
/*
|
||||
let min_z = self
|
||||
.sim
|
||||
.get_interpolated(wpos2d, |chunk| chunk.get_min_z())
|
||||
@ -95,15 +95,25 @@ impl World {
|
||||
.sim
|
||||
.get_interpolated(wpos2d, |chunk| chunk.get_max_z())
|
||||
.unwrap_or(0.0) as i32;
|
||||
*/
|
||||
|
||||
let z_cache = sampler.get_z_cache(wpos2d);
|
||||
let z_cache = match sampler.get_z_cache(wpos2d) {
|
||||
Some(z_cache) => z_cache,
|
||||
None => continue,
|
||||
};
|
||||
|
||||
for z in min_z..max_z {
|
||||
let (min_z, max_z) = z_cache.get_z_limits();
|
||||
|
||||
for z in base_z - 16..min_z as i32 {
|
||||
let _ = chunk.set(Vec3::new(x, y, z), stone);
|
||||
}
|
||||
|
||||
for z in min_z as i32..max_z as i32 {
|
||||
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_with_z_cache(wpos, z_cache.as_ref()) {
|
||||
if let Some(block) = sampler.get_with_z_cache(wpos, Some(&z_cache)) {
|
||||
let _ = chunk.set(lpos, block);
|
||||
}
|
||||
}
|
||||
|
@ -306,8 +306,6 @@ impl WorldSim {
|
||||
}
|
||||
}
|
||||
|
||||
const Z_TOLERANCE: (f32, f32) = (100.0, 128.0);
|
||||
|
||||
pub struct SimChunk {
|
||||
pub chaos: f32,
|
||||
pub alt_base: f32,
|
||||
@ -315,7 +313,7 @@ pub struct SimChunk {
|
||||
pub temp: f32,
|
||||
pub dryness: f32,
|
||||
pub rockiness: f32,
|
||||
pub cliffs: bool,
|
||||
pub is_cliffs: bool,
|
||||
pub near_cliffs: bool,
|
||||
pub tree_density: f32,
|
||||
pub forest_kind: ForestKind,
|
||||
@ -421,21 +419,23 @@ impl SimChunk {
|
||||
.sub(0.1)
|
||||
.mul(1.3)
|
||||
.max(0.0),
|
||||
cliffs: cliff > 0.5
|
||||
is_cliffs: cliff > 0.5
|
||||
&& dryness > 0.05
|
||||
&& alt > CONFIG.sea_level + 5.0
|
||||
&& dryness.abs() > 0.075,
|
||||
near_cliffs: cliff > 0.4,
|
||||
near_cliffs: cliff > 0.325,
|
||||
tree_density: (gen_ctx.tree_nz.get((wposf.div(1024.0)).into_array()) as f32)
|
||||
.mul(1.5)
|
||||
.add(1.0)
|
||||
.mul(0.5)
|
||||
.mul(1.2 - chaos * 0.95)
|
||||
.add(0.1)
|
||||
.add(0.05)
|
||||
.mul(if alt > CONFIG.sea_level + 5.0 {
|
||||
1.0
|
||||
} else {
|
||||
0.0
|
||||
}),
|
||||
})
|
||||
.max(0.0),
|
||||
forest_kind: if temp > 0.0 {
|
||||
if temp > CONFIG.desert_temp {
|
||||
ForestKind::Palm
|
||||
@ -457,16 +457,7 @@ impl SimChunk {
|
||||
}
|
||||
|
||||
pub fn get_base_z(&self) -> f32 {
|
||||
self.alt - Z_TOLERANCE.0 * self.chaos
|
||||
}
|
||||
|
||||
pub fn get_min_z(&self) -> f32 {
|
||||
self.alt - Z_TOLERANCE.0 * (self.chaos * 1.2 + 0.3)
|
||||
}
|
||||
|
||||
pub fn get_max_z(&self) -> f32 {
|
||||
(self.alt + Z_TOLERANCE.1 * if self.near_cliffs { 1.0 } else { 0.5 })
|
||||
.max(CONFIG.sea_level + 2.0)
|
||||
self.alt - self.chaos * 50.0
|
||||
}
|
||||
|
||||
pub fn get_name(&self, world: &WorldSim) -> Option<String> {
|
||||
|
Loading…
Reference in New Issue
Block a user