diff --git a/Cargo.lock b/Cargo.lock index 1fc9905ab0..d113f9fc0e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2708,6 +2708,7 @@ name = "veloren-world" version = "0.2.0" dependencies = [ "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "minifb 0.11.2 (git+https://github.com/emoon/rust_minifb.git)", "noise 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "vek 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/assets/world/tree/pine/3.vox b/assets/world/tree/pine/3.vox new file mode 100644 index 0000000000..94170360b7 Binary files /dev/null and b/assets/world/tree/pine/3.vox differ diff --git a/common/src/assets/mod.rs b/common/src/assets/mod.rs index c1fd3e5c50..e8e8c5bd28 100644 --- a/common/src/assets/mod.rs +++ b/common/src/assets/mod.rs @@ -36,6 +36,16 @@ lazy_static! { RwLock::new(HashMap::new()); } +pub fn load_map A>(specifier: &str, f: F) -> Result, Error> { + Ok(ASSETS + .write() + .unwrap() + .entry(specifier.to_string()) + .or_insert(Arc::new(f(A::load(specifier)?))) + .clone() + .downcast()?) +} + /// Function used to load assets. /// Loaded assets are cached in a global singleton hashmap. /// Example usage: @@ -46,13 +56,7 @@ lazy_static! { /// let my_image = assets::load::("core.ui.backgrounds.city").unwrap(); /// ``` pub fn load(specifier: &str) -> Result, Error> { - Ok(ASSETS - .write() - .unwrap() - .entry(specifier.to_string()) - .or_insert(Arc::new(A::load(specifier)?)) - .clone() - .downcast()?) + load_map(specifier, |x| x) } /// Function used to load assets that will panic if the asset is not found. diff --git a/common/src/terrain/mod.rs b/common/src/terrain/mod.rs index bcaa6b7d6b..27a34abaa8 100644 --- a/common/src/terrain/mod.rs +++ b/common/src/terrain/mod.rs @@ -4,7 +4,11 @@ pub mod chonk; pub mod structure; // Reexports -pub use self::{biome::BiomeKind, block::Block}; +pub use self::{ + biome::BiomeKind, + block::Block, + structure::Structure, +}; use crate::{ vol::VolSize, diff --git a/common/src/terrain/structure.rs b/common/src/terrain/structure.rs index 6806b06b2b..d38207d68c 100644 --- a/common/src/terrain/structure.rs +++ b/common/src/terrain/structure.rs @@ -10,6 +10,7 @@ use super::Block; #[derive(Debug)] pub enum StructureError {} +#[derive(Clone)] pub struct Structure { center: Vec3, vol: Dyna, @@ -31,7 +32,7 @@ impl BaseVol for Structure { impl ReadVol for Structure { #[inline(always)] fn get(&self, pos: Vec3) -> Result<&Block, StructureError> { - match self.vol.get(pos - self.center) { + match self.vol.get(pos + self.center) { Ok(block) => Ok(block), Err(DynaErr::OutOfBounds) => Ok(&self.empty), } diff --git a/common/src/volumes/dyna.rs b/common/src/volumes/dyna.rs index fbbbb87d3d..41cf7a446b 100644 --- a/common/src/volumes/dyna.rs +++ b/common/src/volumes/dyna.rs @@ -1,5 +1,6 @@ // Library use vek::*; +use serde_derive::{Deserialize, Serialize}; // Local use crate::vol::{BaseVol, ReadVol, SizedVol, Vox, WriteVol}; @@ -13,6 +14,7 @@ pub enum DynaErr { // V = Voxel // S = Size (replace when const generics are a thing) // M = Metadata +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct Dyna { vox: Vec, meta: M, diff --git a/world/Cargo.toml b/world/Cargo.toml index 48c6b0f045..dc07295de9 100644 --- a/world/Cargo.toml +++ b/world/Cargo.toml @@ -9,6 +9,7 @@ common = { package = "veloren-common", path = "../common" } vek = "0.9" noise = "0.5" fxhash = "0.2" +lazy_static = "1.3" [dev-dependencies] minifb = { git = "https://github.com/emoon/rust_minifb.git" } diff --git a/world/src/sim.rs b/world/src/sim.rs index ba5b46720b..d6f9262308 100644 --- a/world/src/sim.rs +++ b/world/src/sim.rs @@ -3,16 +3,19 @@ structure::StructureGen2d, Cache, }; use common::{ - terrain::{Block, TerrainChunkSize}, - vol::{Vox, VolSize}, + assets, + terrain::{Block, TerrainChunkSize, Structure}, + vol::{Vox, VolSize, ReadVol}, }; use noise::{ BasicMulti, HybridMulti, MultiFractal, NoiseFn, OpenSimplex, RidgedMulti, Seedable, SuperSimplex, }; +use lazy_static::lazy_static; use std::{ f32, ops::{Add, Div, Mul, Neg, Sub}, + sync::Arc, }; use vek::*; @@ -53,7 +56,7 @@ impl WorldSim { seed, chunks, gen_ctx, - tree_gen: StructureGen2d::new(seed, 64, 32), + tree_gen: StructureGen2d::new(seed, 48, 32), } } @@ -208,7 +211,7 @@ impl<'a> Sampler<'a> { chaos, surface_color, close_trees, - } = self.sample_2d(wpos2d)?; + } = *self.sample_2d(wpos2d)?; // Apply warping @@ -230,16 +233,19 @@ impl<'a> Sampler<'a> { let sand = Block::new(4, Rgb::new(180, 150, 50)); let water = Block::new(5, Rgb::new(100, 150, 255)); - let above_ground = if (&close_trees) + let above_ground = (&close_trees) .iter() - .any(|tree| { - tree.distance_squared(wpos.into()) < 36 - }) - { - grass - } else { - air - }; + .fold(air, |block, tree| { + match self.sample_2d(*tree) { + Some(tree_sample) => { + let tree_pos = Vec3::new(tree.x, tree.y, tree_sample.alt as i32); + block.or(TREE.get(wpos - tree_pos) + .map(|b| b.clone()) + .unwrap_or(Block::empty())) + }, + None => block, + } + }); let z = wposf.z as f32; Some(Sample3d { @@ -256,6 +262,13 @@ impl<'a> Sampler<'a> { } } +lazy_static! { + static ref TREE: Arc = assets::load_map( + "world/tree/pine/3.vox", + |s: Structure| s.with_center(Vec3::new(15, 15, 14)), + ).unwrap(); +} + #[derive(Copy, Clone)] pub struct Sample2d { pub alt: f32, @@ -264,6 +277,7 @@ pub struct Sample2d { pub close_trees: [Vec2; 9], } +#[derive(Copy, Clone)] pub struct Sample3d { pub block: Block, } @@ -280,7 +294,7 @@ struct GenCtx { warp_nz: BasicMulti, } -const Z_TOLERANCE: (f32, f32) = (32.0, 64.0); +const Z_TOLERANCE: (f32, f32) = (48.0, 64.0); pub const SEA_LEVEL: f32 = 64.0; pub struct SimChunk {