mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Basic region generation
This commit is contained in:
parent
aa28f0b427
commit
451bbe9921
@ -41,7 +41,7 @@ fn get_ao_quad<V: ReadVol>(vol: &V, pos: Vec3<i32>, shift: Vec3<i32>, dirs: &[Ve
|
|||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
// Map both 1 and 2 neighbors to 0.5 occlusion.
|
// Map both 1 and 2 neighbors to 0.5 occlusion.
|
||||||
if s1 || s2 || corner {
|
if s1 || s2 || corner {
|
||||||
0.5
|
0.3
|
||||||
} else {
|
} else {
|
||||||
1.0
|
1.0
|
||||||
}
|
}
|
||||||
|
@ -58,12 +58,10 @@ impl SessionState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Get rid of this when we're done with it (we're not yet)
|
// TODO: Get rid of this when we're done with it (we're not yet)
|
||||||
/*
|
|
||||||
match self.client.borrow().current_chunk() {
|
match self.client.borrow().current_chunk() {
|
||||||
Some(chunk) => println!("Chunk location: {:?}", chunk.meta().name()),
|
Some(chunk) => println!("Chunk location: {:?}", chunk.meta().name()),
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -15,35 +15,44 @@ fn main() {
|
|||||||
|
|
||||||
let mut focus = Vec2::zero();
|
let mut focus = Vec2::zero();
|
||||||
let mut gain = 1.0;
|
let mut gain = 1.0;
|
||||||
|
let mut scale = 4;
|
||||||
|
|
||||||
while win.is_open() {
|
while win.is_open() {
|
||||||
let mut buf = vec![0; W * H];
|
let mut buf = vec![0; W * H];
|
||||||
|
|
||||||
for i in 0..W {
|
for i in 0..W {
|
||||||
for j in 0..H {
|
for j in 0..H {
|
||||||
let pos = focus + Vec2::new(i as i32, j as i32) * 4;
|
let pos = focus + Vec2::new(i as i32, j as i32) * scale;
|
||||||
|
|
||||||
let alt = sampler
|
let (alt, location) = sampler
|
||||||
.get(pos)
|
.get(pos)
|
||||||
.map(|sample| sample.alt.sub(64.0).add(gain).mul(0.7).max(0.0).min(255.0) as u8)
|
.map(|sample| (
|
||||||
.unwrap_or(0);
|
sample.alt.sub(64.0).add(gain).mul(0.7).max(0.0).min(255.0) as u8,
|
||||||
|
sample.location,
|
||||||
|
))
|
||||||
|
.unwrap_or((0, None));
|
||||||
|
|
||||||
buf[j * W + i] = u32::from_le_bytes([alt; 4]);
|
let loc_color = location.map(|l| (
|
||||||
|
l.name().bytes().nth(0).unwrap() * 17,
|
||||||
|
l.name().bytes().nth(1).unwrap() * 17,
|
||||||
|
)).unwrap_or((0, 0));
|
||||||
|
|
||||||
|
buf[j * W + i] = u32::from_le_bytes([loc_color.0, loc_color.1, alt, alt]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let spd = 32;
|
let spd = 32;
|
||||||
if win.is_key_down(minifb::Key::W) {
|
if win.is_key_down(minifb::Key::W) {
|
||||||
focus.y -= spd;
|
focus.y -= spd * scale;
|
||||||
}
|
}
|
||||||
if win.is_key_down(minifb::Key::A) {
|
if win.is_key_down(minifb::Key::A) {
|
||||||
focus.x -= spd;
|
focus.x -= spd * scale;
|
||||||
}
|
}
|
||||||
if win.is_key_down(minifb::Key::S) {
|
if win.is_key_down(minifb::Key::S) {
|
||||||
focus.y += spd;
|
focus.y += spd * scale;
|
||||||
}
|
}
|
||||||
if win.is_key_down(minifb::Key::D) {
|
if win.is_key_down(minifb::Key::D) {
|
||||||
focus.x += spd;
|
focus.x += spd * scale;
|
||||||
}
|
}
|
||||||
if win.is_key_down(minifb::Key::Q) {
|
if win.is_key_down(minifb::Key::Q) {
|
||||||
gain += 10.0;
|
gain += 10.0;
|
||||||
@ -51,6 +60,12 @@ fn main() {
|
|||||||
if win.is_key_down(minifb::Key::E) {
|
if win.is_key_down(minifb::Key::E) {
|
||||||
gain -= 10.0;
|
gain -= 10.0;
|
||||||
}
|
}
|
||||||
|
if win.is_key_down(minifb::Key::R) {
|
||||||
|
scale += 1;
|
||||||
|
}
|
||||||
|
if win.is_key_down(minifb::Key::F) {
|
||||||
|
scale -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
win.update_with_buffer(&buf).unwrap();
|
win.update_with_buffer(&buf).unwrap();
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ use vek::*;
|
|||||||
|
|
||||||
pub struct BlockGen<'a> {
|
pub struct BlockGen<'a> {
|
||||||
world: &'a World,
|
world: &'a World,
|
||||||
column_cache: HashCache<Vec2<i32>, Option<ColumnSample>>,
|
column_cache: HashCache<Vec2<i32>, Option<ColumnSample<'a>>>,
|
||||||
column_gen: ColumnGen<'a>,
|
column_gen: ColumnGen<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,6 +53,7 @@ impl<'a> SamplerMut for BlockGen<'a> {
|
|||||||
rock,
|
rock,
|
||||||
cliff,
|
cliff,
|
||||||
temp,
|
temp,
|
||||||
|
..
|
||||||
} = self.sample_column(Vec2::from(wpos))?;
|
} = self.sample_column(Vec2::from(wpos))?;
|
||||||
|
|
||||||
let wposf = wpos.map(|e| e as f64);
|
let wposf = wpos.map(|e| e as f64);
|
||||||
|
@ -1,10 +1,19 @@
|
|||||||
use crate::{all::ForestKind, util::Sampler, World, CONFIG};
|
use crate::{
|
||||||
|
all::ForestKind,
|
||||||
|
util::Sampler,
|
||||||
|
sim::Location,
|
||||||
|
World,
|
||||||
|
CONFIG,
|
||||||
|
};
|
||||||
use common::{
|
use common::{
|
||||||
terrain::{Block, TerrainChunkSize},
|
terrain::{Block, TerrainChunkSize},
|
||||||
vol::{VolSize, Vox},
|
vol::{VolSize, Vox},
|
||||||
};
|
};
|
||||||
use noise::NoiseFn;
|
use noise::NoiseFn;
|
||||||
use std::ops::{Add, Div, Mul, Neg, Sub};
|
use std::{
|
||||||
|
ops::{Add, Div, Mul, Neg, Sub},
|
||||||
|
sync::Arc,
|
||||||
|
};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
pub struct ColumnGen<'a> {
|
pub struct ColumnGen<'a> {
|
||||||
@ -19,12 +28,12 @@ impl<'a> ColumnGen<'a> {
|
|||||||
|
|
||||||
impl<'a> Sampler for ColumnGen<'a> {
|
impl<'a> Sampler for ColumnGen<'a> {
|
||||||
type Index = Vec2<i32>;
|
type Index = Vec2<i32>;
|
||||||
type Sample = Option<ColumnSample>;
|
type Sample = Option<ColumnSample<'a>>;
|
||||||
|
|
||||||
fn get(&self, wpos: Vec2<i32>) -> Option<ColumnSample> {
|
fn get(&self, wpos: Vec2<i32>) -> Option<ColumnSample<'a>> {
|
||||||
let wposf = wpos.map(|e| e as f64);
|
let wposf = wpos.map(|e| e as f64);
|
||||||
let chunk_pos = wpos.map2(Vec2::from(TerrainChunkSize::SIZE), |e, sz: u32| {
|
let chunk_pos = wpos.map2(Vec2::from(TerrainChunkSize::SIZE), |e, sz: u32| {
|
||||||
e as u32 / sz
|
e / sz as i32
|
||||||
});
|
});
|
||||||
|
|
||||||
let sim = self.world.sim();
|
let sim = self.world.sim();
|
||||||
@ -36,7 +45,7 @@ impl<'a> Sampler for ColumnGen<'a> {
|
|||||||
let cliffiness = sim.get_interpolated(wpos, |chunk| chunk.cliffiness)?;
|
let cliffiness = sim.get_interpolated(wpos, |chunk| chunk.cliffiness)?;
|
||||||
let tree_density = sim.get_interpolated(wpos, |chunk| chunk.tree_density)?;
|
let tree_density = sim.get_interpolated(wpos, |chunk| chunk.tree_density)?;
|
||||||
|
|
||||||
let forest_kind = sim.get(chunk_pos)?.forest_kind;
|
let sim_chunk = sim.get(chunk_pos)?;
|
||||||
|
|
||||||
let alt = sim.get_interpolated(wpos, |chunk| chunk.alt)?
|
let alt = sim.get_interpolated(wpos, |chunk| chunk.alt)?
|
||||||
+ (sim.gen_ctx.small_nz.get((wposf.div(256.0)).into_array()) as f32)
|
+ (sim.gen_ctx.small_nz.get((wposf.div(256.0)).into_array()) as f32)
|
||||||
@ -140,19 +149,20 @@ impl<'a> Sampler for ColumnGen<'a> {
|
|||||||
(alt - CONFIG.sea_level - 2.0) / 5.0,
|
(alt - CONFIG.sea_level - 2.0) / 5.0,
|
||||||
),
|
),
|
||||||
tree_density,
|
tree_density,
|
||||||
forest_kind,
|
forest_kind: sim_chunk.forest_kind,
|
||||||
close_trees: sim.gen_ctx.tree_gen.get(wpos),
|
close_trees: sim.gen_ctx.tree_gen.get(wpos),
|
||||||
cave_xy,
|
cave_xy,
|
||||||
cave_alt,
|
cave_alt,
|
||||||
rock,
|
rock,
|
||||||
cliff: cliffiness,
|
cliff: cliffiness,
|
||||||
temp,
|
temp,
|
||||||
|
location: sim_chunk.location.as_ref(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ColumnSample {
|
pub struct ColumnSample<'a> {
|
||||||
pub alt: f32,
|
pub alt: f32,
|
||||||
pub chaos: f32,
|
pub chaos: f32,
|
||||||
pub surface_color: Rgb<f32>,
|
pub surface_color: Rgb<f32>,
|
||||||
@ -164,4 +174,5 @@ pub struct ColumnSample {
|
|||||||
pub rock: f32,
|
pub rock: f32,
|
||||||
pub cliff: f32,
|
pub cliff: f32,
|
||||||
pub temp: f32,
|
pub temp: f32,
|
||||||
|
pub location: Option<&'a Arc<Location>>
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ mod all;
|
|||||||
mod block;
|
mod block;
|
||||||
mod column;
|
mod column;
|
||||||
pub mod config;
|
pub mod config;
|
||||||
mod sim;
|
pub mod sim;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
|
||||||
// Reexports
|
// Reexports
|
||||||
@ -62,15 +62,20 @@ impl World {
|
|||||||
let water = Block::new(5, Rgb::new(100, 150, 255));
|
let water = Block::new(5, Rgb::new(100, 150, 255));
|
||||||
|
|
||||||
let chunk_size2d = Vec2::from(TerrainChunkSize::SIZE);
|
let chunk_size2d = Vec2::from(TerrainChunkSize::SIZE);
|
||||||
let base_z = match self.sim.get_interpolated(
|
let (base_z, sim_chunk) = match self.sim.get_interpolated(
|
||||||
chunk_pos.map2(chunk_size2d, |e, sz: u32| e * sz as i32 + sz as i32 / 2),
|
chunk_pos.map2(chunk_size2d, |e, sz: u32| e * sz as i32 + sz as i32 / 2),
|
||||||
|chunk| chunk.get_base_z(),
|
|chunk| chunk.get_base_z(),
|
||||||
) {
|
).and_then(|base_z| self.sim.get(chunk_pos).map(|sim_chunk| (base_z, sim_chunk))) {
|
||||||
Some(base_z) => base_z as i32,
|
Some((base_z, sim_chunk)) => (base_z as i32, sim_chunk),
|
||||||
None => return TerrainChunk::new(0, water, air, TerrainChunkMeta::void()),
|
None => return TerrainChunk::new(0, water, air, TerrainChunkMeta::void()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut chunk = TerrainChunk::new(base_z - 8, stone, air, TerrainChunkMeta::void());
|
let meta = TerrainChunkMeta::new(
|
||||||
|
sim_chunk.get_name(),
|
||||||
|
sim_chunk.get_biome(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut chunk = TerrainChunk::new(base_z - 8, stone, air, meta);
|
||||||
|
|
||||||
let mut sampler = self.sample_blocks();
|
let mut sampler = self.sample_blocks();
|
||||||
|
|
||||||
|
@ -1,17 +1,37 @@
|
|||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
use vek::*;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub enum LocationKind {
|
pub enum LocationKind {
|
||||||
Settlement,
|
Settlement,
|
||||||
Mountain,
|
Wildnerness,
|
||||||
Forest,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Location {
|
pub struct Location {
|
||||||
name: String,
|
name: String,
|
||||||
|
center: Vec2<i32>,
|
||||||
kind: LocationKind,
|
kind: LocationKind,
|
||||||
kingdom: Kingdom,
|
kingdom: Option<Kingdom>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Location {
|
||||||
|
pub fn generate<R: Rng>(center: Vec2<i32>, rng: &mut R) -> Self {
|
||||||
|
Self {
|
||||||
|
name: generate_name(rng),
|
||||||
|
center,
|
||||||
|
kind: LocationKind::Wildnerness,
|
||||||
|
kingdom: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn name(&self) -> &str {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn kingdom(&self) -> Option<&Kingdom> {
|
||||||
|
self.kingdom.as_ref()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -19,7 +39,7 @@ pub struct Kingdom {
|
|||||||
name: String,
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_name() -> String {
|
fn generate_name<R: Rng>(rng: &mut R) -> String {
|
||||||
let consts = [
|
let consts = [
|
||||||
"st", "tr", "b", "n", "p", "ph", "cr", "g", "c", "d", "k", "kr", "kl", "gh", "sl", "st",
|
"st", "tr", "b", "n", "p", "ph", "cr", "g", "c", "d", "k", "kr", "kl", "gh", "sl", "st",
|
||||||
"cr", "sp", "th", "dr", "pr", "dr", "gr", "br", "ryth", "rh", "sl", "f", "fr", "p", "pr",
|
"cr", "sp", "th", "dr", "pr", "dr", "gr", "br", "ryth", "rh", "sl", "f", "fr", "p", "pr",
|
||||||
|
@ -1,14 +1,24 @@
|
|||||||
mod location;
|
mod location;
|
||||||
|
|
||||||
use self::location::Location;
|
// Reexports
|
||||||
|
pub use self::location::Location;
|
||||||
|
|
||||||
use crate::{all::ForestKind, util::StructureGen2d, CONFIG};
|
use crate::{all::ForestKind, util::StructureGen2d, CONFIG};
|
||||||
use common::{terrain::TerrainChunkSize, vol::VolSize};
|
use common::{
|
||||||
|
terrain::{BiomeKind, TerrainChunkSize},
|
||||||
|
vol::VolSize,
|
||||||
|
};
|
||||||
use noise::{BasicMulti, HybridMulti, MultiFractal, NoiseFn, RidgedMulti, Seedable, SuperSimplex};
|
use noise::{BasicMulti, HybridMulti, MultiFractal, NoiseFn, RidgedMulti, Seedable, SuperSimplex};
|
||||||
use std::{
|
use std::{
|
||||||
ops::{Add, Div, Mul, Neg, Sub},
|
ops::{Add, Div, Mul, Neg, Sub},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
use rand::{
|
||||||
|
Rng,
|
||||||
|
SeedableRng,
|
||||||
|
prng::XorShiftRng,
|
||||||
|
};
|
||||||
|
|
||||||
pub const WORLD_SIZE: Vec2<usize> = Vec2 { x: 1024, y: 1024 };
|
pub const WORLD_SIZE: Vec2<usize> = Vec2 { x: 1024, y: 1024 };
|
||||||
|
|
||||||
@ -35,6 +45,7 @@ pub struct WorldSim {
|
|||||||
pub seed: u32,
|
pub seed: u32,
|
||||||
pub(crate) chunks: Vec<SimChunk>,
|
pub(crate) chunks: Vec<SimChunk>,
|
||||||
pub(crate) gen_ctx: GenCtx,
|
pub(crate) gen_ctx: GenCtx,
|
||||||
|
pub rng: XorShiftRng,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WorldSim {
|
impl WorldSim {
|
||||||
@ -64,8 +75,8 @@ impl WorldSim {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut chunks = Vec::new();
|
let mut chunks = Vec::new();
|
||||||
for x in 0..WORLD_SIZE.x as u32 {
|
for x in 0..WORLD_SIZE.x as i32 {
|
||||||
for y in 0..WORLD_SIZE.y as u32 {
|
for y in 0..WORLD_SIZE.y as i32 {
|
||||||
chunks.push(SimChunk::generate(Vec2::new(x, y), &mut gen_ctx));
|
chunks.push(SimChunk::generate(Vec2::new(x, y), &mut gen_ctx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -74,20 +85,70 @@ impl WorldSim {
|
|||||||
seed,
|
seed,
|
||||||
chunks,
|
chunks,
|
||||||
gen_ctx,
|
gen_ctx,
|
||||||
|
rng: XorShiftRng::from_seed([
|
||||||
|
(seed >> 0) as u8, 0, 0, 0,
|
||||||
|
(seed >> 8) as u8, 0, 0, 0,
|
||||||
|
(seed >> 16) as u8, 0, 0, 0,
|
||||||
|
(seed >> 24) as u8, 0, 0, 0,
|
||||||
|
]),
|
||||||
};
|
};
|
||||||
|
|
||||||
this.simulate(100);
|
this.seed_elements();
|
||||||
|
this.simulate(200);
|
||||||
|
|
||||||
this
|
this
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn simulate(&mut self, cycles: usize) {
|
/// Prepare the world for simulation
|
||||||
// TODO
|
pub fn seed_elements(&mut self) {
|
||||||
|
let mut rng = self.rng.clone();
|
||||||
|
|
||||||
|
for _ in 0..250 {
|
||||||
|
let loc_center = Vec2::new(
|
||||||
|
self.rng.gen::<i32>() % WORLD_SIZE.x as i32,
|
||||||
|
self.rng.gen::<i32>() % WORLD_SIZE.y as i32,
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Some(chunk) = self.get_mut(loc_center) {
|
||||||
|
chunk.location = Some(Location::generate(loc_center, &mut rng).into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.rng = rng;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&self, chunk_pos: Vec2<u32>) -> Option<&SimChunk> {
|
pub fn simulate(&mut self, cycles: usize) {
|
||||||
|
let mut rng = self.rng.clone();
|
||||||
|
|
||||||
|
for _ in 0..cycles {
|
||||||
|
for i in 0..WORLD_SIZE.x as i32 {
|
||||||
|
for j in 0..WORLD_SIZE.y as i32 {
|
||||||
|
let pos = Vec2::new(i, j);
|
||||||
|
|
||||||
|
let location = self.get(pos).unwrap().location.clone();
|
||||||
|
|
||||||
|
let rpos = Vec2::new(
|
||||||
|
rng.gen::<i32>(),
|
||||||
|
rng.gen::<i32>(),
|
||||||
|
).map(|e| e.abs() % 3 - 1);
|
||||||
|
|
||||||
|
if let Some(other) = &mut self.get_mut(pos + rpos) {
|
||||||
|
if other.location.is_none()
|
||||||
|
&& rng.gen::<f32>() > other.chaos * 1.5
|
||||||
|
&& other.alt > CONFIG.sea_level {
|
||||||
|
other.location = location;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.rng = rng;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(&self, chunk_pos: Vec2<i32>) -> Option<&SimChunk> {
|
||||||
if chunk_pos
|
if chunk_pos
|
||||||
.map2(WORLD_SIZE, |e, sz| e < sz as u32)
|
.map2(WORLD_SIZE, |e, sz| e >= 0 && e < sz as i32)
|
||||||
.reduce_and()
|
.reduce_and()
|
||||||
{
|
{
|
||||||
Some(&self.chunks[chunk_pos.y as usize * WORLD_SIZE.x + chunk_pos.x as usize])
|
Some(&self.chunks[chunk_pos.y as usize * WORLD_SIZE.x + chunk_pos.x as usize])
|
||||||
@ -96,7 +157,18 @@ impl WorldSim {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_base_z(&self, chunk_pos: Vec2<u32>) -> Option<f32> {
|
pub fn get_mut(&mut self, chunk_pos: Vec2<i32>) -> Option<&mut SimChunk> {
|
||||||
|
if chunk_pos
|
||||||
|
.map2(WORLD_SIZE, |e, sz| e >= 0 && e < sz as i32)
|
||||||
|
.reduce_and()
|
||||||
|
{
|
||||||
|
Some(&mut self.chunks[chunk_pos.y as usize * WORLD_SIZE.x + chunk_pos.x as usize])
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_base_z(&self, chunk_pos: Vec2<i32>) -> Option<f32> {
|
||||||
self.get(chunk_pos).and_then(|_| {
|
self.get(chunk_pos).and_then(|_| {
|
||||||
(0..2)
|
(0..2)
|
||||||
.map(|i| (0..2).map(move |j| (i, j)))
|
.map(|i| (0..2).map(move |j| (i, j)))
|
||||||
@ -135,10 +207,10 @@ impl WorldSim {
|
|||||||
|
|
||||||
for (x_idx, j) in (-1..3).enumerate() {
|
for (x_idx, j) in (-1..3).enumerate() {
|
||||||
let y0 =
|
let y0 =
|
||||||
f(self.get(pos.map2(Vec2::new(j, -1), |e, q| (e.max(0.0) as i32 + q) as u32))?);
|
f(self.get(pos.map2(Vec2::new(j, -1), |e, q| e.max(0.0) as i32 + q))?);
|
||||||
let y1 = f(self.get(pos.map2(Vec2::new(j, 0), |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))?);
|
||||||
let y2 = f(self.get(pos.map2(Vec2::new(j, 1), |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))?);
|
||||||
let y3 = f(self.get(pos.map2(Vec2::new(j, 2), |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))?);
|
||||||
|
|
||||||
x[x_idx] = cubic(y0, y1, y2, y3, pos.y.fract() as f32);
|
x[x_idx] = cubic(y0, y1, y2, y3, pos.y.fract() as f32);
|
||||||
}
|
}
|
||||||
@ -162,8 +234,8 @@ pub struct SimChunk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SimChunk {
|
impl SimChunk {
|
||||||
fn generate(pos: Vec2<u32>, gen_ctx: &mut GenCtx) -> Self {
|
fn generate(pos: Vec2<i32>, gen_ctx: &mut GenCtx) -> Self {
|
||||||
let wposf = (pos * Vec2::from(TerrainChunkSize::SIZE)).map(|e| e as f64);
|
let wposf = (pos * TerrainChunkSize::SIZE.map(|e| e as i32)).map(|e| e as f64);
|
||||||
|
|
||||||
let hill = (0.0
|
let hill = (0.0
|
||||||
+ gen_ctx
|
+ gen_ctx
|
||||||
@ -180,6 +252,7 @@ impl SimChunk {
|
|||||||
let chaos = (gen_ctx.chaos_nz.get((wposf.div(4_000.0)).into_array()) as f32)
|
let chaos = (gen_ctx.chaos_nz.get((wposf.div(4_000.0)).into_array()) as f32)
|
||||||
.add(1.0)
|
.add(1.0)
|
||||||
.mul(0.5)
|
.mul(0.5)
|
||||||
|
.mul((gen_ctx.chaos_nz.get((wposf.div(8_000.0)).into_array()) as f32).powf(2.0).add(0.5).min(1.0))
|
||||||
.powf(1.4)
|
.powf(1.4)
|
||||||
.add(0.1 * hill);
|
.add(0.1 * hill);
|
||||||
|
|
||||||
@ -263,4 +336,26 @@ impl SimChunk {
|
|||||||
pub fn get_max_z(&self) -> f32 {
|
pub fn get_max_z(&self) -> f32 {
|
||||||
(self.alt + Z_TOLERANCE.1).max(CONFIG.sea_level + 1.0)
|
(self.alt + Z_TOLERANCE.1).max(CONFIG.sea_level + 1.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_name(&self) -> Option<String> {
|
||||||
|
self.location
|
||||||
|
.as_ref()
|
||||||
|
.map(|l| l.name().to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_biome(&self) -> BiomeKind {
|
||||||
|
if self.alt < CONFIG.sea_level {
|
||||||
|
BiomeKind::Ocean
|
||||||
|
} else if self.chaos > 0.6 {
|
||||||
|
BiomeKind::Mountain
|
||||||
|
} else if self.temp > CONFIG.desert_temp {
|
||||||
|
BiomeKind::Desert
|
||||||
|
} else if self.temp < CONFIG.snow_temp {
|
||||||
|
BiomeKind::Snowlands
|
||||||
|
} else if self.tree_density > 0.65 {
|
||||||
|
BiomeKind::Forest
|
||||||
|
} else {
|
||||||
|
BiomeKind::Grassland
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user