Adjusted tree colour variation

This commit is contained in:
Joshua Barretto 2019-06-15 11:36:26 +01:00
parent 30b668d0cc
commit a9d30bbfb6
18 changed files with 225 additions and 152 deletions

View File

@ -12,19 +12,15 @@ use common::{
msg::{ClientMsg, ClientState, ServerInfo, ServerMsg},
net::PostBox,
state::State,
terrain::{
TerrainChunk,
TerrainChunkSize,
chonk::ChonkMetrics,
},
terrain::{chonk::ChonkMetrics, TerrainChunk, TerrainChunkSize},
vol::VolSize,
};
use log::{debug, info, log_enabled};
use std::{
collections::HashMap,
net::SocketAddr,
time::{Duration, Instant},
sync::Arc,
time::{Duration, Instant},
};
use threadpool::ThreadPool;
use vek::*;
@ -155,11 +151,16 @@ impl Client {
}
pub fn current_chunk(&self) -> Option<Arc<TerrainChunk>> {
let chunk_pos = Vec2::from(self
.state
.read_storage::<comp::phys::Pos>()
.get(self.entity)
.cloned()?.0).map2(Vec2::from(TerrainChunkSize::SIZE), |e: f32, sz| (e as u32).div_euclid(sz) as i32);
let chunk_pos = Vec2::from(
self.state
.read_storage::<comp::phys::Pos>()
.get(self.entity)
.cloned()?
.0,
)
.map2(Vec2::from(TerrainChunkSize::SIZE), |e: f32, sz| {
(e as u32).div_euclid(sz) as i32
});
self.state.terrain().get_key_arc(chunk_pos).cloned()
}

View File

@ -267,9 +267,9 @@ impl<S: PostMsg, R: PostMsg> PostBox<S, R> {
for _ in 0..100 {
match incoming_buf.get(0..9) {
Some(len_bytes) => {
let len = u64::from_le_bytes(
<[u8; 8]>::try_from(&len_bytes[0..8]).unwrap(),
) as usize; // Can't fail
let len =
u64::from_le_bytes(<[u8; 8]>::try_from(&len_bytes[0..8]).unwrap())
as usize; // Can't fail
if len > MAX_MSG_SIZE {
recv_tx.send(Err(Error::InvalidMessage)).unwrap();

View File

@ -33,10 +33,7 @@ pub struct TerrainChunkMeta {
impl TerrainChunkMeta {
pub fn new(name: Option<String>, biome: BiomeKind) -> Self {
Self {
name,
biome,
}
Self { name, biome }
}
pub fn void() -> Self {

View File

@ -83,14 +83,17 @@ impl Asset for Structure {
1 => StructureBlock::PineLeaves,
2 => StructureBlock::PalmLeaves,
index => {
let color = palette.get(index as usize).copied().unwrap_or(Rgb::broadcast(0));
let color = palette
.get(index as usize)
.copied()
.unwrap_or(Rgb::broadcast(0));
StructureBlock::Block(Block::new(1, color))
}
};
let _ = vol.set(
Vec3::new(voxel.x, voxel.y, voxel.z).map(|e| e as i32),
block
block,
);
}

View File

@ -32,7 +32,7 @@ void main() {
float sun_ambience = 0.8;
vec3 sun_dir = normalize(vec3(1.3, 1.7, 2.1));
vec3 sun_dir = normalize(vec3(0.7, 1.3, 2.1));
float sun_diffuse = dot(sun_dir, f_norm);
float sun_light = sun_ambience + sun_diffuse;

View File

@ -117,7 +117,8 @@ impl Scene {
// Alter camera position to match player.
let tilt = self.camera.get_orientation().y;
let dist = self.camera.get_distance();
self.camera.set_focus_pos(player_pos + Vec3::unit_z() * (2.1 - tilt.min(0.0) * dist * 0.75));
self.camera
.set_focus_pos(player_pos + Vec3::unit_z() * (2.1 - tilt.min(0.0) * dist * 0.75));
// Tick camera for interpolation.
self.camera.update(client.state().get_time());

View File

@ -72,7 +72,7 @@ impl SessionState {
// TODO: Get rid of this
match self.client.borrow().current_chunk() {
Some(chunk) => println!("Chunk location: {:?}", chunk.meta().name()),
None => {},
None => {}
}
Ok(())

View File

@ -1,18 +1,17 @@
mod tree;
use std::ops::{Add, Div, Mul, Neg, Sub};
use noise::NoiseFn;
use vek::*;
use common::{
terrain::{Block, structure::StructureBlock},
vol::{Vox, ReadVol},
};
use crate::{
util::{Sampler, HashCache},
column::{ColumnGen, ColumnSample},
CONFIG,
World,
util::{HashCache, RandomField, Sampler, SamplerMut},
World, CONFIG,
};
use common::{
terrain::{structure::StructureBlock, Block},
vol::{ReadVol, Vox},
};
use noise::NoiseFn;
use std::ops::{Add, Div, Mul, Neg, Sub};
use vek::*;
pub struct BlockGen<'a> {
world: &'a World,
@ -37,7 +36,7 @@ impl<'a> BlockGen<'a> {
}
}
impl<'a> Sampler for BlockGen<'a> {
impl<'a> SamplerMut for BlockGen<'a> {
type Index = Vec3<i32>;
type Sample = Option<Block>;
@ -60,7 +59,9 @@ impl<'a> Sampler for BlockGen<'a> {
// Apply warping
let warp = (self.world.sim()
let warp = (self
.world
.sim()
.gen_ctx
.warp_nz
.get((wposf.div(Vec3::new(150.0, 150.0, 150.0))).into_array())
@ -69,29 +70,37 @@ impl<'a> Sampler for BlockGen<'a> {
.mul(115.0);
let is_cliff = if cliff > 0.0 {
(self.world.sim()
.gen_ctx
.warp_nz
.get((wposf.div(Vec3::new(300.0, 300.0, 1500.0))).into_array())
as f32) * cliff > 0.3
(self
.world
.sim()
.gen_ctx
.warp_nz
.get((wposf.div(Vec3::new(300.0, 300.0, 1500.0))).into_array()) as f32)
* cliff
> 0.3
} else {
false
};
let cliff = if is_cliff {
(0.0
+ (self.world.sim()
(0.0 + (self
.world
.sim()
.gen_ctx
.warp_nz
.get((wposf.div(Vec3::new(350.0, 350.0, 800.0))).into_array())
as f32) * 0.8
+ (self.world.sim()
.gen_ctx
.warp_nz
.get((wposf.div(Vec3::new(100.0, 100.0, 70.0))).into_array())
as f32) * 0.3)
.add(0.4)
.mul(64.0)
as f32)
* 0.8
+ (self
.world
.sim()
.gen_ctx
.warp_nz
.get((wposf.div(Vec3::new(100.0, 100.0, 70.0))).into_array())
as f32)
* 0.3)
.add(0.4)
.mul(75.0)
} else {
0.0
};
@ -162,24 +171,43 @@ impl<'a> Sampler for BlockGen<'a> {
}
});
fn block_from_structure(sblock: StructureBlock, structure_pos: Vec2<i32>, sample: &ColumnSample) -> Block {
let temp_lerp = sample.temp * 4.0;
fn block_from_structure(
sblock: StructureBlock,
pos: Vec3<i32>,
structure_pos: Vec2<i32>,
structure_seed: u32,
sample: &ColumnSample,
) -> Block {
let field = RandomField::new(structure_seed + 0);
let lerp = 0.5
+ ((field.get(Vec3::from(structure_pos)) % 256) as f32 / 256.0 - 0.5) * 0.75
+ ((field.get(Vec3::from(pos)) % 256) as f32 / 256.0 - 0.5) * 0.2;
match sblock {
StructureBlock::TemperateLeaves => Block::new(1, Lerp::lerp(
Rgb::new(0.0, 150.0, 50.0),
Rgb::new(200.0, 255.0, 0.0),
temp_lerp,
).map(|e| e as u8)),
StructureBlock::PineLeaves => Block::new(1, Lerp::lerp(
Rgb::new(0.0, 100.0, 90.0),
Rgb::new(50.0, 150.0, 50.0),
temp_lerp,
).map(|e| e as u8)),
StructureBlock::PalmLeaves => Block::new(1, Lerp::lerp(
Rgb::new(80.0, 150.0, 0.0),
Rgb::new(180.0, 255.0, 0.0),
temp_lerp,
).map(|e| e as u8)),
StructureBlock::TemperateLeaves => Block::new(
1,
Lerp::lerp(
Rgb::new(0.0, 80.0, 40.0),
Rgb::new(120.0, 255.0, 10.0),
lerp,
)
.map(|e| e as u8),
),
StructureBlock::PineLeaves => Block::new(
1,
Lerp::lerp(Rgb::new(0.0, 60.0, 50.0), Rgb::new(30.0, 100.0, 10.0), lerp)
.map(|e| e as u8),
),
StructureBlock::PalmLeaves => Block::new(
1,
Lerp::lerp(
Rgb::new(30.0, 100.0, 30.0),
Rgb::new(120.0, 255.0, 0.0),
lerp,
)
.map(|e| e as u8),
),
StructureBlock::Block(block) => block,
}
}
@ -202,7 +230,15 @@ impl<'a> Sampler for BlockGen<'a> {
block.or(trees[*tree_seed as usize % trees.len()]
.get((rpos * 128) / 128) // Scaling
.map(|b| block_from_structure(*b, *tree_pos, &tree_sample))
.map(|b| {
block_from_structure(
*b,
rpos,
*tree_pos,
*tree_seed,
&tree_sample,
)
})
.unwrap_or(Block::empty()))
}
_ => block,

View File

@ -1,8 +1,8 @@
use crate::all::ForestKind;
use common::{assets, terrain::Structure};
use lazy_static::lazy_static;
use std::sync::Arc;
use vek::*;
use crate::all::ForestKind;
pub fn kinds(forest_kind: ForestKind) -> &'static [Arc<Structure>] {
match forest_kind {

View File

@ -1,16 +1,11 @@
use std::ops::{Add, Div, Mul, Neg, Sub};
use vek::*;
use noise::NoiseFn;
use crate::{all::ForestKind, util::Sampler, World, CONFIG};
use common::{
terrain::{Block, TerrainChunkSize},
vol::{Vox, VolSize},
};
use crate::{
CONFIG,
all::ForestKind,
util::Sampler,
World,
vol::{VolSize, Vox},
};
use noise::NoiseFn;
use std::ops::{Add, Div, Mul, Neg, Sub};
use vek::*;
pub struct ColumnGen<'a> {
world: &'a World,
@ -18,9 +13,7 @@ pub struct ColumnGen<'a> {
impl<'a> ColumnGen<'a> {
pub fn new(world: &'a World) -> Self {
Self {
world,
}
Self { world }
}
}
@ -28,9 +21,11 @@ impl<'a> Sampler for ColumnGen<'a> {
type Index = Vec2<i32>;
type Sample = Option<ColumnSample>;
fn get(&mut self, wpos: Vec2<i32>) -> Option<ColumnSample> {
fn get(&self, wpos: Vec2<i32>) -> Option<ColumnSample> {
let wposf = wpos.map(|e| e as f64);
let chunk_pos = wpos.map2(Vec2::from(TerrainChunkSize::SIZE), |e, sz: u32| e as u32 / sz);
let chunk_pos = wpos.map2(Vec2::from(TerrainChunkSize::SIZE), |e, sz: u32| {
e as u32 / sz
});
let sim = self.world.sim();
@ -48,7 +43,11 @@ impl<'a> Sampler for ColumnGen<'a> {
* chaos.max(0.2)
* 64.0;
let rock = (sim.gen_ctx.small_nz.get(Vec3::new(wposf.x, wposf.y, alt as f64).div(100.0).into_array()) as f32)
let rock = (sim.gen_ctx.small_nz.get(
Vec3::new(wposf.x, wposf.y, alt as f64)
.div(100.0)
.into_array(),
) as f32)
.mul(rockiness)
.sub(0.4)
.max(0.0)
@ -59,8 +58,8 @@ impl<'a> Sampler for ColumnGen<'a> {
let marble = (0.0
+ (sim.gen_ctx.hill_nz.get((wposf3d.div(48.0)).into_array()) as f32).mul(0.75)
+ (sim.gen_ctx.hill_nz.get((wposf3d.div(3.0)).into_array()) as f32).mul(0.25))
.add(1.0)
.mul(0.5);
.add(1.0)
.mul(0.5);
// Colours
let cold_grass = Rgb::new(0.0, 0.3, 0.1);
@ -79,7 +78,9 @@ impl<'a> Sampler for ColumnGen<'a> {
Rgb::lerp(
snow,
grass,
temp.sub(CONFIG.snow_temp).sub((marble - 0.5) * 0.05).mul(256.0),
temp.sub(CONFIG.snow_temp)
.sub((marble - 0.5) * 0.05)
.mul(256.0),
),
sand,
temp.sub(CONFIG.desert_temp).mul(32.0),

View File

@ -1,26 +1,26 @@
#![feature(euclidean_division, bind_by_move_pattern_guards)]
mod config;
mod all;
mod util;
mod block;
mod column;
mod config;
mod sim;
mod util;
// Reexports
pub use crate::config::CONFIG;
use crate::{
block::BlockGen,
column::ColumnGen,
util::{HashCache, Sampler, SamplerMut},
};
use common::{
terrain::{Block, TerrainChunk, TerrainChunkMeta, TerrainChunkSize},
vol::{VolSize, Vox, WriteVol},
};
use std::time::Duration;
use vek::*;
use crate::{
util::{Sampler, HashCache},
column::ColumnGen,
block::BlockGen,
};
#[derive(Debug)]
pub enum Error {
@ -46,7 +46,7 @@ impl World {
// TODO
}
pub fn sample(&self) -> impl Sampler<Index=Vec3<i32>, Sample=Option<Block>> + '_ {
pub fn sample(&self) -> impl SamplerMut<Index = Vec3<i32>, Sample = Option<Block>> + '_ {
BlockGen::new(self, ColumnGen::new(self))
}

View File

@ -21,20 +21,17 @@ pub struct Kingdom {
fn generate_name() -> String {
let consts = [
"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", "qu", "s", "sh", "z", "k",
"br", "wh", "tr", "h", "bl", "sl", "r", "kl", "sl",
"w", "v", "vr", "kr",
"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",
"qu", "s", "sh", "z", "k", "br", "wh", "tr", "h", "bl", "sl", "r", "kl", "sl", "w", "v",
"vr", "kr",
];
let vowels = [
"oo", "o", "oa", "au", "e", "ee", "ea", "ou", "u", "a", "i", "ie",
];
let vowels = ["oo", "o", "oa", "au", "e", "ee", "ea", "ou", "u", "a", "i", "ie"];
let tails = [
"er", "in", "o", "on", "an",
"ar", "is", "oon", "er", "aru",
"ab", "um", "id", "and", "eld",
"ald", "oft", "aft", "ift", "ity",
"ell", "oll", "ill", "all",
"er", "in", "o", "on", "an", "ar", "is", "oon", "er", "aru", "ab", "um", "id", "and",
"eld", "ald", "oft", "aft", "ift", "ity", "ell", "oll", "ill", "all",
];
let mut name = String::new();

View File

@ -1,24 +1,14 @@
mod location;
use self::location::Location;
use crate::{all::ForestKind, util::StructureGen2d, CONFIG};
use common::{terrain::TerrainChunkSize, vol::VolSize};
use noise::{BasicMulti, HybridMulti, MultiFractal, NoiseFn, RidgedMulti, Seedable, SuperSimplex};
use std::{
ops::{Add, Div, Mul, Neg, Sub},
sync::Arc,
};
use vek::*;
use noise::{
BasicMulti, RidgedMulti, SuperSimplex, HybridMulti,
MultiFractal, NoiseFn, Seedable,
};
use common::{
terrain::TerrainChunkSize,
vol::VolSize,
};
use crate::{
CONFIG,
all::ForestKind,
util::StructureGen2d,
};
use self::location::Location;
pub const WORLD_SIZE: Vec2<usize> = Vec2 { x: 1024, y: 1024 };
@ -240,7 +230,11 @@ impl SimChunk {
.mul(0.5)
.mul(1.2 - chaos * 0.85)
.add(0.1)
.mul(if alt > CONFIG.sea_level + 2.0 { 1.0 } else { 0.0 }),
.mul(if alt > CONFIG.sea_level + 5.0 {
1.0
} else {
0.0
}),
forest_kind: if temp > 0.0 {
if temp > CONFIG.desert_temp {
ForestKind::Palm

View File

@ -1,5 +1,5 @@
use std::hash::Hash;
use fxhash::FxHashMap;
use std::hash::Hash;
pub struct HashCache<K: Hash + Eq + Clone, V> {
capacity: usize,

View File

@ -1,10 +1,12 @@
pub mod sampler;
pub mod hash_cache;
pub mod random;
pub mod sampler;
pub mod structure;
// Reexports
pub use self::{
sampler::Sampler,
hash_cache::HashCache,
random::RandomField,
sampler::{Sampler, SamplerMut},
structure::StructureGen2d,
};

41
world/src/util/random.rs Normal file
View File

@ -0,0 +1,41 @@
use super::Sampler;
use vek::*;
pub struct RandomField {
seed: u32,
}
impl RandomField {
pub fn new(seed: u32) -> Self {
Self { seed }
}
}
impl Sampler for RandomField {
type Index = Vec3<i32>;
type Sample = u32;
fn get(&self, pos: Self::Index) -> Self::Sample {
let pos = pos.map(|e| (e * 13 + (1 << 31)) as u32);
let next = self.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(318912) ^ 0x23341753;
let next = next
.rotate_left(13)
.wrapping_mul(938219)
.wrapping_add(pos.z);
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
}
}

View File

@ -2,5 +2,12 @@ pub trait Sampler: Sized {
type Index;
type Sample;
fn get(&self, index: Self::Index) -> Self::Sample;
}
pub trait SamplerMut: Sized {
type Index;
type Sample;
fn get(&mut self, index: Self::Index) -> Self::Sample;
}

View File

@ -1,38 +1,31 @@
use super::{RandomField, Sampler};
use vek::*;
pub struct StructureGen2d {
seed: u32,
freq: u32,
spread: u32,
x_field: RandomField,
y_field: RandomField,
seed_field: RandomField,
}
impl StructureGen2d {
pub fn new(seed: u32, freq: u32, spread: u32) -> Self {
Self { seed, freq, spread }
Self {
freq,
spread,
x_field: RandomField::new(seed + 0),
y_field: RandomField::new(seed + 1),
seed_field: RandomField::new(seed + 2),
}
}
}
fn random(&self, seed: u32, pos: Vec2<i32>) -> u32 {
let pos = pos.map(|e| (e * 13 + (1 << 31)) as u32);
impl Sampler for StructureGen2d {
type Index = Vec2<i32>;
type Sample = [(Vec2<i32>, u32); 9];
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
}
pub fn get(&self, sample_pos: Vec2<i32>) -> [(Vec2<i32>, u32); 9] {
fn get(&self, sample_pos: Self::Index) -> Self::Sample {
let mut samples = [(Vec2::zero(), 0); 9];
let sample_closest = sample_pos.map(|e| e - e.rem_euclid(self.freq as i32));
@ -45,12 +38,12 @@ impl StructureGen2d {
samples[i * 3 + j] = (
center
+ Vec2::new(
(self.random(1, center) % (self.spread * 2)) as i32
(self.x_field.get(Vec3::from(center)) % (self.spread * 2)) as i32
- self.spread as i32,
(self.random(2, center) % (self.spread * 2)) as i32
(self.y_field.get(Vec3::from(center)) % (self.spread * 2)) as i32
- self.spread as i32,
),
self.random(3, center),
self.seed_field.get(Vec3::from(center)),
);
}
}