diff --git a/assets/world/manifests/shrubs.ron b/assets/world/manifests/shrubs.ron new file mode 100644 index 0000000000..ffefe8dfe6 --- /dev/null +++ b/assets/world/manifests/shrubs.ron @@ -0,0 +1,8 @@ +#![enable(unwrap_newtypes)] + +[ + ( + specifier: "world.shrub.1", + center: (6, 6, 2), + ), +] diff --git a/assets/world/shrub/1.vox b/assets/world/shrub/1.vox new file mode 100644 index 0000000000..8342c6742c --- /dev/null +++ b/assets/world/shrub/1.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f08946c4ceebc280dfd30e86eeda045b85f0502620bfbff194e425e9550e64e2 +size 1332 diff --git a/world/src/layer/mod.rs b/world/src/layer/mod.rs index 1ed4cc8410..9d3148eb80 100644 --- a/world/src/layer/mod.rs +++ b/world/src/layer/mod.rs @@ -1,9 +1,12 @@ pub mod scatter; +pub mod shrub; pub mod spot; pub mod tree; pub mod wildlife; -pub use self::{scatter::apply_scatter_to, spot::apply_spots_to, tree::apply_trees_to}; +pub use self::{ + scatter::apply_scatter_to, shrub::apply_shrubs_to, spot::apply_spots_to, tree::apply_trees_to, +}; use crate::{ column::ColumnSample, diff --git a/world/src/layer/shrub.rs b/world/src/layer/shrub.rs new file mode 100644 index 0000000000..8b64402766 --- /dev/null +++ b/world/src/layer/shrub.rs @@ -0,0 +1,57 @@ +use crate::{ + util::{seed_expan, RandomPerm, Sampler, StructureGen2d, UnitChooser}, + Canvas, +}; +use common::{ + assets::AssetHandle, + terrain::structure::{Structure, StructuresGroup}, + vol::ReadVol, +}; +use hashbrown::HashMap; +use lazy_static::lazy_static; +use rand::prelude::*; +use rand_chacha::ChaChaRng; +use vek::*; + +lazy_static! { + static ref SHRUBS: AssetHandle = Structure::load_group("shrubs"); +} + +struct Shrub { + wpos: Vec3, + seed: u32, +} + +pub fn apply_shrubs_to(canvas: &mut Canvas, rng: &mut impl Rng) { + let mut shrub_cache = HashMap::new(); + + let shrub_gen = StructureGen2d::new(canvas.index().seed, 8, 4); + + let info = canvas.info(); + canvas.foreach_col(|canvas, wpos2d, col| { + for (wpos, seed) in std::array::IntoIter::new(shrub_gen.get(wpos2d)) { + shrub_cache.entry(wpos).or_insert_with(|| { + let col = info.col_or_gen(wpos)?; + + if RandomPerm::new(seed).chance(37, col.tree_density * 0.3) { + Some(Shrub { + wpos: wpos.with_z(col.alt as i32), + seed, + }) + } else { + None + } + }); + } + }); + + for shrub in shrub_cache.values().filter_map(|s| s.as_ref()) { + let mut rng = ChaChaRng::from_seed(seed_expan::rng_state(shrub.seed)); + + let units = UnitChooser::new(shrub.seed).get(shrub.seed).into(); + + let shrubs = SHRUBS.read(); + let structure = shrubs.choose(&mut rng).unwrap(); + canvas.blit_structure(shrub.wpos, structure, shrub.seed, units, true); + } +} diff --git a/world/src/layer/tree.rs b/world/src/layer/tree.rs index a511b4ffad..dfbd12e2fa 100644 --- a/world/src/layer/tree.rs +++ b/world/src/layer/tree.rs @@ -360,7 +360,7 @@ impl TreeConfig { } pub fn jungle(rng: &mut impl Rng, scale: f32) -> Self { - let scale = scale * (0.9 + rng.gen::().powi(4) * 1.0); + let scale = scale * (0.8 + rng.gen::() * 0.5); let log_scale = 1.0 + scale.log2().max(0.0); Self { @@ -469,14 +469,14 @@ impl TreeConfig { branch_child_len: 0.75, branch_child_radius: 0.75, branch_child_radius_lerp: true, - leaf_radius: 2.0 * log_scale..2.1 * log_scale, + leaf_radius: 1.5 * log_scale..2.0 * log_scale, leaf_radius_scaled: 0.0, straightness: 0.3, max_depth: 5, splits: 3.5..4.25, split_range: 0.5..1.25, branch_len_bias: 0.0, - leaf_vertical_scale: 0.5, + leaf_vertical_scale: 0.65, proportionality: 0.5, inhabited: false, hanging_sprites: &[(0.00007, SpriteKind::Beehive)], diff --git a/world/src/lib.rs b/world/src/lib.rs index 2ebd01a561..72edb90318 100644 --- a/world/src/lib.rs +++ b/world/src/lib.rs @@ -347,6 +347,7 @@ impl World { }; layer::apply_caves_to(&mut canvas, &mut dynamic_rng); + layer::apply_shrubs_to(&mut canvas, &mut dynamic_rng); layer::apply_trees_to(&mut canvas, &mut dynamic_rng); layer::apply_scatter_to(&mut canvas, &mut dynamic_rng); layer::apply_paths_to(&mut canvas);