mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'mega-worldgen' into 'master'
Proper worldgen See merge request veloren/veloren!146 Former-commit-id: c823999ad7605f5d06907af4f1382acffcd99fa5
This commit is contained in:
commit
ff5d7c7d65
71
Cargo.lock
generated
71
Cargo.lock
generated
@ -173,6 +173,11 @@ name = "bitflags"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "0.8.2"
|
||||
@ -234,6 +239,11 @@ dependencies = [
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cast"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.37"
|
||||
@ -1393,6 +1403,19 @@ name = "memoffset"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "minifb"
|
||||
version = "0.11.2"
|
||||
source = "git+https://github.com/emoon/rust_minifb.git#2b8094cc6ce7fefeb322a8b4df09e0c978efd5e2"
|
||||
dependencies = [
|
||||
"cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"orbclient 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"x11-dl 2.18.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "minimp3"
|
||||
version = "0.3.3"
|
||||
@ -1524,6 +1547,16 @@ name = "nonzero_signed"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "num"
|
||||
version = "0.1.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num"
|
||||
version = "0.2.0"
|
||||
@ -1642,6 +1675,15 @@ dependencies = [
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "orbclient"
|
||||
version = "0.3.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sdl2 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ordered-float"
|
||||
version = "1.0.2"
|
||||
@ -2164,6 +2206,27 @@ name = "scopeguard"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "sdl2"
|
||||
version = "0.31.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sdl2-sys 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sdl2-sys"
|
||||
version = "0.31.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.9.0"
|
||||
@ -2645,6 +2708,7 @@ dependencies = [
|
||||
name = "veloren-world"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"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)",
|
||||
"veloren-common 0.2.0",
|
||||
@ -2867,6 +2931,7 @@ dependencies = [
|
||||
"checksum bincode 1.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9f04a5e50dc80b3d5d35320889053637d15011aed5e66b66b37ae798c65da6f7"
|
||||
"checksum bindgen 0.32.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8b242e11a8f446f5fc7b76b37e81d737cabca562a927bd33766dac55b5f1177f"
|
||||
"checksum bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f67931368edf3a9a51d29886d245f1c3db2f1ef0dcc9e35ff70341b78c10d23"
|
||||
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
|
||||
"checksum bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1370e9fc2a6ae53aea8b7a5110edbd08836ed87c88736dfabccade1c2b44bff4"
|
||||
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
|
||||
"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400"
|
||||
@ -2876,6 +2941,7 @@ dependencies = [
|
||||
"checksum c_vec 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6237ac5a4b1e81c213c24c6437964c61e646df910a914b4ab1487b46df20bd13"
|
||||
"checksum cairo-rs 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0180a8b65dc13e78479c6a47c4d5f094d64dc34465a9433c6daef9ae2fbfb3ee"
|
||||
"checksum cairo-sys-rs 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a2414b86c20c40dfb56a98b1dbca05bde56411f488d268c4289a86df1b648c61"
|
||||
"checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427"
|
||||
"checksum cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "39f75544d7bbaf57560d2168f28fd649ff9c76153874db88bdbdfd839b1a7e7d"
|
||||
"checksum cexpr 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "42aac45e9567d97474a834efdee3081b3c942b2205be932092f53354ce503d6c"
|
||||
"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33"
|
||||
@ -3002,6 +3068,7 @@ dependencies = [
|
||||
"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39"
|
||||
"checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
|
||||
"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
|
||||
"checksum minifb 0.11.2 (git+https://github.com/emoon/rust_minifb.git)" = "<none>"
|
||||
"checksum minimp3 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "542e9bed56860c5070a09939eee0e2df6f8f73f60304ddf56d620947e7017239"
|
||||
"checksum minimp3-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c109ae05c00ad6e3a53fab101e2f234545bdd010f0fffd399355efaf70817817"
|
||||
"checksum mio 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)" = "049ba5ca2b63e837adeee724aa9e36b408ed593529dcc802aa96ca14bd329bdf"
|
||||
@ -3016,6 +3083,7 @@ dependencies = [
|
||||
"checksum nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05aec50c70fd288702bcd93284a8444607f3292dbdf2a30de5ea5dcdbe72287b"
|
||||
"checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6"
|
||||
"checksum nonzero_signed 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "02783a0482333b0d3f5f5411b8fb60454a596696da041da0470ac9ef3e6e37d8"
|
||||
"checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e"
|
||||
"checksum num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf4825417e1e1406b3782a8ce92f4d53f26ec055e3622e1881ca8e9f5f9e08db"
|
||||
"checksum num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "57450397855d951f1a41305e54851b1a7b8f5d2e349543a02a2effe25459f718"
|
||||
"checksum num-complex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "107b9be86cd2481930688277b675b0114578227f034674726605b8a482d8baf8"
|
||||
@ -3030,6 +3098,7 @@ dependencies = [
|
||||
"checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
|
||||
"checksum objc 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "31d20fd2b37e07cf5125be68357b588672e8cefe9a96f8c17a9d46053b3e590d"
|
||||
"checksum ogg 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d79f1db9148be9d0e174bb3ac890f6030fcb1ed947267c5a91ee4c91b5a91e15"
|
||||
"checksum orbclient 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "1d0e398a001ca5f52b252d1cf5679d52ddd347d3130ac9ded98549f16537c546"
|
||||
"checksum ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "18869315e81473c951eb56ad5558bbc56978562d3ecfb87abb7a1e944cea4518"
|
||||
"checksum osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "88cfece6e95d2e717e0872a7f53a8684712ad13822a7979bc760b9c77ec0013b"
|
||||
"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13"
|
||||
@ -3089,6 +3158,8 @@ dependencies = [
|
||||
"checksum scan_fmt 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8b87497427f9fbe539ee6b9626f5a5e899331fdf1c1d62f14c637a462969db30"
|
||||
"checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
|
||||
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
|
||||
"checksum sdl2 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a74c2a98a354b20713b90cce70aef9e927e46110d1bc4ef728fd74e0d53eba60"
|
||||
"checksum sdl2-sys 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5c543ce8a6e33a30cb909612eeeb22e693848211a84558d5a00bb11e791b7ab7"
|
||||
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
||||
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
"checksum serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8"
|
||||
|
@ -73,7 +73,7 @@ impl<'a> System<'a> for Sys {
|
||||
* 50.0
|
||||
* vel.0.map(|e| {
|
||||
(e.abs() * friction * (vel.0.magnitude() * 0.1 + 0.5))
|
||||
.min(e.abs())
|
||||
.min(e.abs() * dt.0 * 50.0)
|
||||
.copysign(e)
|
||||
})
|
||||
* Vec3::new(1.0, 1.0, 0.0);
|
||||
|
@ -9,12 +9,12 @@ use specs::DispatcherBuilder;
|
||||
// System names
|
||||
const AGENT_SYS: &str = "agent_sys";
|
||||
const CONTROL_SYS: &str = "control_sys";
|
||||
const MOVEMENT_SYS: &str = "movement_sys";
|
||||
const PHYS_SYS: &str = "phys_sys";
|
||||
const ANIM_SYS: &str = "anim_sys";
|
||||
|
||||
pub fn add_local_systems(dispatch_builder: &mut DispatcherBuilder) {
|
||||
dispatch_builder.add(agent::Sys, AGENT_SYS, &[]);
|
||||
dispatch_builder.add(control::Sys, CONTROL_SYS, &[]);
|
||||
dispatch_builder.add(phys::Sys, MOVEMENT_SYS, &[]);
|
||||
dispatch_builder.add(phys::Sys, PHYS_SYS, &[]);
|
||||
dispatch_builder.add(control::Sys, CONTROL_SYS, &["phys_sys"]);
|
||||
dispatch_builder.add(anim::Sys, ANIM_SYS, &[]);
|
||||
}
|
||||
|
@ -36,16 +36,16 @@ impl<'a> System<'a> for Sys {
|
||||
}
|
||||
|
||||
// Basic collision with terrain
|
||||
let mut i = 0;
|
||||
let mut i = 0.0;
|
||||
while terrain
|
||||
.get(pos.0.map(|e| e.floor() as i32))
|
||||
.map(|vox| !vox.is_empty())
|
||||
.unwrap_or(false)
|
||||
&& i < 100
|
||||
&& i < 6000.0 * dt.0
|
||||
{
|
||||
pos.0.z += 0.0025;
|
||||
vel.0.z = 0.0;
|
||||
i += 1;
|
||||
i += 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,8 @@ pub enum ChonkError {
|
||||
OutOfBounds,
|
||||
}
|
||||
|
||||
const SUB_CHUNK_HEIGHT: u32 = 16;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Chonk {
|
||||
z_offset: i32,
|
||||
@ -32,8 +34,16 @@ impl Chonk {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_z_min(&self) -> i32 {
|
||||
self.z_offset
|
||||
}
|
||||
|
||||
pub fn get_z_max(&self) -> i32 {
|
||||
self.z_offset + (self.sub_chunks.len() as u32 * SUB_CHUNK_HEIGHT) as i32
|
||||
}
|
||||
|
||||
fn sub_chunk_idx(&self, z: i32) -> usize {
|
||||
((z - self.z_offset) as u32 / TerrainChunkSize::SIZE.z as u32) as usize
|
||||
((z - self.z_offset) as u32 / SUB_CHUNK_HEIGHT as u32) as usize
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,9 +58,7 @@ impl ReadVol for Chonk {
|
||||
if pos.z < self.z_offset {
|
||||
// Below the terrain
|
||||
Ok(&self.below)
|
||||
} else if pos.z
|
||||
>= self.z_offset + TerrainChunkSize::SIZE.z as i32 * self.sub_chunks.len() as i32
|
||||
{
|
||||
} else if pos.z >= self.z_offset + SUB_CHUNK_HEIGHT as i32 * self.sub_chunks.len() as i32 {
|
||||
// Above the terrain
|
||||
Ok(&self.above)
|
||||
} else {
|
||||
@ -64,8 +72,7 @@ impl ReadVol for Chonk {
|
||||
SubChunk::Heterogeneous(chunk) => {
|
||||
let rpos = pos
|
||||
- Vec3::unit_z()
|
||||
* (self.z_offset
|
||||
+ sub_chunk_idx as i32 * TerrainChunkSize::SIZE.z as i32);
|
||||
* (self.z_offset + sub_chunk_idx as i32 * SUB_CHUNK_HEIGHT as i32);
|
||||
chunk.get(rpos).map_err(|err| ChonkError::ChunkError(err))
|
||||
}
|
||||
}
|
||||
@ -86,8 +93,7 @@ impl WriteVol for Chonk {
|
||||
}
|
||||
|
||||
let rpos = pos
|
||||
- Vec3::unit_z()
|
||||
* (self.z_offset + sub_chunk_idx as i32 * TerrainChunkSize::SIZE.z as i32);
|
||||
- Vec3::unit_z() * (self.z_offset + sub_chunk_idx as i32 * SUB_CHUNK_HEIGHT as i32);
|
||||
|
||||
match &mut self.sub_chunks[sub_chunk_idx] {
|
||||
// Can't fail
|
||||
|
@ -23,22 +23,33 @@ use specs::{
|
||||
join::Join, saveload::MarkedBuilder, world::EntityBuilder as EcsEntityBuilder, Builder,
|
||||
Entity as EcsEntity,
|
||||
};
|
||||
use std::{collections::HashSet, i32, net::SocketAddr, sync::mpsc, time::Duration};
|
||||
use std::{
|
||||
collections::HashSet,
|
||||
i32,
|
||||
net::SocketAddr,
|
||||
sync::{mpsc, Arc},
|
||||
time::Duration,
|
||||
};
|
||||
use threadpool::ThreadPool;
|
||||
use vek::*;
|
||||
use world::World;
|
||||
|
||||
const CLIENT_TIMEOUT: f64 = 20.0; // Seconds
|
||||
|
||||
const DEFAULT_WORLD_SEED: u32 = 1337;
|
||||
|
||||
pub enum Event {
|
||||
ClientConnected { entity: EcsEntity },
|
||||
ClientDisconnected { entity: EcsEntity },
|
||||
Chat { entity: EcsEntity, msg: String },
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct SpawnPoint(Vec3<f32>);
|
||||
|
||||
pub struct Server {
|
||||
state: State,
|
||||
world: World,
|
||||
world: Arc<World>,
|
||||
|
||||
postoffice: PostOffice<ServerMsg, ClientMsg>,
|
||||
clients: Clients,
|
||||
@ -63,10 +74,13 @@ impl Server {
|
||||
|
||||
let mut state = State::new();
|
||||
state.ecs_mut().register::<comp::phys::ForceUpdate>();
|
||||
state
|
||||
.ecs_mut()
|
||||
.add_resource(SpawnPoint(Vec3::new(16_384.0, 16_384.0, 150.0)));
|
||||
|
||||
let mut this = Self {
|
||||
state,
|
||||
world: World::new(),
|
||||
world: Arc::new(World::generate(DEFAULT_WORLD_SEED)),
|
||||
|
||||
postoffice: PostOffice::bind(addrs.into())?,
|
||||
clients: Clients::empty(),
|
||||
@ -79,6 +93,7 @@ impl Server {
|
||||
pending_chunks: HashSet::new(),
|
||||
};
|
||||
|
||||
/*
|
||||
for i in 0..4 {
|
||||
this.create_npc(
|
||||
"Tobermory".to_owned(),
|
||||
@ -88,6 +103,7 @@ impl Server {
|
||||
.with(comp::Agent::Wanderer(Vec2::zero()))
|
||||
.build();
|
||||
}
|
||||
*/
|
||||
|
||||
Ok(this)
|
||||
}
|
||||
@ -108,11 +124,6 @@ impl Server {
|
||||
pub fn world(&self) -> &World {
|
||||
&self.world
|
||||
}
|
||||
/// Get a mutable reference to the server's world.
|
||||
#[allow(dead_code)]
|
||||
pub fn world_mut(&mut self) -> &mut World {
|
||||
&mut self.world
|
||||
}
|
||||
|
||||
/// Build a non-player character.
|
||||
#[allow(dead_code)]
|
||||
@ -135,8 +146,10 @@ impl Server {
|
||||
name: String,
|
||||
body: comp::Body,
|
||||
) {
|
||||
let spawn_point = state.ecs().read_resource::<SpawnPoint>().0;
|
||||
|
||||
state.write_component(entity, comp::Actor::Character { name, body });
|
||||
state.write_component(entity, comp::phys::Pos(Vec3::new(0.0, 0.0, 64.0)));
|
||||
state.write_component(entity, comp::phys::Pos(spawn_point));
|
||||
state.write_component(entity, comp::phys::Vel(Vec3::zero()));
|
||||
state.write_component(entity, comp::phys::Dir(Vec3::unit_y()));
|
||||
// Make sure everything is accepted.
|
||||
@ -184,6 +197,9 @@ impl Server {
|
||||
// Tick the client's LocalState (step 3).
|
||||
self.state.tick(dt);
|
||||
|
||||
// Tick the world
|
||||
self.world.tick(dt);
|
||||
|
||||
// Fetch any generated `TerrainChunk`s and insert them into the terrain.
|
||||
// Also, send the chunk data to anybody that is close by.
|
||||
if let Ok((key, chunk)) = self.chunk_rx.try_recv() {
|
||||
@ -569,8 +585,9 @@ impl Server {
|
||||
pub fn generate_chunk(&mut self, key: Vec2<i32>) {
|
||||
if self.pending_chunks.insert(key) {
|
||||
let chunk_tx = self.chunk_tx.clone();
|
||||
let world = self.world.clone();
|
||||
self.thread_pool.execute(move || {
|
||||
let _ = chunk_tx.send((key, World::generate_chunk(key)));
|
||||
let _ = chunk_tx.send((key, world.generate_chunk(key))).unwrap();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -166,7 +166,7 @@ void main() {
|
||||
vec4 fxaa_color = fxaa_apply(src_color, uv * screen_res.xy, screen_res.xy);
|
||||
|
||||
vec4 hsva_color = vec4(rgb2hsv(fxaa_color.rgb), fxaa_color.a);
|
||||
hsva_color.y += 0.17;
|
||||
hsva_color.y += 0.27;
|
||||
hsva_color.x -= 0.015;
|
||||
hsva_color.z = 1.0 - 1.0 / (1.0 * hsva_color.z + 1.0);
|
||||
vec4 final_color = vec4(hsv2rgb(hsva_color.rgb), hsva_color.a);
|
||||
|
@ -51,7 +51,7 @@ image_ids! {
|
||||
// Crosshair
|
||||
crosshair: "voxygen/element/misc_bg/crosshair.vox",
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
<VoxelMs9Graphic>
|
||||
|
||||
// Buttons
|
||||
@ -121,7 +121,7 @@ image_ids! {
|
||||
button_hover: "voxygen/element/buttons/button_hover.vox",
|
||||
button_press: "voxygen/element/buttons/button_press.vox",
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
<ImageGraphic>
|
||||
|
||||
charwindow_gradient:"voxygen/element/misc_bg/charwindow.png",
|
||||
|
@ -1,5 +1,6 @@
|
||||
use client::{error::Error as ClientError, Client};
|
||||
use common::comp;
|
||||
use log::info;
|
||||
use std::{
|
||||
net::ToSocketAddrs,
|
||||
sync::mpsc::{channel, Receiver, TryRecvError},
|
||||
@ -32,6 +33,7 @@ impl ClientInit {
|
||||
thread::spawn(move || {
|
||||
// Sleep the thread to wait for the single-player server to start up.
|
||||
if wait {
|
||||
info!("Waiting for server to come up...");
|
||||
thread::sleep(Duration::from_millis(500));
|
||||
}
|
||||
// Parse ip address or resolves hostname.
|
||||
|
@ -29,7 +29,7 @@ impl PlayState for StartSingleplayerState {
|
||||
let server_address = self.sock.ip().to_string();
|
||||
|
||||
let client_init = ClientInit::new(
|
||||
(server_address.clone(), self.sock.port(), false),
|
||||
(server_address.clone(), self.sock.port(), true),
|
||||
comp::Player::new(username.clone(), Some(10)),
|
||||
true,
|
||||
);
|
||||
|
@ -51,55 +51,25 @@ impl<V: BaseVol<Vox = Block> + ReadVol, S: VolSize + Clone> Meshable for VolMap2
|
||||
fn generate_mesh(&self, range: Self::Supplement) -> Mesh<Self::Pipeline> {
|
||||
let mut mesh = Mesh::new();
|
||||
|
||||
let mut last_chunk_pos = self.pos_key(range.min);
|
||||
let mut last_chunk = self.get_key(last_chunk_pos);
|
||||
|
||||
let size = range.max - range.min;
|
||||
for x in 1..size.x - 1 {
|
||||
for y in 1..size.y - 1 {
|
||||
for z in 0..size.z {
|
||||
for x in range.min.x + 1..range.max.x - 1 {
|
||||
for y in range.min.y + 1..range.max.y - 1 {
|
||||
for z in range.min.z..range.max.z {
|
||||
let pos = Vec3::new(x, y, z);
|
||||
let offs = (pos - range.min * Vec3::new(1, 1, 0)).map(|e| e as f32)
|
||||
- Vec3::new(1.0, 1.0, 0.0);
|
||||
|
||||
let new_chunk_pos = self.pos_key(range.min + pos);
|
||||
if last_chunk_pos != new_chunk_pos {
|
||||
last_chunk = self.get_key(new_chunk_pos);
|
||||
last_chunk_pos = new_chunk_pos;
|
||||
}
|
||||
let offs = pos.map(|e| e as f32) - Vec3::new(1.0, 1.0, 0.0);
|
||||
if let Some(chunk) = last_chunk {
|
||||
let chunk_pos = Self::chunk_offs(range.min + pos);
|
||||
if let Some(col) = chunk.get(chunk_pos).ok().and_then(|vox| vox.get_color())
|
||||
{
|
||||
let col = col.map(|e| e as f32 / 255.0);
|
||||
if let Some(col) = self.get(pos).ok().and_then(|vox| vox.get_color()) {
|
||||
let col = col.map(|e| e as f32 / 255.0);
|
||||
|
||||
vol::push_vox_verts(
|
||||
&mut mesh,
|
||||
self,
|
||||
range.min + pos,
|
||||
offs,
|
||||
col,
|
||||
TerrainVertex::new,
|
||||
false,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if let Some(col) = self
|
||||
.get(range.min + pos)
|
||||
.ok()
|
||||
.and_then(|vox| vox.get_color())
|
||||
{
|
||||
let col = col.map(|e| e as f32 / 255.0);
|
||||
|
||||
vol::push_vox_verts(
|
||||
&mut mesh,
|
||||
self,
|
||||
range.min + pos,
|
||||
offs,
|
||||
col,
|
||||
TerrainVertex::new,
|
||||
false,
|
||||
);
|
||||
}
|
||||
vol::push_vox_verts(
|
||||
&mut mesh,
|
||||
self,
|
||||
pos,
|
||||
offs,
|
||||
col,
|
||||
TerrainVertex::new,
|
||||
false,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -50,22 +50,32 @@ fn create_quad<P: Pipeline, F: Fn(Vec3<f32>, Vec3<f32>, Rgb<f32>) -> P::Vertex>(
|
||||
ao: Vec4<f32>,
|
||||
vcons: &F,
|
||||
) -> Quad<P> {
|
||||
let ao_scale = 1.0;
|
||||
let ao_scale = 0.95;
|
||||
let dark = col * (1.0 - ao_scale);
|
||||
|
||||
let ao_map = ao.map(|e| e.powf(2.0));
|
||||
|
||||
if ao[0] + ao[2] < ao[1] + ao[3] {
|
||||
Quad::new(
|
||||
vcons(origin + unit_y, norm, Rgb::lerp(dark, col, ao[3])),
|
||||
vcons(origin, norm, Rgb::lerp(dark, col, ao[0])),
|
||||
vcons(origin + unit_x, norm, Rgb::lerp(dark, col, ao[1])),
|
||||
vcons(origin + unit_x + unit_y, norm, Rgb::lerp(dark, col, ao[2])),
|
||||
vcons(origin + unit_y, norm, Rgb::lerp(dark, col, ao_map[3])),
|
||||
vcons(origin, norm, Rgb::lerp(dark, col, ao_map[0])),
|
||||
vcons(origin + unit_x, norm, Rgb::lerp(dark, col, ao_map[1])),
|
||||
vcons(
|
||||
origin + unit_x + unit_y,
|
||||
norm,
|
||||
Rgb::lerp(dark, col, ao_map[2]),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
Quad::new(
|
||||
vcons(origin, norm, Rgb::lerp(dark, col, ao[0])),
|
||||
vcons(origin + unit_x, norm, Rgb::lerp(dark, col, ao[1])),
|
||||
vcons(origin + unit_x + unit_y, norm, Rgb::lerp(dark, col, ao[2])),
|
||||
vcons(origin + unit_y, norm, Rgb::lerp(dark, col, ao[3])),
|
||||
vcons(origin, norm, Rgb::lerp(dark, col, ao_map[0])),
|
||||
vcons(origin + unit_x, norm, Rgb::lerp(dark, col, ao_map[1])),
|
||||
vcons(
|
||||
origin + unit_x + unit_y,
|
||||
norm,
|
||||
Rgb::lerp(dark, col, ao_map[2]),
|
||||
),
|
||||
vcons(origin + unit_y, norm, Rgb::lerp(dark, col, ao_map[3])),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ use crate::{
|
||||
};
|
||||
use client::Client;
|
||||
use common::{terrain::TerrainMap, vol::SampleVol, volumes::vol_map_2d::VolMap2dErr};
|
||||
use std::{collections::HashMap, sync::mpsc, time::Duration};
|
||||
use std::{collections::HashMap, i32, sync::mpsc, time::Duration};
|
||||
use vek::*;
|
||||
|
||||
struct TerrainChunk {
|
||||
@ -132,11 +132,6 @@ impl Terrain {
|
||||
.map2(TerrainMap::chunk_size(), |e, sz| (e + 1) * sz as i32 + 1),
|
||||
};
|
||||
|
||||
let aabb = Aabb {
|
||||
min: Vec3::from(aabr.min),
|
||||
max: Vec3::from(aabr.max) + Vec3::unit_z() * 256,
|
||||
};
|
||||
|
||||
// Copy out the chunk data we need to perform the meshing. We do this by taking a
|
||||
// sample of the terrain that includes both the chunk we want and its neighbours.
|
||||
let volume = match client.state().terrain().sample(aabr) {
|
||||
@ -147,6 +142,19 @@ impl Terrain {
|
||||
_ => panic!("Unhandled edge case"),
|
||||
};
|
||||
|
||||
// The region to actually mesh
|
||||
let z_min = volume
|
||||
.iter()
|
||||
.fold(i32::MAX, |min, (_, chunk)| chunk.get_z_min().min(min));
|
||||
let z_max = volume
|
||||
.iter()
|
||||
.fold(i32::MIN, |max, (_, chunk)| chunk.get_z_max().max(max));
|
||||
|
||||
let aabb = Aabb {
|
||||
min: Vec3::from(aabr.min) + Vec3::unit_z() * z_min,
|
||||
max: Vec3::from(aabr.max) + Vec3::unit_z() * z_max,
|
||||
};
|
||||
|
||||
// Clone various things so that they can be moved into the thread.
|
||||
let send = self.mesh_send_tmp.clone();
|
||||
let pos = todo.pos;
|
||||
|
@ -31,9 +31,11 @@ impl Singleplayer {
|
||||
pick_unused_port().expect("Failed to find unused port!"),
|
||||
));
|
||||
|
||||
let sock2 = sock.clone();
|
||||
// Create server
|
||||
let server = Server::bind(sock.clone()).expect("Failed to create server instance!");
|
||||
|
||||
let thread = thread::spawn(move || {
|
||||
run_server(sock2, reciever);
|
||||
run_server(server, reciever);
|
||||
});
|
||||
|
||||
(
|
||||
@ -53,15 +55,12 @@ impl Drop for Singleplayer {
|
||||
}
|
||||
}
|
||||
|
||||
fn run_server(sock: SocketAddr, rec: Receiver<Msg>) {
|
||||
fn run_server(mut server: Server, rec: Receiver<Msg>) {
|
||||
info!("Starting server-cli...");
|
||||
|
||||
// Set up an fps clock
|
||||
let mut clock = Clock::new();
|
||||
|
||||
// Create server
|
||||
let mut server = Server::bind(sock).expect("Failed to create server instance!");
|
||||
|
||||
loop {
|
||||
let events = server
|
||||
.tick(Input::default(), clock.get_last_delta())
|
||||
|
@ -8,3 +8,6 @@ edition = "2018"
|
||||
common = { package = "veloren-common", path = "../common" }
|
||||
vek = "0.9"
|
||||
noise = "0.5"
|
||||
|
||||
[dev-dependencies]
|
||||
minifb = { git = "https://github.com/emoon/rust_minifb.git" }
|
||||
|
56
world/examples/view.rs
Normal file
56
world/examples/view.rs
Normal file
@ -0,0 +1,56 @@
|
||||
use std::ops::{Add, Mul, Sub};
|
||||
use vek::*;
|
||||
use veloren_world::World;
|
||||
|
||||
const W: usize = 640;
|
||||
const H: usize = 480;
|
||||
|
||||
fn main() {
|
||||
let world = World::generate(0);
|
||||
|
||||
let mut win =
|
||||
minifb::Window::new("World Viewer", W, H, minifb::WindowOptions::default()).unwrap();
|
||||
|
||||
let mut focus = Vec2::zero();
|
||||
let mut gain = 1.0;
|
||||
|
||||
while win.is_open() {
|
||||
let mut buf = [0; W * H];
|
||||
|
||||
for i in 0..W {
|
||||
for j in 0..H {
|
||||
let pos = focus + Vec2::new(i as i32, j as i32) * 4;
|
||||
|
||||
let alt = world
|
||||
.sim()
|
||||
.sample(pos)
|
||||
.map(|sample| sample.alt.sub(64.0).add(gain).mul(0.7).max(0.0).min(255.0) as u8)
|
||||
.unwrap_or(0);
|
||||
|
||||
buf[j * W + i] = u32::from_le_bytes([alt; 4]);
|
||||
}
|
||||
}
|
||||
|
||||
let spd = 32;
|
||||
if win.is_key_down(minifb::Key::W) {
|
||||
focus.y -= spd;
|
||||
}
|
||||
if win.is_key_down(minifb::Key::A) {
|
||||
focus.x -= spd;
|
||||
}
|
||||
if win.is_key_down(minifb::Key::S) {
|
||||
focus.y += spd;
|
||||
}
|
||||
if win.is_key_down(minifb::Key::D) {
|
||||
focus.x += spd;
|
||||
}
|
||||
if win.is_key_down(minifb::Key::Q) {
|
||||
gain += 10.0;
|
||||
}
|
||||
if win.is_key_down(minifb::Key::E) {
|
||||
gain -= 10.0;
|
||||
}
|
||||
|
||||
win.update_with_buffer(&buf).unwrap();
|
||||
}
|
||||
}
|
104
world/src/lib.rs
104
world/src/lib.rs
@ -1,26 +1,41 @@
|
||||
// Library
|
||||
use noise::{NoiseFn, Perlin, Seedable};
|
||||
use vek::*;
|
||||
mod sim;
|
||||
|
||||
// Project
|
||||
use common::{
|
||||
terrain::{Block, TerrainChunk, TerrainChunkMeta, TerrainChunkSize},
|
||||
vol::{SizedVol, VolSize, Vox, WriteVol},
|
||||
};
|
||||
use noise::{BasicMulti, MultiFractal, NoiseFn, Perlin, Seedable};
|
||||
use std::{
|
||||
ops::{Add, Div, Mul, Neg, Sub},
|
||||
time::Duration,
|
||||
};
|
||||
use vek::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
Other(String),
|
||||
}
|
||||
|
||||
pub struct World;
|
||||
pub struct World {
|
||||
sim: sim::WorldSim,
|
||||
}
|
||||
|
||||
impl World {
|
||||
pub fn new() -> Self {
|
||||
Self
|
||||
pub fn generate(seed: u32) -> Self {
|
||||
Self {
|
||||
sim: sim::WorldSim::generate(seed),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_chunk(chunk_pos: Vec2<i32>) -> TerrainChunk {
|
||||
pub fn sim(&self) -> &sim::WorldSim {
|
||||
&self.sim
|
||||
}
|
||||
|
||||
pub fn tick(&self, dt: Duration) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
pub fn generate_chunk(&self, chunk_pos: Vec2<i32>) -> TerrainChunk {
|
||||
// TODO: This is all test code, remove/improve this later.
|
||||
|
||||
let air = Block::empty();
|
||||
@ -28,51 +43,62 @@ impl World {
|
||||
let grass = Block::new(2, Rgb::new(75, 150, 0));
|
||||
let dirt = Block::new(3, Rgb::new(128, 90, 0));
|
||||
let sand = Block::new(4, Rgb::new(180, 150, 50));
|
||||
let water = Block::new(5, Rgb::new(100, 150, 255));
|
||||
|
||||
let mut chunk = TerrainChunk::new(0, stone, air, TerrainChunkMeta::void());
|
||||
let warp_nz = BasicMulti::new().set_octaves(3).set_seed(self.sim.seed + 0);
|
||||
|
||||
let perlin_nz = Perlin::new().set_seed(1);
|
||||
let temp_nz = Perlin::new().set_seed(2);
|
||||
let chaos_nz = Perlin::new().set_seed(3);
|
||||
let base_z = match self.sim.get_base_z(chunk_pos.map(|e| e as u32)) {
|
||||
Some(base_z) => base_z as i32,
|
||||
None => return TerrainChunk::new(0, air, air, TerrainChunkMeta::void()),
|
||||
};
|
||||
|
||||
let mut chunk = TerrainChunk::new(base_z, stone, air, TerrainChunkMeta::void());
|
||||
|
||||
for x in 0..TerrainChunkSize::SIZE.x as i32 {
|
||||
for y in 0..TerrainChunkSize::SIZE.y as i32 {
|
||||
for z in 0..256 {
|
||||
let wpos2d = Vec2::new(x, y)
|
||||
+ Vec3::from(chunk_pos) * TerrainChunkSize::SIZE.map(|e| e as i32);
|
||||
let wposf2d = wpos2d.map(|e| e as f64);
|
||||
|
||||
let sim::Sample {
|
||||
alt,
|
||||
chaos,
|
||||
surface_color,
|
||||
} = if let Some(sample) = self.sim.sample(wpos2d) {
|
||||
sample
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let max_z = self
|
||||
.sim
|
||||
.get_interpolated(wpos2d, |chunk| chunk.get_max_z())
|
||||
.unwrap_or(0.0) as i32;
|
||||
|
||||
for z in base_z..max_z {
|
||||
let lpos = Vec3::new(x, y, z);
|
||||
let wpos =
|
||||
lpos + Vec3::from(chunk_pos) * TerrainChunkSize::SIZE.map(|e| e as i32);
|
||||
let wposf = wpos.map(|e| e as f64);
|
||||
|
||||
let chaos_freq = 1.0 / 100.0;
|
||||
let freq = 1.0 / 128.0;
|
||||
let ampl = 75.0;
|
||||
let small_freq = 1.0 / 32.0;
|
||||
let small_ampl = 6.0;
|
||||
let offs = 32.0;
|
||||
let warp = (warp_nz
|
||||
.get((wposf.div(Vec3::new(120.0, 120.0, 150.0))).into_array())
|
||||
as f32)
|
||||
.mul((chaos - 0.1).max(0.0))
|
||||
.mul(90.0);
|
||||
|
||||
let chaos = chaos_nz
|
||||
.get(Vec2::from(wposf * chaos_freq).into_array())
|
||||
.max(0.0)
|
||||
+ 0.5;
|
||||
|
||||
let height =
|
||||
perlin_nz.get(Vec2::from(wposf * freq).into_array()) * ampl * chaos
|
||||
+ perlin_nz.get((wposf * small_freq).into_array())
|
||||
* small_ampl
|
||||
* 3.0
|
||||
* chaos.powf(2.0)
|
||||
+ offs;
|
||||
let temp =
|
||||
(temp_nz.get(Vec2::from(wposf * (1.0 / 64.0)).into_array()) + 1.0) * 0.5;
|
||||
let height = alt + warp;
|
||||
let temp = 0.0;
|
||||
|
||||
let z = wposf.z as f32;
|
||||
let _ = chunk.set(
|
||||
lpos,
|
||||
if wposf.z < height - 4.0 {
|
||||
if z < height - 4.0 {
|
||||
stone
|
||||
} else if wposf.z < height - 2.0 {
|
||||
dirt
|
||||
} else if wposf.z < height {
|
||||
Block::new(2, Rgb::new(10 + (150.0 * temp) as u8, 150, 0))
|
||||
} else if z < height {
|
||||
Block::new(1, surface_color.map(|e| (e * 255.0) as u8))
|
||||
} else if z < sim::SEA_LEVEL {
|
||||
water
|
||||
} else {
|
||||
air
|
||||
},
|
||||
@ -82,5 +108,7 @@ impl World {
|
||||
}
|
||||
|
||||
chunk
|
||||
|
||||
// */
|
||||
}
|
||||
}
|
||||
|
251
world/src/sim.rs
Normal file
251
world/src/sim.rs
Normal file
@ -0,0 +1,251 @@
|
||||
use common::{terrain::TerrainChunkSize, vol::VolSize};
|
||||
use noise::{
|
||||
BasicMulti, HybridMulti, MultiFractal, NoiseFn, OpenSimplex, RidgedMulti, Seedable,
|
||||
SuperSimplex,
|
||||
};
|
||||
use std::{
|
||||
f32,
|
||||
ops::{Add, Div, Mul, Neg, Sub},
|
||||
};
|
||||
use vek::*;
|
||||
|
||||
pub const WORLD_SIZE: Vec2<usize> = Vec2 { x: 1024, y: 1024 };
|
||||
|
||||
pub struct WorldSim {
|
||||
pub seed: u32,
|
||||
chunks: Vec<SimChunk>,
|
||||
gen_ctx: GenCtx,
|
||||
}
|
||||
|
||||
impl WorldSim {
|
||||
pub fn generate(seed: u32) -> Self {
|
||||
let mut gen_ctx = GenCtx {
|
||||
turb_x_nz: BasicMulti::new().set_seed(seed + 0),
|
||||
turb_y_nz: BasicMulti::new().set_seed(seed + 1),
|
||||
chaos_nz: RidgedMulti::new().set_octaves(7).set_seed(seed + 2),
|
||||
hill_nz: SuperSimplex::new().set_seed(seed + 3),
|
||||
alt_nz: HybridMulti::new()
|
||||
.set_octaves(7)
|
||||
.set_persistence(0.1)
|
||||
.set_seed(seed + 4),
|
||||
temp_nz: SuperSimplex::new().set_seed(seed + 5),
|
||||
small_nz: BasicMulti::new().set_octaves(2).set_seed(seed + 6),
|
||||
rock_nz: HybridMulti::new().set_persistence(0.3).set_seed(seed + 7),
|
||||
};
|
||||
|
||||
let mut chunks = Vec::new();
|
||||
for x in 0..WORLD_SIZE.x as u32 {
|
||||
for y in 0..WORLD_SIZE.y as u32 {
|
||||
chunks.push(SimChunk::generate(Vec2::new(x, y), &mut gen_ctx));
|
||||
}
|
||||
}
|
||||
|
||||
Self {
|
||||
seed,
|
||||
chunks,
|
||||
gen_ctx,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self, chunk_pos: Vec2<u32>) -> Option<&SimChunk> {
|
||||
if chunk_pos
|
||||
.map2(WORLD_SIZE, |e, sz| e < sz as u32)
|
||||
.reduce_and()
|
||||
{
|
||||
Some(&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<u32>) -> Option<f32> {
|
||||
self.get(chunk_pos).and_then(|_| {
|
||||
(0..2)
|
||||
.map(|i| (0..2).map(move |j| (i, j)))
|
||||
.flatten()
|
||||
.map(|(i, j)| {
|
||||
self.get(chunk_pos + Vec2::new(i, j))
|
||||
.map(|c| c.get_base_z())
|
||||
})
|
||||
.flatten()
|
||||
.fold(None, |a: Option<f32>, x| a.map(|a| a.min(x)).or(Some(x)))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_interpolated<T, F>(&self, pos: Vec2<i32>, mut f: F) -> Option<T>
|
||||
where
|
||||
T: Copy + Default + Add<Output = T> + Mul<f32, Output = T>,
|
||||
F: FnMut(&SimChunk) -> T,
|
||||
{
|
||||
let pos = pos.map2(TerrainChunkSize::SIZE.into(), |e, sz: u32| {
|
||||
e as f64 / sz as f64
|
||||
});
|
||||
|
||||
let cubic = |a: T, b: T, c: T, d: T, x: f32| -> T {
|
||||
let x2 = x * x;
|
||||
|
||||
// Catmull-Rom splines
|
||||
let co0 = a * -0.5 + b * 1.5 + c * -1.5 + d * 0.5;
|
||||
let co1 = a + b * -2.5 + c * 2.0 + d * -0.5;
|
||||
let co2 = a * -0.5 + c * 0.5;
|
||||
let co3 = b;
|
||||
|
||||
co0 * x2 * x + co1 * x2 + co2 * x + co3
|
||||
};
|
||||
|
||||
let mut y = [T::default(); 4];
|
||||
|
||||
for (y_idx, j) in (-1..3).enumerate() {
|
||||
let x0 =
|
||||
f(self.get(pos.map2(Vec2::new(-1, j), |e, q| (e.max(0.0) as i32 + q) as u32))?);
|
||||
let x1 = f(self.get(pos.map2(Vec2::new(0, j), |e, q| (e.max(0.0) as i32 + q) as u32))?);
|
||||
let x2 = f(self.get(pos.map2(Vec2::new(1, j), |e, q| (e.max(0.0) as i32 + q) as u32))?);
|
||||
let x3 = f(self.get(pos.map2(Vec2::new(2, j), |e, q| (e.max(0.0) as i32 + q) as u32))?);
|
||||
|
||||
y[y_idx] = cubic(x0, x1, x2, x3, pos.x.fract() as f32);
|
||||
}
|
||||
|
||||
Some(cubic(y[0], y[1], y[2], y[3], pos.y.fract() as f32))
|
||||
}
|
||||
|
||||
pub fn sample(&self, pos: Vec2<i32>) -> Option<Sample> {
|
||||
let wposf = pos.map(|e| e as f64);
|
||||
|
||||
/*let wposf = wposf + Vec2::new(
|
||||
self.gen_ctx.turb_x_nz.get((wposf.div(200.0)).into_array()) * 250.0,
|
||||
self.gen_ctx.turb_y_nz.get((wposf.div(200.0)).into_array()) * 250.0,
|
||||
);*/
|
||||
|
||||
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)?;
|
||||
|
||||
let rock = (self.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
|
||||
* chaos.max(0.15)
|
||||
* 32.0
|
||||
+ rock * 15.0;
|
||||
|
||||
// Colours
|
||||
let cold_grass = Rgb::new(0.0, 0.75, 0.25);
|
||||
let warm_grass = Rgb::new(0.55, 0.9, 0.0);
|
||||
let cold_stone = Rgb::new(0.78, 0.86, 1.0);
|
||||
let warm_stone = Rgb::new(0.8, 0.7, 0.55);
|
||||
let sand = Rgb::new(0.93, 0.84, 0.23);
|
||||
|
||||
let grass = Rgb::lerp(cold_grass, warm_grass, temp);
|
||||
let ground = Rgb::lerp(grass, warm_stone, rock.mul(5.0).min(0.8));
|
||||
let cliff = Rgb::lerp(cold_stone, warm_stone, temp);
|
||||
|
||||
Some(Sample {
|
||||
alt,
|
||||
chaos,
|
||||
surface_color: Rgb::lerp(
|
||||
sand,
|
||||
// Land
|
||||
Rgb::lerp(ground, cliff, (alt - SEA_LEVEL - 100.0) / 150.0),
|
||||
// Beach
|
||||
(alt - SEA_LEVEL - 2.0) / 5.0,
|
||||
),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Sample {
|
||||
pub alt: f32,
|
||||
pub chaos: f32,
|
||||
pub surface_color: Rgb<f32>,
|
||||
}
|
||||
|
||||
struct GenCtx {
|
||||
turb_x_nz: BasicMulti,
|
||||
turb_y_nz: BasicMulti,
|
||||
chaos_nz: RidgedMulti,
|
||||
alt_nz: HybridMulti,
|
||||
hill_nz: SuperSimplex,
|
||||
temp_nz: SuperSimplex,
|
||||
small_nz: BasicMulti,
|
||||
rock_nz: HybridMulti,
|
||||
}
|
||||
|
||||
const Z_TOLERANCE: (f32, f32) = (32.0, 64.0);
|
||||
pub const SEA_LEVEL: f32 = 64.0;
|
||||
|
||||
pub struct SimChunk {
|
||||
pub chaos: f32,
|
||||
pub alt: f32,
|
||||
pub temp: f32,
|
||||
pub rockiness: f32,
|
||||
}
|
||||
|
||||
impl SimChunk {
|
||||
fn generate(pos: Vec2<u32>, gen_ctx: &mut GenCtx) -> Self {
|
||||
let wposf = (pos * Vec2::from(TerrainChunkSize::SIZE)).map(|e| e as f64);
|
||||
|
||||
let hill = (gen_ctx.hill_nz.get((wposf.div(3500.0)).into_array()) as f32).max(0.0);
|
||||
|
||||
let chaos = (gen_ctx.chaos_nz.get((wposf.div(3500.0)).into_array()) as f32)
|
||||
.add(1.0)
|
||||
.mul(0.5)
|
||||
.powf(1.9)
|
||||
.add(0.25 * hill);
|
||||
|
||||
let chaos = chaos + chaos.mul(20.0).sin().mul(0.05);
|
||||
|
||||
let alt_base = gen_ctx.alt_nz.get((wposf.div(5000.0)).into_array()) as f32 * 0.4;
|
||||
|
||||
let alt_main = gen_ctx.alt_nz.get((wposf.div(750.0)).into_array()) as f32;
|
||||
|
||||
Self {
|
||||
chaos,
|
||||
alt: SEA_LEVEL
|
||||
+ (0.0
|
||||
+ alt_main
|
||||
+ gen_ctx.small_nz.get((wposf.div(300.0)).into_array()) as f32
|
||||
* alt_main.max(0.05)
|
||||
* chaos
|
||||
* 1.3)
|
||||
.add(1.0)
|
||||
.mul(0.5)
|
||||
.mul(chaos)
|
||||
.add(alt_base)
|
||||
.mul(750.0),
|
||||
temp: (gen_ctx.temp_nz.get((wposf.div(48.0)).into_array()) as f32)
|
||||
.add(1.0)
|
||||
.mul(0.5),
|
||||
rockiness: (gen_ctx.rock_nz.get((wposf.div(1024.0)).into_array()) as f32)
|
||||
.sub(0.1)
|
||||
.mul(1.2)
|
||||
.max(0.0),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_base_z(&self) -> f32 {
|
||||
self.alt - Z_TOLERANCE.0
|
||||
}
|
||||
|
||||
pub fn get_max_z(&self) -> f32 {
|
||||
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!()
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user