Former-commit-id: 689464ed1009ebfd74769fa113fc7b433ea62bbd
This commit is contained in:
Joshua Barretto 2019-05-25 06:54:47 +01:00
parent 16b80ab006
commit 92391883a9
8 changed files with 137 additions and 86 deletions

View File

@ -36,7 +36,10 @@ lazy_static! {
RwLock::new(HashMap::new());
}
pub fn load_map<A: Asset + 'static, F: FnOnce(A) -> A>(specifier: &str, f: F) -> Result<Arc<A>, Error> {
pub fn load_map<A: Asset + 'static, F: FnOnce(A) -> A>(
specifier: &str,
f: F,
) -> Result<Arc<A>, Error> {
Ok(ASSETS
.write()
.unwrap()

View File

@ -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)

View File

@ -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,

View File

@ -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::<Vec<_>>();
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) {

View File

@ -1,6 +1,6 @@
// Library
use vek::*;
use serde_derive::{Deserialize, Serialize};
use vek::*;
// Local
use crate::vol::{BaseVol, ReadVol, SizedVol, Vox, WriteVol};

View File

@ -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<K: Hash + Eq + Copy, V> Cache<K, V> {
pub fn get<F: FnOnce(K) -> 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
}
}

View File

@ -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<i32>) -> 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<i32>) -> Option<Sample3d> {
@ -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<Structure>; 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

View File

@ -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<i32>) -> 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),
);
}
}