Added basic structure generation

Former-commit-id: 88a6bf2e18ac4f8f9b560797c8aac82ca318afb0
This commit is contained in:
Joshua Barretto 2019-05-23 21:41:01 +01:00
parent 79ae6f10e7
commit 857315a27d
5 changed files with 120 additions and 31 deletions

7
Cargo.lock generated
View File

@ -1129,6 +1129,11 @@ dependencies = [
"svg_fmt 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "hashbrown"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "hibitset"
version = "0.5.4"
@ -2707,6 +2712,7 @@ dependencies = [
name = "veloren-world"
version = "0.2.0"
dependencies = [
"hashbrown 0.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)",
@ -3030,6 +3036,7 @@ dependencies = [
"checksum gtk 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d695d6be4110618a97c19cd068e8a00e53e33b87e3c65cdc5397667498b1bc24"
"checksum gtk-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d9554cf5b3a85a13fb39258c65b04b262989c1d7a758f8f555b77a478621a91"
"checksum guillotiere 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "182af928b4435d8fbef910535586ecdca95ab4068493769c090e6573477f5e35"
"checksum hashbrown 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "570178d5e4952010d138b0f1d581271ff3a02406d990f887d1e87e3d6e43b0ac"
"checksum hibitset 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6527bc88f32e0d3926c7572874b2bf17a19b36978aacd0aacf75f7d27a5992d0"
"checksum hound 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a164bb2ceaeff4f42542bdb847c41517c78a60f5649671b2a07312b6e117549"
"checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114"

View File

@ -8,6 +8,7 @@ edition = "2018"
common = { package = "veloren-common", path = "../common" }
vek = "0.9"
noise = "0.5"
hashbrown = "0.3.0"
[dev-dependencies]
minifb = { git = "https://github.com/emoon/rust_minifb.git" }

View File

@ -1,4 +1,7 @@
#![feature(euclidean_division)]
mod sim;
mod structure;
use common::{
terrain::{Block, TerrainChunk, TerrainChunkMeta, TerrainChunkSize},
@ -6,6 +9,7 @@ use common::{
};
use noise::{BasicMulti, MultiFractal, NoiseFn, Perlin, Seedable};
use std::{
hash::Hash,
ops::{Add, Div, Mul, Neg, Sub},
time::Duration,
};
@ -64,7 +68,8 @@ impl World {
alt,
chaos,
surface_color,
} = if let Some(sample) = self.sim.sample(wpos2d) {
close_trees,
} = if let Some(sample) = self.sim.sampler().sample(wpos2d) {
sample
} else {
continue;
@ -90,6 +95,15 @@ impl World {
let height = alt + warp;
let temp = 0.0;
let above_ground = if (&close_trees)
.iter()
.any(|tree| tree.distance_squared(wpos.into()) < 36)
{
grass
} else {
air
};
let z = wposf.z as f32;
let _ = chunk.set(
lpos,
@ -100,7 +114,7 @@ impl World {
} else if z < sim::SEA_LEVEL {
water
} else {
air
above_ground
},
);
}
@ -108,7 +122,23 @@ impl World {
}
chunk
// */
}
}
struct Cache<K: Hash + Eq + Copy, V> {
map: hashbrown::HashMap<K, V>,
}
impl<K: Hash + Eq + Copy, V> Cache<K, V> {
pub fn new() -> Self {
Self {
map: hashbrown::HashMap::new(),
}
}
pub fn get<F: FnOnce(K) -> V>(&mut self, k: K, f: F) -> &V {
self.map
.entry(k)
.or_insert_with(|| f(k))
}
}

View File

@ -1,3 +1,7 @@
use crate::{
structure::StructureGen2d,
Cache,
};
use common::{terrain::TerrainChunkSize, vol::VolSize};
use noise::{
BasicMulti, HybridMulti, MultiFractal, NoiseFn, OpenSimplex, RidgedMulti, Seedable,
@ -15,6 +19,7 @@ pub struct WorldSim {
pub seed: u32,
chunks: Vec<SimChunk>,
gen_ctx: GenCtx,
tree_gen: StructureGen2d,
}
impl WorldSim {
@ -44,6 +49,7 @@ impl WorldSim {
seed,
chunks,
gen_ctx,
tree_gen: StructureGen2d::new(seed, 64, 32),
}
}
@ -107,29 +113,41 @@ impl WorldSim {
Some(cubic(x[0], x[1], x[2], x[3], pos.x.fract() as f32))
}
pub fn sample(&self, pos: Vec2<i32>) -> Option<Sample> {
let wposf = pos.map(|e| e as f64);
pub fn sampler(&self) -> Sampler {
Sampler {
sim: self,
}
}
}
let alt_base = self.get_interpolated(pos, |chunk| chunk.alt_base)?;
let chaos = self.get_interpolated(pos, |chunk| chunk.chaos)?;
let temp = self.get_interpolated(pos, |chunk| chunk.temp)?;
let rockiness = self.get_interpolated(pos, |chunk| chunk.rockiness)?;
pub struct Sampler<'a> {
sim: &'a WorldSim,
}
let rock = (self.gen_ctx.small_nz.get((wposf.div(100.0)).into_array()) as f32)
impl<'a> Sampler<'a> {
pub fn sample(&self, wpos: Vec2<i32>) -> Option<Sample> {
let wposf = wpos.map(|e| e as f64);
let alt_base = self.sim.get_interpolated(wpos, |chunk| chunk.alt_base)?;
let chaos = self.sim.get_interpolated(wpos, |chunk| chunk.chaos)?;
let temp = self.sim.get_interpolated(wpos, |chunk| chunk.temp)?;
let rockiness = self.sim.get_interpolated(wpos, |chunk| chunk.rockiness)?;
let rock = (self.sim.gen_ctx.small_nz.get((wposf.div(100.0)).into_array()) as f32)
.mul(rockiness)
.sub(0.2)
.max(0.0)
.mul(2.0);
let alt = self.get_interpolated(pos, |chunk| chunk.alt)?
+ self.gen_ctx.small_nz.get((wposf.div(128.0)).into_array()) as f32
let alt = self.sim.get_interpolated(wpos, |chunk| chunk.alt)?
+ self.sim.gen_ctx.small_nz.get((wposf.div(128.0)).into_array()) as f32
* chaos.max(0.15)
* 32.0
+ rock * 15.0;
let wposf3d = Vec3::new(wposf.x, wposf.y, alt as f64);
let marble = (self.gen_ctx.hill_nz.get((wposf3d.div(64.0)).into_array()) as f32)
let marble = (self.sim.gen_ctx.hill_nz.get((wposf3d.div(64.0)).into_array()) as f32)
.mul(0.5)
.add(1.0).mul(0.5);
@ -164,6 +182,7 @@ impl WorldSim {
// Beach
(alt - SEA_LEVEL - 2.0) / 5.0,
),
close_trees: self.sim.tree_gen.sample(wpos),
})
}
}
@ -172,6 +191,7 @@ pub struct Sample {
pub alt: f32,
pub chaos: f32,
pub surface_color: Rgb<f32>,
pub close_trees: [Vec2<i32>; 9],
}
struct GenCtx {
@ -250,18 +270,3 @@ impl SimChunk {
self.alt + Z_TOLERANCE.1
}
}
trait Hsv {
fn into_hsv(self) -> Self;
fn into_rgb(self) -> Self;
}
impl Hsv for Rgb<f32> {
fn into_hsv(mut self) -> Self {
unimplemented!()
}
fn into_rgb(mut self) -> Self {
unimplemented!()
}
}

View File

@ -1,4 +1,50 @@
pub struct StructureGen {
freq: f32,
use vek::*;
pub struct StructureGen2d {
seed: u32,
freq: u32,
spread: u32,
}
impl StructureGen2d {
pub fn new(seed: u32, freq: u32, spread: u32) -> Self {
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 = 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(313322) ^ 0xDEADBEEF;
let next = next.rotate_left(13).wrapping_mul(929009) ^ 0xFF329DE3;
let next = next.rotate_left(13).wrapping_mul(422671) ^ 0x42892942;
next & 0xFFFF
}
pub fn sample(&self, sample_pos: Vec2<i32>) -> [Vec2<i32>; 9] {
let mut samples = [Vec2::zero(); 9];
let sample_closest = sample_pos.map(|e| e - e.rem_euclid(self.freq as i32));
for i in 0..3 {
for j in 0..3 {
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,
);
}
}
samples
}
}