mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Added terrain scatter densities
This commit is contained in:
parent
9329b4ce55
commit
6633298722
@ -20,6 +20,7 @@ use dot_vox::DotVoxData;
|
||||
use hashbrown::HashMap;
|
||||
use std::{f32, fmt::Debug, i32, marker::PhantomData, time::Duration};
|
||||
use treeculler::{BVol, Frustum, AABB};
|
||||
use tracing::warn;
|
||||
use vek::*;
|
||||
|
||||
struct TerrainChunkData {
|
||||
@ -142,7 +143,7 @@ fn sprite_config_for(kind: BlockKind) -> Option<SpriteConfig> {
|
||||
wind_sway: 0.1,
|
||||
}),
|
||||
BlockKind::LargeGrass => Some(SpriteConfig {
|
||||
variations: 3,
|
||||
variations: 1,
|
||||
wind_sway: 0.5,
|
||||
}),
|
||||
|
||||
@ -3141,23 +3142,28 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
let dist_sqrd = Vec2::from(focus_pos).distance_squared(chunk_center);
|
||||
if dist_sqrd < sprite_render_distance.powf(2.0) {
|
||||
for (kind, instances) in &chunk.sprite_instances {
|
||||
renderer.render_sprites(
|
||||
if dist_sqrd < sprite_high_detail_distance.powf(2.0) {
|
||||
&self.sprite_models[&kind][0]
|
||||
} else if dist_sqrd < sprite_hid_detail_distance.powf(2.0) {
|
||||
&self.sprite_models[&kind][1]
|
||||
} else if dist_sqrd < sprite_mid_detail_distance.powf(2.0) {
|
||||
&self.sprite_models[&kind][2]
|
||||
} else if dist_sqrd < sprite_low_detail_distance.powf(2.0) {
|
||||
&self.sprite_models[&kind][3]
|
||||
} else {
|
||||
&self.sprite_models[&kind][4]
|
||||
},
|
||||
globals,
|
||||
&instances,
|
||||
lights,
|
||||
shadows,
|
||||
);
|
||||
|
||||
if let Some(models) = self.sprite_models.get(&kind) {
|
||||
renderer.render_sprites(
|
||||
if dist_sqrd < sprite_high_detail_distance.powf(2.0) {
|
||||
&self.sprite_models[&kind][0]
|
||||
} else if dist_sqrd < sprite_hid_detail_distance.powf(2.0) {
|
||||
&self.sprite_models[&kind][1]
|
||||
} else if dist_sqrd < sprite_mid_detail_distance.powf(2.0) {
|
||||
&self.sprite_models[&kind][2]
|
||||
} else if dist_sqrd < sprite_low_detail_distance.powf(2.0) {
|
||||
&self.sprite_models[&kind][3]
|
||||
} else {
|
||||
&self.sprite_models[&kind][4]
|
||||
},
|
||||
globals,
|
||||
&instances,
|
||||
lights,
|
||||
shadows,
|
||||
);
|
||||
} else {
|
||||
warn!("Sprite model for {:?} does not exists", kind);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -283,6 +283,7 @@ impl<'a> BlockGen<'a> {
|
||||
&& marble_small > 0.55
|
||||
&& (marble * 3173.7).fract() < 0.6
|
||||
&& humidity > CONFIG.desert_hum
|
||||
&& false
|
||||
{
|
||||
let treasures = [BlockKind::Chest, BlockKind::Velorite];
|
||||
|
||||
@ -322,6 +323,7 @@ impl<'a> BlockGen<'a> {
|
||||
} else if (wposf.z as f32) < height + 0.9
|
||||
&& temp > CONFIG.desert_temp
|
||||
&& (marble * 4423.5).fract() < 0.0005
|
||||
&& false
|
||||
{
|
||||
let large_cacti = [
|
||||
BlockKind::LargeCactus,
|
||||
|
@ -22,12 +22,14 @@ impl Index {
|
||||
|
||||
pub struct Noise {
|
||||
pub cave_nz: SuperSimplex,
|
||||
pub scatter_nz: SuperSimplex,
|
||||
}
|
||||
|
||||
impl Noise {
|
||||
fn new(seed: u32) -> Self {
|
||||
Self {
|
||||
cave_nz: SuperSimplex::new().set_seed(seed),
|
||||
cave_nz: SuperSimplex::new().set_seed(seed + 0),
|
||||
scatter_nz: SuperSimplex::new().set_seed(seed + 1),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::{
|
||||
column::ColumnSample,
|
||||
util::{RandomField, Sampler},
|
||||
sim::SimChunk,
|
||||
Index,
|
||||
};
|
||||
use common::{
|
||||
@ -19,6 +20,70 @@ use std::{
|
||||
use vek::*;
|
||||
use rand::prelude::*;
|
||||
|
||||
fn close(x: f32, tgt: f32, falloff: f32) -> f32 { (1.0 - (x - tgt).abs() / falloff).max(0.0).powf(0.5) }
|
||||
|
||||
pub fn apply_scatter_to<'a>(
|
||||
wpos2d: Vec2<i32>,
|
||||
mut get_column: impl FnMut(Vec2<i32>) -> Option<&'a ColumnSample<'a>>,
|
||||
vol: &mut (impl BaseVol<Vox = Block> + RectSizedVol + ReadVol + WriteVol),
|
||||
index: &Index,
|
||||
chunk: &SimChunk,
|
||||
) {
|
||||
use BlockKind::*;
|
||||
let scatter: &[(_, fn(&SimChunk) -> (f32, Option<(f32, f32)>))] = &[
|
||||
// (density, Option<(wavelen, threshold)>)
|
||||
(BlueFlower, |c| (close(c.temp, -0.3, 0.7).min(close(c.humidity, 0.6, 0.35)) * 0.05, Some((48.0, 0.6)))),
|
||||
(PinkFlower, |c| (close(c.temp, 0.15, 0.5).min(close(c.humidity, 0.6, 0.35)) * 0.05, Some((48.0, 0.6)))),
|
||||
(DeadBush, |c| (close(c.temp, 0.8, 0.3).min(close(c.humidity, 0.0, 0.4)) * 0.015, None)),
|
||||
(Twigs, |c| ((c.tree_density - 0.5).max(0.0) * 0.0025, None)),
|
||||
(Stones, |c| ((c.rockiness - 0.5).max(0.0) * 0.005, None)),
|
||||
];
|
||||
|
||||
for y in 0..vol.size_xy().y as i32 {
|
||||
for x in 0..vol.size_xy().x as i32 {
|
||||
let offs = Vec2::new(x, y);
|
||||
|
||||
let wpos2d = wpos2d + offs;
|
||||
|
||||
// Sample terrain
|
||||
let col_sample = if let Some(col_sample) = get_column(offs) {
|
||||
col_sample
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let bk = scatter
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find_map(|(i, (bk, f))| {
|
||||
let (density, patch) = f(chunk);
|
||||
if density <= 0.0 || patch.map(|(wavelen, threshold)| index
|
||||
.noise
|
||||
.scatter_nz
|
||||
.get(wpos2d.map(|e| e as f64 / wavelen as f64 + i as f64 * 43.0).into_array()) < threshold as f64)
|
||||
.unwrap_or(false)
|
||||
|| !RandomField::new(i as u32).chance(Vec3::new(wpos2d.x, wpos2d.y, 0), density)
|
||||
{
|
||||
None
|
||||
} else {
|
||||
Some(*bk)
|
||||
}
|
||||
});
|
||||
|
||||
if let Some(bk) = bk {
|
||||
let mut z = col_sample.alt as i32 - 4;
|
||||
for _ in 0..8 {
|
||||
if vol.get(Vec3::new(offs.x, offs.y, z)).map(|b| !b.is_solid()).unwrap_or(true) {
|
||||
let _ = vol.set(Vec3::new(offs.x, offs.y, z), Block::new(bk, Rgb::broadcast(0)));
|
||||
break;
|
||||
}
|
||||
z += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn apply_paths_to<'a>(
|
||||
wpos2d: Vec2<i32>,
|
||||
mut get_column: impl FnMut(Vec2<i32>) -> Option<&'a ColumnSample<'a>>,
|
||||
@ -227,7 +292,7 @@ pub fn apply_caves_supplement<'a>(
|
||||
let cave_roof = (cave.alt + cave_height) as i32;
|
||||
|
||||
// Scatter things in caves
|
||||
if RandomField::new(index.seed).chance(wpos2d.into(), 0.0001)
|
||||
if RandomField::new(index.seed).chance(wpos2d.into(), 0.00005)
|
||||
&& cave_base < surface_z as i32 - 40
|
||||
{
|
||||
let entity = EntityInfo::at(Vec3::new(wpos2d.x as f32, wpos2d.y as f32, cave_base as f32))
|
||||
|
@ -176,6 +176,7 @@ impl World {
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
// Apply layers (paths, caves, etc.)
|
||||
layer::apply_scatter_to(chunk_wpos2d, sample_get, &mut chunk, &self.index, sim_chunk);
|
||||
layer::apply_paths_to(chunk_wpos2d, sample_get, &mut chunk, &self.index);
|
||||
layer::apply_caves_to(chunk_wpos2d, sample_get, &mut chunk, &self.index);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user