From cdb57e3831f451742e3b13e1baf931d646ec2c07 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Fri, 17 May 2019 22:19:32 +0100 Subject: [PATCH 01/15] Added mega worldgen Former-commit-id: f7c88a1d387c282b78ab834dd63e64432b371552 --- common/src/terrain/chonk.rs | 8 ++++++ voxygen/src/mesh/terrain.rs | 53 +++++------------------------------- voxygen/src/scene/terrain.rs | 20 ++++++++++---- world/src/lib.rs | 23 +++++++++++----- 4 files changed, 45 insertions(+), 59 deletions(-) diff --git a/common/src/terrain/chonk.rs b/common/src/terrain/chonk.rs index 9d812957e8..245aa09ab3 100644 --- a/common/src/terrain/chonk.rs +++ b/common/src/terrain/chonk.rs @@ -32,6 +32,14 @@ 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 * TerrainChunkSize::SIZE.z) as i32 + } + fn sub_chunk_idx(&self, z: i32) -> usize { ((z - self.z_offset) as u32 / TerrainChunkSize::SIZE.z as u32) as usize } diff --git a/voxygen/src/mesh/terrain.rs b/voxygen/src/mesh/terrain.rs index f250f86926..8e2e341dbe 100644 --- a/voxygen/src/mesh/terrain.rs +++ b/voxygen/src/mesh/terrain.rs @@ -51,55 +51,16 @@ impl + ReadVol, S: VolSize + Clone> Meshable for VolMap2 fn generate_mesh(&self, range: Self::Supplement) -> Mesh { 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); } } } diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index ea23ecf77a..0bf56fc129 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -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, sync::mpsc, time::Duration, i32}; 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; diff --git a/world/src/lib.rs b/world/src/lib.rs index ca03b18be6..c4239c80cd 100644 --- a/world/src/lib.rs +++ b/world/src/lib.rs @@ -29,18 +29,26 @@ impl World { let dirt = Block::new(3, Rgb::new(128, 90, 0)); let sand = Block::new(4, Rgb::new(180, 150, 50)); - let mut chunk = TerrainChunk::new(0, stone, air, TerrainChunkMeta::void()); - + let offset_nz = Perlin::new().set_seed(3); 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 get_offset = |pos: Vec2| { + ((offset_nz.get(pos.map(|e| e as f64 / 4000.0).into_array()) + 1.0) + * 1000.0) as i32 + }; + + let offset_z = get_offset(chunk_pos * Vec2::from(TerrainChunkSize::SIZE).map(|e: u32| e as i32)); + + let mut chunk = TerrainChunk::new(offset_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 { + for z in offset_z..offset_z + 256 { let lpos = Vec3::new(x, y, z); - let wpos = - lpos + Vec3::from(chunk_pos) * TerrainChunkSize::SIZE.map(|e| e as i32); + 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; @@ -48,7 +56,7 @@ impl World { let ampl = 75.0; let small_freq = 1.0 / 32.0; let small_ampl = 6.0; - let offs = 32.0; + let offs = 128.0; let chaos = chaos_nz .get(Vec2::from(wposf * chaos_freq).into_array()) @@ -61,7 +69,8 @@ impl World { * small_ampl * 3.0 * chaos.powf(2.0) - + offs; + + offs + + get_offset(Vec2::from(wpos)) as f64; let temp = (temp_nz.get(Vec2::from(wposf * (1.0 / 64.0)).into_array()) + 1.0) * 0.5; From 12788fb3388402152b027d2541acafd1a433cd2e Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Fri, 17 May 2019 23:42:44 +0100 Subject: [PATCH 02/15] Attempted fix of deltatime bug Former-commit-id: d287bbf541dd318a7034f1e3ad4d9a167ac3c344 --- common/src/sys/phys.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/src/sys/phys.rs b/common/src/sys/phys.rs index 9793cf073b..99a8ce8db4 100644 --- a/common/src/sys/phys.rs +++ b/common/src/sys/phys.rs @@ -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; } } } From 5cadcac30a942aac6cb003539881de49646d2092 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sat, 18 May 2019 00:50:14 +0100 Subject: [PATCH 03/15] Less noisy worldgen Former-commit-id: f1df6cc5b170db4949e88f11d26b9867056caacd --- world/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/world/src/lib.rs b/world/src/lib.rs index c4239c80cd..5c9493c359 100644 --- a/world/src/lib.rs +++ b/world/src/lib.rs @@ -36,16 +36,16 @@ impl World { let get_offset = |pos: Vec2| { ((offset_nz.get(pos.map(|e| e as f64 / 4000.0).into_array()) + 1.0) - * 1000.0) as i32 + * 1000.0) }; let offset_z = get_offset(chunk_pos * Vec2::from(TerrainChunkSize::SIZE).map(|e: u32| e as i32)); - let mut chunk = TerrainChunk::new(offset_z, stone, air, TerrainChunkMeta::void()); + let mut chunk = TerrainChunk::new(offset_z as i32, 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 offset_z..offset_z + 256 { + for z in offset_z as i32..offset_z as i32 + 256 { let lpos = Vec3::new(x, y, z); let wpos = lpos + Vec3::from(chunk_pos) * TerrainChunkSize::SIZE.map(|e| e as i32); From 7a2461b5a84c8abba97b0137661283061bfb5c88 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sat, 18 May 2019 09:59:58 +0100 Subject: [PATCH 04/15] Added worldsim API, ticking Former-commit-id: 50a63e44557c634f2b39ef7a580cdbeec5ed0d70 --- server/src/lib.rs | 7 ++++++- world/src/lib.rs | 20 ++++++++++++++------ world/src/sim.rs | 44 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 7 deletions(-) create mode 100644 world/src/sim.rs diff --git a/server/src/lib.rs b/server/src/lib.rs index e1e94d1e86..411b371670 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -30,6 +30,8 @@ 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 }, @@ -66,7 +68,7 @@ impl Server { let mut this = Self { state, - world: World::new(), + world: World::generate(DEFAULT_WORLD_SEED), postoffice: PostOffice::bind(addrs.into())?, clients: Clients::empty(), @@ -184,6 +186,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() { diff --git a/world/src/lib.rs b/world/src/lib.rs index 5c9493c359..8291e696e4 100644 --- a/world/src/lib.rs +++ b/world/src/lib.rs @@ -1,8 +1,8 @@ -// Library +mod sim; + +use std::time::Duration; use noise::{NoiseFn, Perlin, Seedable}; use vek::*; - -// Project use common::{ terrain::{Block, TerrainChunk, TerrainChunkMeta, TerrainChunkSize}, vol::{SizedVol, VolSize, Vox, WriteVol}, @@ -13,11 +13,19 @@ pub enum Error { Other(String), } -pub struct World; +pub const WORLD_SIZE: Vec2 = Vec2 { x: 1024, y: 1024 }; + +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 tick(&mut self, dt: Duration) { + // TODO } pub fn generate_chunk(chunk_pos: Vec2) -> TerrainChunk { diff --git a/world/src/sim.rs b/world/src/sim.rs new file mode 100644 index 0000000000..a93dfe746e --- /dev/null +++ b/world/src/sim.rs @@ -0,0 +1,44 @@ +use noise::{NoiseFn, OpenSimplex, Seedable}; +use crate::WORLD_SIZE; + +pub struct WorldSim { + seed: u32, + chunks: Vec, +} + +impl WorldSim { + pub fn generate(seed: u32) -> Self { + let mut gen_ctx = GenCtx { + alt_nz: OpenSimplex::new() + .set_seed(seed), + }; + + let mut chunks = Vec::new(); + for x in 0..WORLD_SIZE.x { + for y in 0..WORLD_SIZE.y { + chunks.push(SimChunk::generate(&mut gen_ctx)); + } + } + + Self { + seed, + chunks, + } + } +} + +struct GenCtx { + alt_nz: OpenSimplex, +} + +struct SimChunk { + alt: f32, +} + +impl SimChunk { + pub fn generate(gen_ctx: &mut GenCtx) -> Self { + Self { + alt: 0.0 + } + } +} From 220aa123189c6129e446de243e318eba86c08159 Mon Sep 17 00:00:00 2001 From: Pfauenauge90 <44173739+Pfauenauge90@users.noreply.github.com> Date: Thu, 16 May 2019 19:40:32 +0200 Subject: [PATCH 05/15] Basic worldgen Former-commit-id: 3ca0afa95dd1d868a84a41129e889a203e8a7cd9 --- common/src/sys/control.rs | 2 +- common/src/sys/mod.rs | 6 +++--- server/src/lib.rs | 14 +++++--------- voxygen/src/hud/img_ids.rs | 4 ++-- world/src/lib.rs | 10 +++++++--- world/src/sim.rs | 32 +++++++++++++++++++++++++------- 6 files changed, 43 insertions(+), 25 deletions(-) diff --git a/common/src/sys/control.rs b/common/src/sys/control.rs index 37610a8795..0fa60fe0d0 100644 --- a/common/src/sys/control.rs +++ b/common/src/sys/control.rs @@ -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); diff --git a/common/src/sys/mod.rs b/common/src/sys/mod.rs index 18ece5816e..85427a1e59 100644 --- a/common/src/sys/mod.rs +++ b/common/src/sys/mod.rs @@ -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, &[]); } diff --git a/server/src/lib.rs b/server/src/lib.rs index 411b371670..bf7c8de701 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -23,7 +23,7 @@ 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::{Arc, mpsc}, time::Duration}; use threadpool::ThreadPool; use vek::*; use world::World; @@ -40,7 +40,7 @@ pub enum Event { pub struct Server { state: State, - world: World, + world: Arc, postoffice: PostOffice, clients: Clients, @@ -68,7 +68,7 @@ impl Server { let mut this = Self { state, - world: World::generate(DEFAULT_WORLD_SEED), + world: Arc::new(World::generate(DEFAULT_WORLD_SEED)), postoffice: PostOffice::bind(addrs.into())?, clients: Clients::empty(), @@ -110,11 +110,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)] @@ -574,8 +569,9 @@ impl Server { pub fn generate_chunk(&mut self, key: Vec2) { 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() }); } } diff --git a/voxygen/src/hud/img_ids.rs b/voxygen/src/hud/img_ids.rs index d514b4e1af..33a8462944 100644 --- a/voxygen/src/hud/img_ids.rs +++ b/voxygen/src/hud/img_ids.rs @@ -51,7 +51,7 @@ image_ids! { // Crosshair crosshair: "voxygen/element/misc_bg/crosshair.vox", - +//////////////////////////////////////////////////////////////////////// // Buttons @@ -121,7 +121,7 @@ image_ids! { button_hover: "voxygen/element/buttons/button_hover.vox", button_press: "voxygen/element/buttons/button_press.vox", - +////////////////////////////////////////////////////////////////////////////////////////////////////// charwindow_gradient:"voxygen/element/misc_bg/charwindow.png", diff --git a/world/src/lib.rs b/world/src/lib.rs index 8291e696e4..81c31e3f02 100644 --- a/world/src/lib.rs +++ b/world/src/lib.rs @@ -24,11 +24,11 @@ impl World { Self { sim: sim::WorldSim::generate(seed) } } - pub fn tick(&mut self, dt: Duration) { + pub fn tick(&self, dt: Duration) { // TODO } - pub fn generate_chunk(chunk_pos: Vec2) -> TerrainChunk { + pub fn generate_chunk(&self, chunk_pos: Vec2) -> TerrainChunk { // TODO: This is all test code, remove/improve this later. let air = Block::empty(); @@ -47,7 +47,11 @@ impl World { * 1000.0) }; - let offset_z = get_offset(chunk_pos * Vec2::from(TerrainChunkSize::SIZE).map(|e: u32| e as i32)); + let offset_z = self.sim.get(chunk_pos.map(|e| e as u32)) + .map(|chunk| chunk.alt as i32) + .unwrap_or(0); + + //get_offset(chunk_pos * Vec2::from(TerrainChunkSize::SIZE).map(|e: u32| e as i32)); let mut chunk = TerrainChunk::new(offset_z as i32, stone, air, TerrainChunkMeta::void()); diff --git a/world/src/sim.rs b/world/src/sim.rs index a93dfe746e..61f7999ec8 100644 --- a/world/src/sim.rs +++ b/world/src/sim.rs @@ -1,4 +1,10 @@ +use std::ops::{Mul, Div}; use noise::{NoiseFn, OpenSimplex, Seedable}; +use vek::*; +use common::{ + terrain::TerrainChunkSize, + vol::VolSize, +}; use crate::WORLD_SIZE; pub struct WorldSim { @@ -14,9 +20,9 @@ impl WorldSim { }; let mut chunks = Vec::new(); - for x in 0..WORLD_SIZE.x { - for y in 0..WORLD_SIZE.y { - chunks.push(SimChunk::generate(&mut gen_ctx)); + 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)); } } @@ -25,20 +31,32 @@ impl WorldSim { chunks, } } + + pub fn get(&self, chunk_pos: Vec2) -> 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 + } + } } struct GenCtx { alt_nz: OpenSimplex, } -struct SimChunk { - alt: f32, +pub struct SimChunk { + pub alt: f32, } impl SimChunk { - pub fn generate(gen_ctx: &mut GenCtx) -> Self { + fn generate(pos: Vec2, gen_ctx: &mut GenCtx) -> Self { + let wposf = (pos * Vec2::from(TerrainChunkSize::SIZE)).map(|e| e as f64); + Self { - alt: 0.0 + alt: gen_ctx.alt_nz + .get((wposf.div(2048.0)).into_array()) + .mul(512.0) as f32, } } } From 12ef159ea1606f95ca59fb106e969dd82c712335 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sat, 18 May 2019 18:36:45 +0100 Subject: [PATCH 06/15] Fixed semicolon typo Former-commit-id: 30dbac1bccde7a5c8ebce015e04df66e9d64f1b1 --- server/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/lib.rs b/server/src/lib.rs index bf7c8de701..896428df6c 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -571,7 +571,7 @@ impl Server { 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))).unwrap() + let _ = chunk_tx.send((key, world.generate_chunk(key))).unwrap(); }); } } From db7b3c11928bdb500e51fd6f39012b598b3f11d8 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sun, 19 May 2019 15:54:37 +0100 Subject: [PATCH 07/15] Made the edges of the world be empty Former-commit-id: 51a3315a3b00d28c87c6364d83e32d180f4f8e18 --- world/src/lib.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/world/src/lib.rs b/world/src/lib.rs index 81c31e3f02..1603627da2 100644 --- a/world/src/lib.rs +++ b/world/src/lib.rs @@ -47,13 +47,16 @@ impl World { * 1000.0) }; - let offset_z = self.sim.get(chunk_pos.map(|e| e as u32)) + let offset_z = if let Some(offset_z) = self.sim + .get(chunk_pos.map(|e| e as u32)) .map(|chunk| chunk.alt as i32) - .unwrap_or(0); + { + offset_z as i32 + } else { + return TerrainChunk::new(0, air, air, TerrainChunkMeta::void()); + }; - //get_offset(chunk_pos * Vec2::from(TerrainChunkSize::SIZE).map(|e: u32| e as i32)); - - let mut chunk = TerrainChunk::new(offset_z as i32, stone, air, TerrainChunkMeta::void()); + let mut chunk = TerrainChunk::new(offset_z, stone, air, TerrainChunkMeta::void()); for x in 0..TerrainChunkSize::SIZE.x as i32 { for y in 0..TerrainChunkSize::SIZE.y as i32 { From 58952ae9eb1a4b0b48ab87a3cbbd63840930a8a2 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Mon, 20 May 2019 03:53:04 +0100 Subject: [PATCH 08/15] Added basic mountain/valley worldgen Former-commit-id: 5a45f18fcdf523841ee8433ba2ff0b8765eadf3a --- common/src/terrain/chonk.rs | 12 ++--- world/src/lib.rs | 84 +++++++++++++++++------------------ world/src/sim.rs | 87 ++++++++++++++++++++++++++++++++++--- 3 files changed, 127 insertions(+), 56 deletions(-) diff --git a/common/src/terrain/chonk.rs b/common/src/terrain/chonk.rs index 245aa09ab3..554f01d804 100644 --- a/common/src/terrain/chonk.rs +++ b/common/src/terrain/chonk.rs @@ -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, @@ -37,11 +39,11 @@ impl Chonk { } pub fn get_z_max(&self) -> i32 { - self.z_offset + (self.sub_chunks.len() as u32 * TerrainChunkSize::SIZE.z) as 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 } } @@ -57,7 +59,7 @@ impl ReadVol for Chonk { // Below the terrain Ok(&self.below) } else if pos.z - >= self.z_offset + TerrainChunkSize::SIZE.z as i32 * self.sub_chunks.len() as i32 + >= self.z_offset + SUB_CHUNK_HEIGHT as i32 * self.sub_chunks.len() as i32 { // Above the terrain Ok(&self.above) @@ -73,7 +75,7 @@ impl ReadVol for Chonk { let rpos = pos - Vec3::unit_z() * (self.z_offset - + sub_chunk_idx as i32 * TerrainChunkSize::SIZE.z as i32); + + sub_chunk_idx as i32 * SUB_CHUNK_HEIGHT as i32); chunk.get(rpos).map_err(|err| ChonkError::ChunkError(err)) } } @@ -95,7 +97,7 @@ impl WriteVol for Chonk { 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); match &mut self.sub_chunks[sub_chunk_idx] { // Can't fail diff --git a/world/src/lib.rs b/world/src/lib.rs index 1603627da2..96efc48872 100644 --- a/world/src/lib.rs +++ b/world/src/lib.rs @@ -1,6 +1,9 @@ mod sim; -use std::time::Duration; +use std::{ + ops::{Add, Neg}, + time::Duration, +}; use noise::{NoiseFn, Perlin, Seedable}; use vek::*; use common::{ @@ -13,8 +16,6 @@ pub enum Error { Other(String), } -pub const WORLD_SIZE: Vec2 = Vec2 { x: 1024, y: 1024 }; - pub struct World { sim: sim::WorldSim, } @@ -37,66 +38,61 @@ impl World { let dirt = Block::new(3, Rgb::new(128, 90, 0)); let sand = Block::new(4, Rgb::new(180, 150, 50)); - let offset_nz = Perlin::new().set_seed(3); - 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 warp_nz = Perlin::new().set_seed(self.sim.seed + 0); + let temp_nz = Perlin::new().set_seed(self.sim.seed + 1); + let ridge_nz = Perlin::new().set_seed(self.sim.seed + 2); - let get_offset = |pos: Vec2| { - ((offset_nz.get(pos.map(|e| e as f64 / 4000.0).into_array()) + 1.0) - * 1000.0) + 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 offset_z = if let Some(offset_z) = self.sim - .get(chunk_pos.map(|e| e as u32)) - .map(|chunk| chunk.alt as i32) - { - offset_z as i32 - } else { - return TerrainChunk::new(0, air, air, TerrainChunkMeta::void()); - }; - - let mut chunk = TerrainChunk::new(offset_z, stone, 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 offset_z as i32..offset_z as i32 + 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 chaos = self.sim + .get_interpolated(wpos2d, |chunk| chunk.chaos) + .unwrap_or(0.0); + + let ridge_freq = 1.0 / 128.0; + let ridge_ampl = 96.0; + + let ridge = ridge_nz + .get((wposf2d * ridge_freq).into_array()).abs().neg().add(1.0) as f32 * ridge_ampl * chaos.powf(8.0); + + let height_z = self.sim + .get_interpolated(wpos2d, |chunk| chunk.alt) + .unwrap_or(0.0) + + ridge; + + for z in base_z..base_z + 256 { 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 = 128.0; + let warp_freq = 1.0 / 48.0; + let warp_ampl = 24.0; - let chaos = chaos_nz - .get(Vec2::from(wposf * chaos_freq).into_array()) - .max(0.0) - + 0.5; + let height = height_z + + warp_nz.get((wposf * warp_freq).into_array()) as f32 * warp_ampl * (chaos + 0.05); - 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 - + get_offset(Vec2::from(wpos)) as f64; let temp = - (temp_nz.get(Vec2::from(wposf * (1.0 / 64.0)).into_array()) + 1.0) * 0.5; + (temp_nz.get(Vec2::from(wposf * (1.0 / 64.0)).into_array()) as f32 + 1.0) * 0.5; + 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 { + } else if 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(2, Rgb::new(10 + (75.0 * temp) as u8, 180, 50 - (50.0 * temp) as u8)) } else { air }, diff --git a/world/src/sim.rs b/world/src/sim.rs index 61f7999ec8..7f38ffb82c 100644 --- a/world/src/sim.rs +++ b/world/src/sim.rs @@ -1,14 +1,18 @@ -use std::ops::{Mul, Div}; +use std::{ + ops::{Add, Mul, Div}, + f32, +}; use noise::{NoiseFn, OpenSimplex, Seedable}; use vek::*; use common::{ terrain::TerrainChunkSize, vol::VolSize, }; -use crate::WORLD_SIZE; + +pub const WORLD_SIZE: Vec2 = Vec2 { x: 1024, y: 1024 }; pub struct WorldSim { - seed: u32, + pub seed: u32, chunks: Vec, } @@ -16,7 +20,9 @@ impl WorldSim { pub fn generate(seed: u32) -> Self { let mut gen_ctx = GenCtx { alt_nz: OpenSimplex::new() - .set_seed(seed), + .set_seed(seed + 0), + chaos_nz: OpenSimplex::new() + .set_seed(seed + 1), }; let mut chunks = Vec::new(); @@ -39,13 +45,65 @@ impl WorldSim { None } } + + pub fn get_base_z(&self, chunk_pos: Vec2) -> Option { + 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, x| a.map(|a| a.min(x)).or(Some(x)))) + } + + pub fn get_interpolated f32>(&self, pos: Vec2, mut f: F) -> Option { + let pos = pos.map2(TerrainChunkSize::SIZE.into(), |e, sz: u32| e as f64 / sz as f64); + + fn cubic(a: f32, b: f32, c: f32, d: f32, x: f32) -> f32 { + let x2 = x * x; + + // Catmull-Rom splines + let co0 = -0.5 * a + 1.5 * b - 1.5 * c + 0.5 * d; + let co1 = a - 2.5 * b + 2.0 * c - 0.5 * d; + let co2 = -0.5 * a + 0.5 * c; + let co3 = b; + + co0 * x2 * x + co1 * x2 + co2 * x + co3 + } + + let mut y = [0.0; 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); + } + + /* + fn cosine_interp (a: f32, b: f32, x: f32) -> f32 { + let x2 = x;//(1.0 - (x * f32::consts::PI).cos()) / 2.0; + a * (1.0 - x2) + b * x2 + } + */ + + Some(cubic(y[0], y[1], y[2], y[3], pos.y.fract() as f32)) + } } struct GenCtx { + chaos_nz: OpenSimplex, alt_nz: OpenSimplex, } pub struct SimChunk { + pub chaos: f32, pub alt: f32, } @@ -53,10 +111,25 @@ impl SimChunk { fn generate(pos: Vec2, gen_ctx: &mut GenCtx) -> Self { let wposf = (pos * Vec2::from(TerrainChunkSize::SIZE)).map(|e| e as f64); + let chaos = (gen_ctx.chaos_nz + .get((wposf.div(400.0)).into_array()) as f32) + .max(0.0) + .add(0.15) + .powf(2.0); + Self { - alt: gen_ctx.alt_nz - .get((wposf.div(2048.0)).into_array()) - .mul(512.0) as f32, + chaos, + alt: (gen_ctx.alt_nz + .get((wposf.div(125.0)).into_array()) as f32) + .add(1.0).mul(0.5) + .mul(750.0) + .mul(chaos.max(0.05)), } } + + pub fn get_base_z(&self) -> f32 { + const BASE_Z_TOLERANCE: f32 = 32.0; + + self.alt - BASE_Z_TOLERANCE + } } From 343e22e5df44d25cd6c18930413ce992aaee9e4c Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Mon, 20 May 2019 16:01:27 +0100 Subject: [PATCH 09/15] Added rivers, improved mountains Former-commit-id: c1b76c54d2aa8f0616c26b0724fe34c0d80ac4fd --- world/src/lib.rs | 27 +++++++++++++------ world/src/sim.rs | 68 ++++++++++++++++++++++++++++++++++-------------- 2 files changed, 68 insertions(+), 27 deletions(-) diff --git a/world/src/lib.rs b/world/src/lib.rs index 96efc48872..6b8be5a127 100644 --- a/world/src/lib.rs +++ b/world/src/lib.rs @@ -1,7 +1,7 @@ mod sim; use std::{ - ops::{Add, Neg}, + ops::{Add, Mul, Neg}, time::Duration, }; use noise::{NoiseFn, Perlin, Seedable}; @@ -54,12 +54,22 @@ impl World { 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 max_z = self.sim + .get_interpolated(wpos2d, |chunk| chunk.get_max_z()) + .unwrap_or(0.0) as i32; + let chaos = self.sim .get_interpolated(wpos2d, |chunk| chunk.chaos) .unwrap_or(0.0); - let ridge_freq = 1.0 / 128.0; - let ridge_ampl = 96.0; + let damp = self.sim + .get_interpolated(wpos2d, |chunk| chunk.damp) + .unwrap_or(0.0) + .abs().neg().add(1.0) + .mul(1.0 - chaos); + + let ridge_freq = 1.0 / 125.0; + let ridge_ampl = 125.0; let ridge = ridge_nz .get((wposf2d * ridge_freq).into_array()).abs().neg().add(1.0) as f32 * ridge_ampl * chaos.powf(8.0); @@ -67,19 +77,20 @@ impl World { let height_z = self.sim .get_interpolated(wpos2d, |chunk| chunk.alt) .unwrap_or(0.0) - + ridge; + + ridge + - damp.powf(20.0) * 32.0; - for z in base_z..base_z + 256 { + 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 warp_freq = 1.0 / 48.0; - let warp_ampl = 24.0; + let warp_freq = 1.0 / 40.0; + let warp_ampl = 45.0; let height = height_z - + warp_nz.get((wposf * warp_freq).into_array()) as f32 * warp_ampl * (chaos + 0.05); + + warp_nz.get((wposf * warp_freq).into_array()) as f32 * warp_ampl * (chaos + 0.05).min(0.85); let temp = (temp_nz.get(Vec2::from(wposf * (1.0 / 64.0)).into_array()) as f32 + 1.0) * 0.5; diff --git a/world/src/sim.rs b/world/src/sim.rs index 7f38ffb82c..fb377f3db4 100644 --- a/world/src/sim.rs +++ b/world/src/sim.rs @@ -1,8 +1,8 @@ use std::{ - ops::{Add, Mul, Div}, + ops::{Add, Mul, Div, Neg}, f32, }; -use noise::{NoiseFn, OpenSimplex, Seedable}; +use noise::{NoiseFn, SuperSimplex, OpenSimplex, Seedable}; use vek::*; use common::{ terrain::TerrainChunkSize, @@ -19,10 +19,14 @@ pub struct WorldSim { impl WorldSim { pub fn generate(seed: u32) -> Self { let mut gen_ctx = GenCtx { - alt_nz: OpenSimplex::new() + base_nz: OpenSimplex::new() .set_seed(seed + 0), - chaos_nz: OpenSimplex::new() + damp_nz: SuperSimplex::new() .set_seed(seed + 1), + chaos_nz: SuperSimplex::new() + .set_seed(seed + 2), + alt_nz: OpenSimplex::new() + .set_seed(seed + 3), }; let mut chunks = Vec::new(); @@ -60,22 +64,26 @@ impl WorldSim { .fold(None, |a: Option, x| a.map(|a| a.min(x)).or(Some(x)))) } - pub fn get_interpolated f32>(&self, pos: Vec2, mut f: F) -> Option { + pub fn get_interpolated(&self, pos: Vec2, mut f: F) -> Option + where + T: Copy + Default + Add + Mul, + F: FnMut(&SimChunk) -> T, + { let pos = pos.map2(TerrainChunkSize::SIZE.into(), |e, sz: u32| e as f64 / sz as f64); - fn cubic(a: f32, b: f32, c: f32, d: f32, x: f32) -> f32 { + let cubic = |a: T, b: T, c: T, d: T, x: f32| -> T { let x2 = x * x; // Catmull-Rom splines - let co0 = -0.5 * a + 1.5 * b - 1.5 * c + 0.5 * d; - let co1 = a - 2.5 * b + 2.0 * c - 0.5 * d; - let co2 = -0.5 * a + 0.5 * c; + 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 = [0.0; 4]; + 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))?); @@ -98,11 +106,16 @@ impl WorldSim { } struct GenCtx { - chaos_nz: OpenSimplex, + base_nz: OpenSimplex, + damp_nz: SuperSimplex, + chaos_nz: SuperSimplex, alt_nz: OpenSimplex, } +const Z_TOLERANCE: f32 = 32.0; + pub struct SimChunk { + pub damp: f32, pub chaos: f32, pub alt: f32, } @@ -111,16 +124,31 @@ impl SimChunk { fn generate(pos: Vec2, gen_ctx: &mut GenCtx) -> Self { let wposf = (pos * Vec2::from(TerrainChunkSize::SIZE)).map(|e| e as f64); + let base = (gen_ctx.base_nz.get((wposf.div(6000.0)).into_array()) as f32) + .add(1.0).mul(0.5) + .mul(100.0) + .add(32.0); + + let damp = (0.0 + + gen_ctx.damp_nz.get((wposf.div(2000.0)).into_array()) + + gen_ctx.damp_nz.get((wposf.div(250.0)).into_array()) * 0.25 + ) as f32; + let chaos = (gen_ctx.chaos_nz - .get((wposf.div(400.0)).into_array()) as f32) - .max(0.0) + .get((wposf.div(1000.0)).into_array()) as f32) + .add(1.0).mul(0.5) + .mul(damp.max(0.0)) .add(0.15) - .powf(2.0); + .powf(2.0) + .min(1.0); Self { + damp, chaos, - alt: (gen_ctx.alt_nz - .get((wposf.div(125.0)).into_array()) as f32) + alt: base + ((0.0 + + gen_ctx.alt_nz.get((wposf.div(650.0)).into_array()) * 0.7 + + gen_ctx.alt_nz.get((wposf.div(100.0)).into_array()) * 0.3 + ) as f32) .add(1.0).mul(0.5) .mul(750.0) .mul(chaos.max(0.05)), @@ -128,8 +156,10 @@ impl SimChunk { } pub fn get_base_z(&self) -> f32 { - const BASE_Z_TOLERANCE: f32 = 32.0; + self.alt - Z_TOLERANCE + } - self.alt - BASE_Z_TOLERANCE + pub fn get_max_z(&self) -> f32 { + self.alt + Z_TOLERANCE } } From 54ecb0054a30009720573415ba97bc83b1cebace Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Tue, 21 May 2019 01:57:16 +0100 Subject: [PATCH 10/15] Restarted worldgen Former-commit-id: e1526ec5f865904f11ab6a1507ecdc1a52acb28d --- Cargo.lock | 71 +++++++++++++++++++++++++++ common/src/terrain/chonk.rs | 2 +- voxygen/Cargo.toml | 2 +- world/Cargo.toml | 3 ++ world/examples/view.rs | 65 +++++++++++++++++++++++++ world/src/lib.rs | 54 ++++++++------------- world/src/sim.rs | 96 +++++++++++++++++++++---------------- 7 files changed, 218 insertions(+), 75 deletions(-) create mode 100644 world/examples/view.rs diff --git a/Cargo.lock b/Cargo.lock index 608febe085..412c562821 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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)" = "" "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" diff --git a/common/src/terrain/chonk.rs b/common/src/terrain/chonk.rs index 554f01d804..23d0c74bc3 100644 --- a/common/src/terrain/chonk.rs +++ b/common/src/terrain/chonk.rs @@ -12,7 +12,7 @@ pub enum ChonkError { OutOfBounds, } -const SUB_CHUNK_HEIGHT: u32 = 16; +const SUB_CHUNK_HEIGHT: u32 = 32; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Chonk { diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index be86155a08..e597f54905 100644 --- a/voxygen/Cargo.toml +++ b/voxygen/Cargo.toml @@ -52,4 +52,4 @@ directories = "1.0" portpicker = "0.1" num = "0.2" backtrace = "0.3" -rand = "0.5" \ No newline at end of file +rand = "0.5" diff --git a/world/Cargo.toml b/world/Cargo.toml index 6918256955..dc627a90f6 100644 --- a/world/Cargo.toml +++ b/world/Cargo.toml @@ -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" } diff --git a/world/examples/view.rs b/world/examples/view.rs new file mode 100644 index 0000000000..103116e08f --- /dev/null +++ b/world/examples/view.rs @@ -0,0 +1,65 @@ +use std::ops::{Add, Sub, Mul}; +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(); + } +} diff --git a/world/src/lib.rs b/world/src/lib.rs index 6b8be5a127..0201e1614d 100644 --- a/world/src/lib.rs +++ b/world/src/lib.rs @@ -1,7 +1,7 @@ mod sim; use std::{ - ops::{Add, Mul, Neg}, + ops::{Add, Mul, Div, Neg}, time::Duration, }; use noise::{NoiseFn, Perlin, Seedable}; @@ -25,6 +25,10 @@ impl World { Self { sim: sim::WorldSim::generate(seed) } } + pub fn sim(&self) -> &sim::WorldSim { + &self.sim + } + pub fn tick(&self, dt: Duration) { // TODO } @@ -37,6 +41,7 @@ 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 warp_nz = Perlin::new().set_seed(self.sim.seed + 0); let temp_nz = Perlin::new().set_seed(self.sim.seed + 1); @@ -54,56 +59,37 @@ impl World { 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, + 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; - let chaos = self.sim - .get_interpolated(wpos2d, |chunk| chunk.chaos) - .unwrap_or(0.0); - - let damp = self.sim - .get_interpolated(wpos2d, |chunk| chunk.damp) - .unwrap_or(0.0) - .abs().neg().add(1.0) - .mul(1.0 - chaos); - - let ridge_freq = 1.0 / 125.0; - let ridge_ampl = 125.0; - - let ridge = ridge_nz - .get((wposf2d * ridge_freq).into_array()).abs().neg().add(1.0) as f32 * ridge_ampl * chaos.powf(8.0); - - let height_z = self.sim - .get_interpolated(wpos2d, |chunk| chunk.alt) - .unwrap_or(0.0) - + ridge - - damp.powf(20.0) * 32.0; - 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 warp_freq = 1.0 / 40.0; - let warp_ampl = 45.0; - - let height = height_z - + warp_nz.get((wposf * warp_freq).into_array()) as f32 * warp_ampl * (chaos + 0.05).min(0.85); - - let temp = - (temp_nz.get(Vec2::from(wposf * (1.0 / 64.0)).into_array()) as f32 + 1.0) * 0.5; + let height = alt; + let temp = 0.0; let z = wposf.z as f32; let _ = chunk.set( lpos, - if z < height - 4.0 { + if z < height - 6.0 { stone } else if z < height - 2.0 { dirt } else if z < height { - Block::new(2, Rgb::new(10 + (75.0 * temp) as u8, 180, 50 - (50.0 * temp) as u8)) + Block::new(1, surface_color.map(|e| (e * 255.0) as u8)) } else { air }, @@ -113,5 +99,7 @@ impl World { } chunk + + // */ } } diff --git a/world/src/sim.rs b/world/src/sim.rs index fb377f3db4..9686093424 100644 --- a/world/src/sim.rs +++ b/world/src/sim.rs @@ -1,8 +1,8 @@ use std::{ - ops::{Add, Mul, Div, Neg}, + ops::{Add, Sub, Mul, Div, Neg}, f32, }; -use noise::{NoiseFn, SuperSimplex, OpenSimplex, Seedable}; +use noise::{NoiseFn, BasicMulti, HybridMulti, RidgedMulti, SuperSimplex, OpenSimplex, Seedable, MultiFractal}; use vek::*; use common::{ terrain::TerrainChunkSize, @@ -14,19 +14,26 @@ pub const WORLD_SIZE: Vec2 = Vec2 { x: 1024, y: 1024 }; pub struct WorldSim { pub seed: u32, chunks: Vec, + gen_ctx: GenCtx, } impl WorldSim { pub fn generate(seed: u32) -> Self { let mut gen_ctx = GenCtx { - base_nz: OpenSimplex::new() + turb_x_nz: BasicMulti::new() .set_seed(seed + 0), - damp_nz: SuperSimplex::new() + turb_y_nz: BasicMulti::new() .set_seed(seed + 1), - chaos_nz: SuperSimplex::new() + chaos_nz: RidgedMulti::new() + .set_octaves(7) .set_seed(seed + 2), - alt_nz: OpenSimplex::new() + alt_nz: HybridMulti::new() + .set_octaves(7) + .set_persistence(0.1) .set_seed(seed + 3), + small_nz: BasicMulti::new() + .set_octaves(1) + .set_seed(seed + 4), }; let mut chunks = Vec::new(); @@ -39,6 +46,7 @@ impl WorldSim { Self { seed, chunks, + gen_ctx, } } @@ -94,28 +102,50 @@ impl WorldSim { y[y_idx] = cubic(x0, x1, x2, x3, pos.x.fract() as f32); } - /* - fn cosine_interp (a: f32, b: f32, x: f32) -> f32 { - let x2 = x;//(1.0 - (x * f32::consts::PI).cos()) / 2.0; - a * (1.0 - x2) + b * x2 - } - */ - Some(cubic(y[0], y[1], y[2], y[3], pos.y.fract() as f32)) } + + pub fn sample(&self, pos: Vec2) -> Option { + 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 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.2) * 32.0; + + // Colours + let grass = Rgb::new(0.0, 0.765, 0.05); + let stone = Rgb::new(0.695, 0.66, 0.551); + + Some(Sample { + alt, + surface_color: Lerp::lerp(grass, stone, (alt - SEA_LEVEL) / 300.0), + }) + } +} + +pub struct Sample { + pub alt: f32, + pub surface_color: Rgb, } struct GenCtx { - base_nz: OpenSimplex, - damp_nz: SuperSimplex, - chaos_nz: SuperSimplex, - alt_nz: OpenSimplex, + turb_x_nz: BasicMulti, + turb_y_nz: BasicMulti, + chaos_nz: RidgedMulti, + alt_nz: HybridMulti, + small_nz: BasicMulti, } const Z_TOLERANCE: f32 = 32.0; +const SEA_LEVEL: f32 = 64.0; pub struct SimChunk { - pub damp: f32, pub chaos: f32, pub alt: f32, } @@ -124,34 +154,20 @@ impl SimChunk { fn generate(pos: Vec2, gen_ctx: &mut GenCtx) -> Self { let wposf = (pos * Vec2::from(TerrainChunkSize::SIZE)).map(|e| e as f64); - let base = (gen_ctx.base_nz.get((wposf.div(6000.0)).into_array()) as f32) - .add(1.0).mul(0.5) - .mul(100.0) - .add(32.0); - - let damp = (0.0 - + gen_ctx.damp_nz.get((wposf.div(2000.0)).into_array()) - + gen_ctx.damp_nz.get((wposf.div(250.0)).into_array()) * 0.25 - ) as f32; - let chaos = (gen_ctx.chaos_nz - .get((wposf.div(1000.0)).into_array()) as f32) + .get((wposf.div(3500.0)).into_array()) as f32) .add(1.0).mul(0.5) - .mul(damp.max(0.0)) - .add(0.15) - .powf(2.0) - .min(1.0); + .powf(1.85); + + let chaos = chaos + chaos.mul(20.0).sin().mul(0.05); Self { - damp, chaos, - alt: base + ((0.0 - + gen_ctx.alt_nz.get((wposf.div(650.0)).into_array()) * 0.7 - + gen_ctx.alt_nz.get((wposf.div(100.0)).into_array()) * 0.3 - ) as f32) + alt: SEA_LEVEL + (gen_ctx.alt_nz + .get((wposf.div(750.0)).into_array()) as f32) .add(1.0).mul(0.5) - .mul(750.0) - .mul(chaos.max(0.05)), + .mul(chaos) + .mul(650.0), } } From 2a56e7a83d501947ac75e5daa4bd581fcf5ed96a Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Tue, 21 May 2019 13:28:53 +0100 Subject: [PATCH 11/15] Added rocks, improved hills Former-commit-id: c8f3d8fb550186bd87d0de953098971050fd1e03 --- voxygen/shaders/postprocess.frag | 2 +- voxygen/src/mesh/vol.rs | 20 ++++---- world/src/lib.rs | 28 +++++++++-- world/src/sim.rs | 83 ++++++++++++++++++++++++++------ 4 files changed, 105 insertions(+), 28 deletions(-) diff --git a/voxygen/shaders/postprocess.frag b/voxygen/shaders/postprocess.frag index dd32d414f2..7602776032 100644 --- a/voxygen/shaders/postprocess.frag +++ b/voxygen/shaders/postprocess.frag @@ -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); diff --git a/voxygen/src/mesh/vol.rs b/voxygen/src/mesh/vol.rs index d2e1cd2924..f24ad3c31b 100644 --- a/voxygen/src/mesh/vol.rs +++ b/voxygen/src/mesh/vol.rs @@ -50,22 +50,24 @@ fn create_quad, Vec3, Rgb) -> P::Vertex>( ao: Vec4, vcons: &F, ) -> Quad

{ - 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])), ) } } diff --git a/world/src/lib.rs b/world/src/lib.rs index 0201e1614d..a63a2a4e90 100644 --- a/world/src/lib.rs +++ b/world/src/lib.rs @@ -1,10 +1,10 @@ mod sim; use std::{ - ops::{Add, Mul, Div, Neg}, + ops::{Add, Sub, Mul, Div, Neg}, time::Duration, }; -use noise::{NoiseFn, Perlin, Seedable}; +use noise::{NoiseFn, BasicMulti, Perlin, Seedable, MultiFractal}; use vek::*; use common::{ terrain::{Block, TerrainChunk, TerrainChunkMeta, TerrainChunkSize}, @@ -45,7 +45,14 @@ impl World { let warp_nz = Perlin::new().set_seed(self.sim.seed + 0); let temp_nz = Perlin::new().set_seed(self.sim.seed + 1); - let ridge_nz = Perlin::new().set_seed(self.sim.seed + 2); + /* + let cliff_nz = BasicMulti::new() + .set_octaves(2) + .set_seed(self.sim.seed + 2); + let cliff_mask_nz = BasicMulti::new() + .set_octaves(4) + .set_seed(self.sim.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, @@ -78,7 +85,20 @@ impl World { + Vec3::from(chunk_pos) * TerrainChunkSize::SIZE.map(|e| e as i32); let wposf = wpos.map(|e| e as f64); - let height = alt; + /* + let cliff_mask = cliff_mask_nz.get((wposf.div(Vec3::new(512.0, 512.0, 2048.0))).into_array()) + .sub(0.1) + .max(0.0) + .mul(1.5) + .round() as f32; + let cliff = (cliff_nz.get((wposf.div(Vec3::new(256.0, 256.0, 128.0))).into_array()) as f32) + .mul(cliff_mask) + //.mul((30.0).div((wposf.z as f32 - alt)).max(0.0)) + .mul(150.0) + .min(64.0); + */ + + let height = alt;// + cliff; let temp = 0.0; let z = wposf.z as f32; diff --git a/world/src/sim.rs b/world/src/sim.rs index 9686093424..4c064dc593 100644 --- a/world/src/sim.rs +++ b/world/src/sim.rs @@ -27,13 +27,20 @@ impl WorldSim { 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 + 3), - small_nz: BasicMulti::new() - .set_octaves(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(); @@ -114,17 +121,31 @@ impl WorldSim { );*/ 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(200.0)).into_array()) as f32) + .mul(rockiness) + .sub(0.3) + .max(0.0) + .mul(2.5); 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.2) * 32.0; + + self.gen_ctx.small_nz.get((wposf.div(128.0)).into_array()) as f32 * chaos.max(0.2) * 32.0 + + rock * 30.0; // Colours - let grass = Rgb::new(0.0, 0.765, 0.05); - let stone = Rgb::new(0.695, 0.66, 0.551); + let cold_grass = Rgb::new(0.0, 0.75, 0.25); + let warm_grass = Rgb::new(0.55, 0.9, 0.0); + let stone = Rgb::new(0.8, 0.7, 0.551); + + let grass = Rgb::lerp(cold_grass, warm_grass, temp); + let ground = Rgb::lerp(grass, stone, rock.mul(5.0).min(0.8)); + let cliff = stone; Some(Sample { alt, - surface_color: Lerp::lerp(grass, stone, (alt - SEA_LEVEL) / 300.0), + surface_color: Rgb::lerp(ground, cliff, (alt - SEA_LEVEL) / 150.0), }) } } @@ -139,43 +160,77 @@ struct GenCtx { 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 = 32.0; +const Z_TOLERANCE: (f32, f32) = (32.0, 64.0); 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, 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) + .add(1.0).mul(0.5); + let chaos = (gen_ctx.chaos_nz .get((wposf.div(3500.0)).into_array()) as f32) .add(1.0).mul(0.5) - .powf(1.85); + .powf(1.9) + .add(0.25 * hill); let chaos = chaos + chaos.mul(20.0).sin().mul(0.05); + let alt_main = gen_ctx.alt_nz.get((wposf.div(750.0)).into_array()) as f32; + Self { chaos, - alt: SEA_LEVEL + (gen_ctx.alt_nz - .get((wposf.div(750.0)).into_array()) as f32) + alt: SEA_LEVEL + (0.0 + + alt_main + + gen_ctx.small_nz.get((wposf.div(300.0)).into_array()) as f32 * alt_main * 1.3) .add(1.0).mul(0.5) .mul(chaos) - .mul(650.0), + .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 + self.alt - Z_TOLERANCE.0 } pub fn get_max_z(&self) -> f32 { - self.alt + Z_TOLERANCE + self.alt + Z_TOLERANCE.1 + } +} + +trait Hsv { + fn into_hsv(self) -> Self; + fn into_rgb(self) -> Self; +} + +impl Hsv for Rgb { + fn into_hsv(mut self) -> Self { + unimplemented!() + } + + fn into_rgb(mut self) -> Self { + unimplemented!() } } From cdfa5848d1c29e50d119015378bf9ba8d0382319 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Tue, 21 May 2019 22:50:12 +0100 Subject: [PATCH 12/15] Added water, beaches, craggs Former-commit-id: 0213bbac23cf01df31896461d0cdda3b0ee708dc --- world/src/lib.rs | 37 +++++++++++-------------------------- world/src/sim.rs | 41 +++++++++++++++++++++++++++++------------ 2 files changed, 40 insertions(+), 38 deletions(-) diff --git a/world/src/lib.rs b/world/src/lib.rs index a63a2a4e90..e017f71a6f 100644 --- a/world/src/lib.rs +++ b/world/src/lib.rs @@ -43,16 +43,9 @@ impl World { let sand = Block::new(4, Rgb::new(180, 150, 50)); let water = Block::new(5, Rgb::new(100, 150, 255)); - let warp_nz = Perlin::new().set_seed(self.sim.seed + 0); - let temp_nz = Perlin::new().set_seed(self.sim.seed + 1); - /* - let cliff_nz = BasicMulti::new() - .set_octaves(2) - .set_seed(self.sim.seed + 2); - let cliff_mask_nz = BasicMulti::new() - .set_octaves(4) - .set_seed(self.sim.seed + 3); - */ + let warp_nz = BasicMulti::new() + .set_octaves(3) + .set_seed(self.sim.seed + 0); let base_z = match self.sim.get_base_z(chunk_pos.map(|e| e as u32)) { Some(base_z) => base_z as i32, @@ -68,6 +61,7 @@ impl World { let sim::Sample { alt, + chaos, surface_color } = if let Some(sample) = self.sim.sample(wpos2d) { sample @@ -85,31 +79,22 @@ impl World { + Vec3::from(chunk_pos) * TerrainChunkSize::SIZE.map(|e| e as i32); let wposf = wpos.map(|e| e as f64); - /* - let cliff_mask = cliff_mask_nz.get((wposf.div(Vec3::new(512.0, 512.0, 2048.0))).into_array()) - .sub(0.1) - .max(0.0) - .mul(1.5) - .round() as f32; - let cliff = (cliff_nz.get((wposf.div(Vec3::new(256.0, 256.0, 128.0))).into_array()) as f32) - .mul(cliff_mask) - //.mul((30.0).div((wposf.z as f32 - alt)).max(0.0)) - .mul(150.0) - .min(64.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 height = alt;// + cliff; + let height = alt + warp; let temp = 0.0; let z = wposf.z as f32; let _ = chunk.set( lpos, - if z < height - 6.0 { + if z < height - 4.0 { stone - } else if z < height - 2.0 { - dirt } 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 }, diff --git a/world/src/sim.rs b/world/src/sim.rs index 4c064dc593..c6bc951aee 100644 --- a/world/src/sim.rs +++ b/world/src/sim.rs @@ -124,34 +124,48 @@ impl WorldSim { 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(200.0)).into_array()) as f32) + let rock = (self.gen_ctx.small_nz.get((wposf.div(100.0)).into_array()) as f32) .mul(rockiness) - .sub(0.3) + .sub(0.2) .max(0.0) - .mul(2.5); + .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.2) * 32.0 - + rock * 30.0; + + 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 stone = Rgb::new(0.8, 0.7, 0.551); + 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, stone, rock.mul(5.0).min(0.8)); - let cliff = stone; + 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, - surface_color: Rgb::lerp(ground, cliff, (alt - SEA_LEVEL) / 150.0), + 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, } @@ -167,7 +181,7 @@ struct GenCtx { } const Z_TOLERANCE: (f32, f32) = (32.0, 64.0); -const SEA_LEVEL: f32 = 64.0; +pub const SEA_LEVEL: f32 = 64.0; pub struct SimChunk { pub chaos: f32, @@ -182,7 +196,7 @@ impl SimChunk { let hill = (gen_ctx.hill_nz .get((wposf.div(3500.0)).into_array()) as f32) - .add(1.0).mul(0.5); + .max(0.0); let chaos = (gen_ctx.chaos_nz .get((wposf.div(3500.0)).into_array()) as f32) @@ -192,15 +206,18 @@ impl SimChunk { 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 * 1.3) + + 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), From d93743c1a659def88324e59a63c0bc05c34908c4 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Tue, 21 May 2019 23:04:39 +0100 Subject: [PATCH 13/15] Added spawn point Former-commit-id: 04ea38df61d3610d679368166de220243ef1bfba --- common/src/terrain/chonk.rs | 2 +- server/src/lib.rs | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/common/src/terrain/chonk.rs b/common/src/terrain/chonk.rs index 23d0c74bc3..554f01d804 100644 --- a/common/src/terrain/chonk.rs +++ b/common/src/terrain/chonk.rs @@ -12,7 +12,7 @@ pub enum ChonkError { OutOfBounds, } -const SUB_CHUNK_HEIGHT: u32 = 32; +const SUB_CHUNK_HEIGHT: u32 = 16; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Chonk { diff --git a/server/src/lib.rs b/server/src/lib.rs index 896428df6c..cf7c0065d9 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -38,6 +38,9 @@ pub enum Event { Chat { entity: EcsEntity, msg: String }, } +#[derive(Copy, Clone)] +struct SpawnPoint(Vec3); + pub struct Server { state: State, world: Arc, @@ -65,6 +68,7 @@ impl Server { let mut state = State::new(); state.ecs_mut().register::(); + state.ecs_mut().add_resource(SpawnPoint(Vec3::new(16_384.0, 16_384.0, 150.0))); let mut this = Self { state, @@ -81,6 +85,7 @@ impl Server { pending_chunks: HashSet::new(), }; + /* for i in 0..4 { this.create_npc( "Tobermory".to_owned(), @@ -90,6 +95,7 @@ impl Server { .with(comp::Agent::Wanderer(Vec2::zero())) .build(); } + */ Ok(this) } @@ -132,8 +138,10 @@ impl Server { name: String, body: comp::Body, ) { + let spawn_point = state.ecs().read_resource::().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. From 78f9d00604b868cdb394e4effe6fc317e8e0790b Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Tue, 21 May 2019 23:31:17 +0100 Subject: [PATCH 14/15] Fixed singleplayer failure caused by worldgen Former-commit-id: a2fdb56682922694b32e4d25890afa7a90c5b923 --- voxygen/src/menu/main/client_init.rs | 2 ++ voxygen/src/menu/main/start_singleplayer.rs | 2 +- voxygen/src/singleplayer.rs | 11 +++++------ 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/voxygen/src/menu/main/client_init.rs b/voxygen/src/menu/main/client_init.rs index ceef63c874..c464117e0e 100644 --- a/voxygen/src/menu/main/client_init.rs +++ b/voxygen/src/menu/main/client_init.rs @@ -1,3 +1,4 @@ +use log::info; use client::{error::Error as ClientError, Client}; use common::comp; use std::{ @@ -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. diff --git a/voxygen/src/menu/main/start_singleplayer.rs b/voxygen/src/menu/main/start_singleplayer.rs index ff77161948..c3e3446294 100644 --- a/voxygen/src/menu/main/start_singleplayer.rs +++ b/voxygen/src/menu/main/start_singleplayer.rs @@ -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, ); diff --git a/voxygen/src/singleplayer.rs b/voxygen/src/singleplayer.rs index 1955227d4b..0a9aa67a06 100644 --- a/voxygen/src/singleplayer.rs +++ b/voxygen/src/singleplayer.rs @@ -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) { +fn run_server(mut server: Server, rec: Receiver) { 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()) From 91ce041c9116a5c9123ada43cd8da10057c9417c Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Tue, 21 May 2019 23:31:38 +0100 Subject: [PATCH 15/15] fmt Former-commit-id: 1f7bec8da117091b3f2e8f58ce45b9caf1b6c89d --- common/src/terrain/chonk.rs | 10 +-- server/src/lib.rs | 12 ++- voxygen/src/menu/main/client_init.rs | 2 +- voxygen/src/mesh/terrain.rs | 13 ++- voxygen/src/mesh/vol.rs | 12 ++- voxygen/src/scene/terrain.rs | 2 +- world/examples/view.rs | 17 +--- world/src/lib.rs | 38 +++++---- world/src/sim.rs | 120 +++++++++++++-------------- 9 files changed, 120 insertions(+), 106 deletions(-) diff --git a/common/src/terrain/chonk.rs b/common/src/terrain/chonk.rs index 554f01d804..229e68da6e 100644 --- a/common/src/terrain/chonk.rs +++ b/common/src/terrain/chonk.rs @@ -58,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 + SUB_CHUNK_HEIGHT 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 { @@ -74,8 +72,7 @@ impl ReadVol for Chonk { SubChunk::Heterogeneous(chunk) => { let rpos = pos - Vec3::unit_z() - * (self.z_offset - + sub_chunk_idx as i32 * SUB_CHUNK_HEIGHT as i32); + * (self.z_offset + sub_chunk_idx as i32 * SUB_CHUNK_HEIGHT as i32); chunk.get(rpos).map_err(|err| ChonkError::ChunkError(err)) } } @@ -96,8 +93,7 @@ impl WriteVol for Chonk { } let rpos = pos - - Vec3::unit_z() - * (self.z_offset + sub_chunk_idx as i32 * SUB_CHUNK_HEIGHT 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 diff --git a/server/src/lib.rs b/server/src/lib.rs index cf7c0065d9..33267b2584 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -23,7 +23,13 @@ use specs::{ join::Join, saveload::MarkedBuilder, world::EntityBuilder as EcsEntityBuilder, Builder, Entity as EcsEntity, }; -use std::{collections::HashSet, i32, net::SocketAddr, sync::{Arc, mpsc}, time::Duration}; +use std::{ + collections::HashSet, + i32, + net::SocketAddr, + sync::{mpsc, Arc}, + time::Duration, +}; use threadpool::ThreadPool; use vek::*; use world::World; @@ -68,7 +74,9 @@ impl Server { let mut state = State::new(); state.ecs_mut().register::(); - state.ecs_mut().add_resource(SpawnPoint(Vec3::new(16_384.0, 16_384.0, 150.0))); + state + .ecs_mut() + .add_resource(SpawnPoint(Vec3::new(16_384.0, 16_384.0, 150.0))); let mut this = Self { state, diff --git a/voxygen/src/menu/main/client_init.rs b/voxygen/src/menu/main/client_init.rs index c464117e0e..46de37705b 100644 --- a/voxygen/src/menu/main/client_init.rs +++ b/voxygen/src/menu/main/client_init.rs @@ -1,6 +1,6 @@ -use log::info; use client::{error::Error as ClientError, Client}; use common::comp; +use log::info; use std::{ net::ToSocketAddrs, sync::mpsc::{channel, Receiver, TryRecvError}, diff --git a/voxygen/src/mesh/terrain.rs b/voxygen/src/mesh/terrain.rs index 8e2e341dbe..c8e36a6093 100644 --- a/voxygen/src/mesh/terrain.rs +++ b/voxygen/src/mesh/terrain.rs @@ -55,12 +55,21 @@ impl + ReadVol, S: VolSize + Clone> Meshable for VolMap2 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 offs = (pos - range.min * Vec3::new(1, 1, 0)).map(|e| e as f32) + - Vec3::new(1.0, 1.0, 0.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, pos, offs, col, TerrainVertex::new, false); + vol::push_vox_verts( + &mut mesh, + self, + pos, + offs, + col, + TerrainVertex::new, + false, + ); } } } diff --git a/voxygen/src/mesh/vol.rs b/voxygen/src/mesh/vol.rs index f24ad3c31b..75a2484c2a 100644 --- a/voxygen/src/mesh/vol.rs +++ b/voxygen/src/mesh/vol.rs @@ -60,13 +60,21 @@ fn create_quad, Vec3, Rgb) -> P::Vertex>( 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])), + 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_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_x + unit_y, + norm, + Rgb::lerp(dark, col, ao_map[2]), + ), vcons(origin + unit_y, norm, Rgb::lerp(dark, col, ao_map[3])), ) } diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 0bf56fc129..da8bd9ec82 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -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, i32}; +use std::{collections::HashMap, i32, sync::mpsc, time::Duration}; use vek::*; struct TerrainChunk { diff --git a/world/examples/view.rs b/world/examples/view.rs index 103116e08f..cc5ed772ae 100644 --- a/world/examples/view.rs +++ b/world/examples/view.rs @@ -1,4 +1,4 @@ -use std::ops::{Add, Sub, Mul}; +use std::ops::{Add, Mul, Sub}; use vek::*; use veloren_world::World; @@ -8,11 +8,8 @@ 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 win = + minifb::Window::new("World Viewer", W, H, minifb::WindowOptions::default()).unwrap(); let mut focus = Vec2::zero(); let mut gain = 1.0; @@ -27,13 +24,7 @@ fn main() { 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) + .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]); diff --git a/world/src/lib.rs b/world/src/lib.rs index e017f71a6f..38ab296511 100644 --- a/world/src/lib.rs +++ b/world/src/lib.rs @@ -1,15 +1,15 @@ mod sim; -use std::{ - ops::{Add, Sub, Mul, Div, Neg}, - time::Duration, -}; -use noise::{NoiseFn, BasicMulti, Perlin, Seedable, MultiFractal}; -use vek::*; 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 { @@ -22,7 +22,9 @@ pub struct World { impl World { pub fn generate(seed: u32) -> Self { - Self { sim: sim::WorldSim::generate(seed) } + Self { + sim: sim::WorldSim::generate(seed), + } } pub fn sim(&self) -> &sim::WorldSim { @@ -43,9 +45,7 @@ impl World { let sand = Block::new(4, Rgb::new(180, 150, 50)); let water = Block::new(5, Rgb::new(100, 150, 255)); - let warp_nz = BasicMulti::new() - .set_octaves(3) - .set_seed(self.sim.seed + 0); + let warp_nz = BasicMulti::new().set_octaves(3).set_seed(self.sim.seed + 0); let base_z = match self.sim.get_base_z(chunk_pos.map(|e| e as u32)) { Some(base_z) => base_z as i32, @@ -56,30 +56,34 @@ impl World { for x in 0..TerrainChunkSize::SIZE.x as i32 { for y in 0..TerrainChunkSize::SIZE.y as i32 { - let wpos2d = Vec2::new(x, y) + Vec3::from(chunk_pos) * TerrainChunkSize::SIZE.map(|e| e as i32); + 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 + surface_color, } = if let Some(sample) = self.sim.sample(wpos2d) { sample } else { - continue + continue; }; - let max_z = self.sim + 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 wpos = + lpos + Vec3::from(chunk_pos) * TerrainChunkSize::SIZE.map(|e| e as i32); let wposf = wpos.map(|e| e as f64); - let warp = (warp_nz.get((wposf.div(Vec3::new(120.0, 120.0, 150.0))).into_array()) as f32) + 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); diff --git a/world/src/sim.rs b/world/src/sim.rs index c6bc951aee..fcdee446e2 100644 --- a/world/src/sim.rs +++ b/world/src/sim.rs @@ -1,13 +1,13 @@ +use common::{terrain::TerrainChunkSize, vol::VolSize}; +use noise::{ + BasicMulti, HybridMulti, MultiFractal, NoiseFn, OpenSimplex, RidgedMulti, Seedable, + SuperSimplex, +}; use std::{ - ops::{Add, Sub, Mul, Div, Neg}, f32, + ops::{Add, Div, Mul, Neg, Sub}, }; -use noise::{NoiseFn, BasicMulti, HybridMulti, RidgedMulti, SuperSimplex, OpenSimplex, Seedable, MultiFractal}; use vek::*; -use common::{ - terrain::TerrainChunkSize, - vol::VolSize, -}; pub const WORLD_SIZE: Vec2 = Vec2 { x: 1024, y: 1024 }; @@ -20,27 +20,17 @@ pub struct WorldSim { 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), + 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), + 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(); @@ -58,7 +48,10 @@ impl WorldSim { } pub fn get(&self, chunk_pos: Vec2) -> Option<&SimChunk> { - if chunk_pos.map2(WORLD_SIZE, |e, sz| e < sz as u32).reduce_and() { + 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 @@ -66,25 +59,27 @@ impl WorldSim { } pub fn get_base_z(&self, chunk_pos: Vec2) -> Option { - self - .get(chunk_pos) - .and_then(|_| (0..2) - .map(|i| (0..2) - .map(move |j| (i, j))) + 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())) + .map(|(i, j)| { + self.get(chunk_pos + Vec2::new(i, j)) + .map(|c| c.get_base_z()) + }) .flatten() - .fold(None, |a: Option, x| a.map(|a| a.min(x)).or(Some(x)))) + .fold(None, |a: Option, x| a.map(|a| a.min(x)).or(Some(x))) + }) } pub fn get_interpolated(&self, pos: Vec2, mut f: F) -> Option - where - T: Copy + Default + Add + Mul, - F: FnMut(&SimChunk) -> T, + where + T: Copy + Default + Add + Mul, + F: FnMut(&SimChunk) -> T, { - let pos = pos.map2(TerrainChunkSize::SIZE.into(), |e, sz: u32| e as f64 / sz as f64); + 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; @@ -101,10 +96,11 @@ impl WorldSim { 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))?); + 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); } @@ -131,7 +127,9 @@ impl WorldSim { .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 + + self.gen_ctx.small_nz.get((wposf.div(128.0)).into_array()) as f32 + * chaos.max(0.15) + * 32.0 + rock * 15.0; // Colours @@ -151,11 +149,7 @@ impl WorldSim { surface_color: Rgb::lerp( sand, // Land - Rgb::lerp( - ground, - cliff, - (alt - SEA_LEVEL - 100.0) / 150.0 - ), + Rgb::lerp(ground, cliff, (alt - SEA_LEVEL - 100.0) / 150.0), // Beach (alt - SEA_LEVEL - 2.0) / 5.0, ), @@ -194,13 +188,11 @@ impl SimChunk { fn generate(pos: Vec2, 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 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) + 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); @@ -212,15 +204,21 @@ impl SimChunk { 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), + 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), + .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)