diff --git a/common/src/assets/mod.rs b/common/src/assets/mod.rs index e8e8c5bd28..00c65adfb3 100644 --- a/common/src/assets/mod.rs +++ b/common/src/assets/mod.rs @@ -36,7 +36,10 @@ lazy_static! { RwLock::new(HashMap::new()); } -pub fn load_map A>(specifier: &str, f: F) -> Result, Error> { +pub fn load_map A>( + specifier: &str, + f: F, +) -> Result, Error> { Ok(ASSETS .write() .unwrap() diff --git a/common/src/terrain/chonk.rs b/common/src/terrain/chonk.rs index a15e521e83..e5c4de955b 100644 --- a/common/src/terrain/chonk.rs +++ b/common/src/terrain/chonk.rs @@ -4,8 +4,8 @@ use crate::{ volumes::chunk::{Chunk, ChunkErr}, }; use serde_derive::{Deserialize, Serialize}; -use vek::*; use std::collections::HashMap; +use vek::*; #[derive(Debug)] pub enum ChonkError { @@ -76,7 +76,7 @@ impl ReadVol for Chonk { * (self.z_offset + sub_chunk_idx as i32 * SUB_CHUNK_HEIGHT as i32); Ok(map.get(&rpos).unwrap_or(cblock)) - }, + } SubChunk::Heterogeneous(chunk) => { let rpos = pos - Vec3::unit_z() @@ -113,11 +113,11 @@ impl WriteVol for Chonk { self.sub_chunks[sub_chunk_idx] = SubChunk::Hash(*cblock, map); Ok(()) - }, + } SubChunk::Hash(cblock, map) if map.len() < 1024 => { map.insert(rpos, block); Ok(()) - }, + } SubChunk::Hash(cblock, map) => { let mut new_chunk = Chunk::filled(*cblock, ()); new_chunk.set(rpos, block).unwrap(); // Can't fail (I hope) diff --git a/common/src/terrain/mod.rs b/common/src/terrain/mod.rs index 27a34abaa8..c60c7ec99a 100644 --- a/common/src/terrain/mod.rs +++ b/common/src/terrain/mod.rs @@ -4,11 +4,7 @@ pub mod chonk; pub mod structure; // Reexports -pub use self::{ - biome::BiomeKind, - block::Block, - structure::Structure, -}; +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 d38207d68c..7e455851ec 100644 --- a/common/src/terrain/structure.rs +++ b/common/src/terrain/structure.rs @@ -1,11 +1,11 @@ +use super::Block; +use crate::{ + assets::{self, load_from_path, Asset}, + vol::{BaseVol, ReadVol, Vox, WriteVol}, + volumes::dyna::{Dyna, DynaErr}, +}; use dot_vox::DotVoxData; use vek::*; -use crate::{ - assets::{self, Asset, load_from_path}, - volumes::dyna::{Dyna, DynaErr}, - vol::{Vox, BaseVol, ReadVol, WriteVol}, -}; -use super::Block; #[derive(Debug)] pub enum StructureError {} @@ -50,11 +50,11 @@ impl Asset for Structure { .map(|col| Rgba::from(col.to_ne_bytes()).into()) .collect::>(); - let mut vol = Dyna::filled(Vec3::new( - model.size.x, - model.size.y, - model.size.z, - ), Block::empty(), ()); + let mut vol = Dyna::filled( + Vec3::new(model.size.x, model.size.y, model.size.z), + Block::empty(), + (), + ); for voxel in &model.voxels { if let Some(&color) = palette.get(voxel.i as usize) { diff --git a/common/src/volumes/dyna.rs b/common/src/volumes/dyna.rs index 41cf7a446b..9c0968dbc7 100644 --- a/common/src/volumes/dyna.rs +++ b/common/src/volumes/dyna.rs @@ -1,6 +1,6 @@ // Library -use vek::*; use serde_derive::{Deserialize, Serialize}; +use vek::*; // Local use crate::vol::{BaseVol, ReadVol, SizedVol, Vox, WriteVol}; diff --git a/world/src/lib.rs b/world/src/lib.rs index 8909f25e6d..16a3acb68b 100644 --- a/world/src/lib.rs +++ b/world/src/lib.rs @@ -7,6 +7,7 @@ use common::{ terrain::{Block, TerrainChunk, TerrainChunkMeta, TerrainChunkSize}, vol::{SizedVol, VolSize, Vox, WriteVol}, }; +use fxhash::FxHashMap; use noise::{BasicMulti, MultiFractal, NoiseFn, Perlin, Seedable}; use std::{ hash::Hash, @@ -14,7 +15,6 @@ use std::{ time::Duration, }; use vek::*; -use fxhash::FxHashMap; #[derive(Debug)] pub enum Error { @@ -74,11 +74,12 @@ impl World { let wpos = lpos + Vec3::from(chunk_pos) * TerrainChunkSize::SIZE.map(|e| e as i32); - let sim::Sample3d { block } = if let Some(sample) = world_sampler.sample_3d(wpos) { - sample - } else { - continue - }; + let sim::Sample3d { block } = + if let Some(sample) = world_sampler.sample_3d(wpos) { + sample + } else { + continue; + }; let _ = chunk.set(lpos, block); } @@ -111,11 +112,13 @@ impl Cache { pub fn get V>(&mut self, k: K, f: F) -> &V { let mut counter = &mut self.counter; - &self.map + &self + .map .entry(k) .or_insert_with(|| { *counter += 1; (*counter, f(k)) - }).1 + }) + .1 } } diff --git a/world/src/sim.rs b/world/src/sim.rs index 00bebb6d3a..e2d375895a 100644 --- a/world/src/sim.rs +++ b/world/src/sim.rs @@ -1,17 +1,14 @@ -use crate::{ -structure::StructureGen2d, - Cache, -}; +use crate::{structure::StructureGen2d, Cache}; use common::{ assets, - terrain::{Block, TerrainChunkSize, Structure}, - vol::{Vox, VolSize, ReadVol}, + terrain::{Block, Structure, TerrainChunkSize}, + vol::{ReadVol, VolSize, Vox}, }; +use lazy_static::lazy_static; use noise::{ BasicMulti, HybridMulti, MultiFractal, NoiseFn, OpenSimplex, RidgedMulti, Seedable, SuperSimplex, }; -use lazy_static::lazy_static; use std::{ f32, ops::{Add, Div, Mul, Neg, Sub}, @@ -110,10 +107,11 @@ impl WorldSim { let mut x = [T::default(); 4]; for (x_idx, j) in (-1..3).enumerate() { - let y0 = f(self.get(pos.map2(Vec2::new(j, -1), |e, q| (e.max(0.0) as i32 + q) as u32))?); - let y1 = f(self.get(pos.map2(Vec2::new(j, 0), |e, q| (e.max(0.0) as i32 + q) as u32))?); - let y2 = f(self.get(pos.map2(Vec2::new(j, 1), |e, q| (e.max(0.0) as i32 + q) as u32))?); - let y3 = f(self.get(pos.map2(Vec2::new(j, 2), |e, q| (e.max(0.0) as i32 + q) as u32))?); + let y0 = + f(self.get(pos.map2(Vec2::new(j, -1), |e, q| (e.max(0.0) as i32 + q) as u32))?); + let y1 = f(self.get(pos.map2(Vec2::new(j, 0), |e, q| (e.max(0.0) as i32 + q) as u32))?); + let y2 = f(self.get(pos.map2(Vec2::new(j, 1), |e, q| (e.max(0.0) as i32 + q) as u32))?); + let y3 = f(self.get(pos.map2(Vec2::new(j, 2), |e, q| (e.max(0.0) as i32 + q) as u32))?); x[x_idx] = cubic(y0, y1, y2, y3, pos.y.fract() as f32); } @@ -160,7 +158,8 @@ impl<'a> Sampler<'a> { let marble = (sim.gen_ctx.hill_nz.get((wposf3d.div(64.0)).into_array()) as f32) .mul(0.5) - .add(1.0).mul(0.5); + .add(1.0) + .mul(0.5); // Colours let cold_grass = Rgb::new(0.05, 0.5, 0.3); @@ -188,7 +187,7 @@ impl<'a> Sampler<'a> { snow, (alt - SEA_LEVEL - 350.0 - alt_base - temp * 48.0) / 12.0, ), - (alt - SEA_LEVEL - 150.0) / 180.0 + (alt - SEA_LEVEL - 150.0) / 180.0, ), // Beach (alt - SEA_LEVEL - 2.0) / 5.0, @@ -200,7 +199,9 @@ impl<'a> Sampler<'a> { pub fn sample_2d(&mut self, wpos2d: Vec2) -> Option<&Sample2d> { let sim = &self.sim; - self.sample2d_cache.get(wpos2d, |wpos2d| Self::sample_2d_impl(sim, wpos2d)).as_ref() + self.sample2d_cache + .get(wpos2d, |wpos2d| Self::sample_2d_impl(sim, wpos2d)) + .as_ref() } pub fn sample_3d(&mut self, wpos: Vec3) -> Option { @@ -219,7 +220,10 @@ impl<'a> Sampler<'a> { // Apply warping - let warp = (self.sim.gen_ctx.warp_nz + let warp = (self + .sim + .gen_ctx + .warp_nz .get((wposf.div(Vec3::new(120.0, 120.0, 150.0))).into_array()) as f32) .mul((chaos - 0.1).max(0.0)) @@ -237,19 +241,22 @@ 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 = (&close_trees) - .iter() - .fold(air, |block, (tree_pos, tree_seed)| { - match self.sample_2d(*tree_pos) { - Some(tree_sample) if tree_sample.tree_density > 0.5 => { - let tree_pos3d = Vec3::new(tree_pos.x, tree_pos.y, tree_sample.alt as i32); - block.or(TREES[*tree_seed as usize % TREES.len()].get(wpos - tree_pos3d) - .map(|b| b.clone()) - .unwrap_or(Block::empty())) - }, - _ => block, - } - }); + let above_ground = + (&close_trees) + .iter() + .fold(air, |block, (tree_pos, tree_seed)| { + match self.sample_2d(*tree_pos) { + Some(tree_sample) if tree_sample.tree_density > 0.5 => { + let tree_pos3d = + Vec3::new(tree_pos.x, tree_pos.y, tree_sample.alt as i32); + block.or(TREES[*tree_seed as usize % TREES.len()] + .get(wpos - tree_pos3d) + .map(|b| b.clone()) + .unwrap_or(Block::empty())) + } + _ => block, + } + }); let z = wposf.z as f32; Some(Sample3d { @@ -268,18 +275,42 @@ impl<'a> Sampler<'a> { lazy_static! { static ref TREES: [Arc; 12] = [ - assets::load_map("world/tree/oak/1.vox", |s: Structure| s.with_center(Vec3::new(15, 18, 14))).unwrap(), - assets::load_map("world/tree/oak/2.vox", |s: Structure| s.with_center(Vec3::new(15, 18, 14))).unwrap(), - assets::load_map("world/tree/oak/3.vox", |s: Structure| s.with_center(Vec3::new(15, 18, 14))).unwrap(), - assets::load_map("world/tree/pine/3.vox", |s: Structure| s.with_center(Vec3::new(15, 15, 14))).unwrap(), - assets::load_map("world/tree/pine/4.vox", |s: Structure| s.with_center(Vec3::new(15, 15, 14))).unwrap(), - assets::load_map("world/tree/pine/5.vox", |s: Structure| s.with_center(Vec3::new(15, 15, 12))).unwrap(), - assets::load_map("world/tree/temperate/1.vox", |s: Structure| s.with_center(Vec3::new(4, 4, 7))).unwrap(), - assets::load_map("world/tree/temperate/2.vox", |s: Structure| s.with_center(Vec3::new(4, 4, 7))).unwrap(), - assets::load_map("world/tree/temperate/3.vox", |s: Structure| s.with_center(Vec3::new(4, 4, 7))).unwrap(), - assets::load_map("world/tree/temperate/4.vox", |s: Structure| s.with_center(Vec3::new(4, 4, 7))).unwrap(), - assets::load_map("world/tree/temperate/5.vox", |s: Structure| s.with_center(Vec3::new(4, 4, 7))).unwrap(), - assets::load_map("world/tree/temperate/6.vox", |s: Structure| s.with_center(Vec3::new(4, 4, 7))).unwrap(), + assets::load_map("world/tree/oak/1.vox", |s: Structure| s + .with_center(Vec3::new(15, 18, 14))) + .unwrap(), + assets::load_map("world/tree/oak/2.vox", |s: Structure| s + .with_center(Vec3::new(15, 18, 14))) + .unwrap(), + assets::load_map("world/tree/oak/3.vox", |s: Structure| s + .with_center(Vec3::new(15, 18, 14))) + .unwrap(), + assets::load_map("world/tree/pine/3.vox", |s: Structure| s + .with_center(Vec3::new(15, 15, 14))) + .unwrap(), + assets::load_map("world/tree/pine/4.vox", |s: Structure| s + .with_center(Vec3::new(15, 15, 14))) + .unwrap(), + assets::load_map("world/tree/pine/5.vox", |s: Structure| s + .with_center(Vec3::new(15, 15, 12))) + .unwrap(), + assets::load_map("world/tree/temperate/1.vox", |s: Structure| s + .with_center(Vec3::new(4, 4, 7))) + .unwrap(), + assets::load_map("world/tree/temperate/2.vox", |s: Structure| s + .with_center(Vec3::new(4, 4, 7))) + .unwrap(), + assets::load_map("world/tree/temperate/3.vox", |s: Structure| s + .with_center(Vec3::new(4, 4, 7))) + .unwrap(), + assets::load_map("world/tree/temperate/4.vox", |s: Structure| s + .with_center(Vec3::new(4, 4, 7))) + .unwrap(), + assets::load_map("world/tree/temperate/5.vox", |s: Structure| s + .with_center(Vec3::new(4, 4, 7))) + .unwrap(), + assets::load_map("world/tree/temperate/6.vox", |s: Structure| s + .with_center(Vec3::new(4, 4, 7))) + .unwrap(), ]; } @@ -327,9 +358,16 @@ impl SimChunk { let wposf = (pos * Vec2::from(TerrainChunkSize::SIZE)).map(|e| e as f64); let hill = (0.0 - + gen_ctx.hill_nz.get((wposf.div(3_500.0)).into_array()).mul(1.0) as f32 - + gen_ctx.hill_nz.get((wposf.div(1_000.0)).into_array()).mul(0.3) as f32 - ).add(0.3).max(0.0); + + gen_ctx + .hill_nz + .get((wposf.div(3_500.0)).into_array()) + .mul(1.0) as f32 + + gen_ctx + .hill_nz + .get((wposf.div(1_000.0)).into_array()) + .mul(0.3) as f32) + .add(0.3) + .max(0.0); let chaos = (gen_ctx.chaos_nz.get((wposf.div(4_000.0)).into_array()) as f32) .add(1.0) @@ -350,7 +388,8 @@ impl SimChunk { Self { chaos, alt_base, - alt: SEA_LEVEL + alt_base + alt: SEA_LEVEL + + alt_base + (0.0 + alt_main + gen_ctx.small_nz.get((wposf.div(300.0)).into_array()) as f32 diff --git a/world/src/structure.rs b/world/src/structure.rs index 55e5a5a532..4e51c0f206 100644 --- a/world/src/structure.rs +++ b/world/src/structure.rs @@ -8,20 +8,24 @@ pub struct StructureGen2d { impl StructureGen2d { pub fn new(seed: u32, freq: u32, spread: u32) -> Self { - Self { - seed, - freq, - spread, - } + Self { seed, freq, spread } } fn random(&self, seed: u32, pos: Vec2) -> u32 { let pos = pos.map(|e| (e * 13 + (1 << 31)) as u32); - let next = (self.seed + seed).wrapping_mul(0x168E3D1F).wrapping_add(0xDEADBEAD); - let next = next.rotate_left(13).wrapping_mul(133227).wrapping_add(pos.x); + let next = (self.seed + seed) + .wrapping_mul(0x168E3D1F) + .wrapping_add(0xDEADBEAD); + let next = next + .rotate_left(13) + .wrapping_mul(133227) + .wrapping_add(pos.x); let next = next.rotate_left(13).wrapping_mul(318912) ^ 0x42133742; - let next = next.rotate_left(13).wrapping_mul(938219).wrapping_add(pos.y); + let next = next + .rotate_left(13) + .wrapping_mul(938219) + .wrapping_add(pos.y); let next = next.rotate_left(13).wrapping_mul(313322) ^ 0xDEADBEEF; let next = next.rotate_left(13).wrapping_mul(929009) ^ 0xFF329DE3; let next = next.rotate_left(13).wrapping_mul(422671) ^ 0x42892942; @@ -38,10 +42,16 @@ impl StructureGen2d { let center = sample_closest + Vec2::new(i, j).map(|e| e as i32 - 1) * self.freq as i32 + self.freq as i32 / 2; - samples[i * 3 + j] = (center + Vec2::new( - (self.random(1, center) % (self.spread * 2)) as i32 - self.spread as i32, - (self.random(2, center) % (self.spread * 2)) as i32 - self.spread as i32, - ), self.random(3, center)); + samples[i * 3 + j] = ( + center + + Vec2::new( + (self.random(1, center) % (self.spread * 2)) as i32 + - self.spread as i32, + (self.random(2, center) % (self.spread * 2)) as i32 + - self.spread as i32, + ), + self.random(3, center), + ); } }