mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Optimised sub-terrain chonk storage, fixed hash chunk bug, altered terrain base
This commit is contained in:
parent
910eccee82
commit
92f2d36b0c
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -2569,6 +2569,7 @@ dependencies = [
|
|||||||
name = "veloren-client"
|
name = "veloren-client"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"specs 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"specs 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"vek 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"vek 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -7,6 +7,7 @@ edition = "2018"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
common = { package = "veloren-common", path = "../common" }
|
common = { package = "veloren-common", path = "../common" }
|
||||||
|
|
||||||
|
log = "0.4"
|
||||||
specs = "0.14"
|
specs = "0.14"
|
||||||
vek = "0.9"
|
vek = "0.9"
|
||||||
threadpool = "1.7"
|
threadpool = "1.7"
|
||||||
|
@ -12,18 +12,21 @@ use common::{
|
|||||||
msg::{ClientMsg, ClientState, ServerInfo, ServerMsg},
|
msg::{ClientMsg, ClientState, ServerInfo, ServerMsg},
|
||||||
net::PostBox,
|
net::PostBox,
|
||||||
state::State,
|
state::State,
|
||||||
|
terrain::chonk::ChonkMetrics,
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
net::SocketAddr,
|
net::SocketAddr,
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
use threadpool::ThreadPool;
|
use threadpool::ThreadPool;
|
||||||
|
use log::info;
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
const SERVER_TIMEOUT: Duration = Duration::from_secs(20);
|
const SERVER_TIMEOUT: Duration = Duration::from_secs(20);
|
||||||
|
|
||||||
|
const DEBUG_METRICS: bool = true;
|
||||||
|
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
Chat(String),
|
Chat(String),
|
||||||
Disconnect,
|
Disconnect,
|
||||||
@ -308,6 +311,15 @@ impl Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Output debug metrics
|
||||||
|
if DEBUG_METRICS && self.tick % 600 == 0 {
|
||||||
|
let metrics = self.state
|
||||||
|
.terrain()
|
||||||
|
.iter()
|
||||||
|
.fold(ChonkMetrics::default(), |a, (_, c)| a + c.get_metrics());
|
||||||
|
info!("{:?}", metrics);
|
||||||
|
}
|
||||||
|
|
||||||
// 7) Finish the tick, pass control back to the frontend.
|
// 7) Finish the tick, pass control back to the frontend.
|
||||||
|
|
||||||
self.tick += 1;
|
self.tick += 1;
|
||||||
|
@ -4,7 +4,10 @@ use crate::{
|
|||||||
volumes::chunk::{Chunk, ChunkErr},
|
volumes::chunk::{Chunk, ChunkErr},
|
||||||
};
|
};
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use std::collections::HashMap;
|
use std::{
|
||||||
|
ops::Add,
|
||||||
|
collections::HashMap,
|
||||||
|
};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -43,6 +46,24 @@ impl Chonk {
|
|||||||
self.z_offset + (self.sub_chunks.len() as u32 * SUB_CHUNK_HEIGHT) as i32
|
self.z_offset + (self.sub_chunks.len() as u32 * SUB_CHUNK_HEIGHT) as i32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_metrics(&self) -> ChonkMetrics {
|
||||||
|
ChonkMetrics {
|
||||||
|
chonks: 1,
|
||||||
|
homogeneous: self.sub_chunks
|
||||||
|
.iter()
|
||||||
|
.filter(|s| match s { SubChunk::Homogeneous(_) => true, _ => false })
|
||||||
|
.count(),
|
||||||
|
hash: self.sub_chunks
|
||||||
|
.iter()
|
||||||
|
.filter(|s| match s { SubChunk::Hash(_, _) => true, _ => false })
|
||||||
|
.count(),
|
||||||
|
heterogeneous: self.sub_chunks
|
||||||
|
.iter()
|
||||||
|
.filter(|s| match s { SubChunk::Heterogeneous(_) => true, _ => false })
|
||||||
|
.count(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn sub_chunk_idx(&self, z: i32) -> usize {
|
fn sub_chunk_idx(&self, z: i32) -> usize {
|
||||||
((z - self.z_offset) as u32 / SUB_CHUNK_HEIGHT as u32) as usize
|
((z - self.z_offset) as u32 / SUB_CHUNK_HEIGHT as u32) as usize
|
||||||
}
|
}
|
||||||
@ -75,7 +96,7 @@ impl ReadVol for Chonk {
|
|||||||
- Vec3::unit_z()
|
- 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);
|
||||||
|
|
||||||
Ok(map.get(&rpos).unwrap_or(cblock))
|
Ok(map.get(&rpos.map(|e| e as u8)).unwrap_or(cblock))
|
||||||
}
|
}
|
||||||
SubChunk::Heterogeneous(chunk) => {
|
SubChunk::Heterogeneous(chunk) => {
|
||||||
let rpos = pos
|
let rpos = pos
|
||||||
@ -92,59 +113,61 @@ impl ReadVol for Chonk {
|
|||||||
impl WriteVol for Chonk {
|
impl WriteVol for Chonk {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn set(&mut self, pos: Vec3<i32>, block: Block) -> Result<(), ChonkError> {
|
fn set(&mut self, pos: Vec3<i32>, block: Block) -> Result<(), ChonkError> {
|
||||||
if pos.z < self.z_offset {
|
while pos.z < self.z_offset {
|
||||||
Err(ChonkError::OutOfBounds)
|
self.sub_chunks.insert(0, SubChunk::Homogeneous(self.below));
|
||||||
} else {
|
self.z_offset -= SUB_CHUNK_HEIGHT as i32;
|
||||||
let sub_chunk_idx = self.sub_chunk_idx(pos.z);
|
}
|
||||||
|
|
||||||
while self.sub_chunks.get(sub_chunk_idx).is_none() {
|
let sub_chunk_idx = self.sub_chunk_idx(pos.z);
|
||||||
self.sub_chunks.push(SubChunk::Homogeneous(self.above));
|
|
||||||
}
|
while self.sub_chunks.get(sub_chunk_idx).is_none() {
|
||||||
|
self.sub_chunks.push(SubChunk::Homogeneous(self.above));
|
||||||
let rpos = pos
|
}
|
||||||
- Vec3::unit_z() * (self.z_offset + sub_chunk_idx as i32 * SUB_CHUNK_HEIGHT as i32);
|
|
||||||
|
let rpos = pos
|
||||||
match &mut self.sub_chunks[sub_chunk_idx] {
|
- Vec3::unit_z() * (self.z_offset + sub_chunk_idx as i32 * SUB_CHUNK_HEIGHT as i32);
|
||||||
// Can't fail
|
|
||||||
SubChunk::Homogeneous(cblock) if *cblock == block => Ok(()),
|
match &mut self.sub_chunks[sub_chunk_idx] {
|
||||||
SubChunk::Homogeneous(cblock) => {
|
// Can't fail
|
||||||
let mut map = HashMap::new();
|
SubChunk::Homogeneous(cblock) if block == *cblock => Ok(()),
|
||||||
map.insert(rpos, block);
|
SubChunk::Homogeneous(cblock) => {
|
||||||
|
let mut map = HashMap::new();
|
||||||
self.sub_chunks[sub_chunk_idx] = SubChunk::Hash(*cblock, map);
|
map.insert(rpos.map(|e| e as u8), block);
|
||||||
Ok(())
|
|
||||||
}
|
self.sub_chunks[sub_chunk_idx] = SubChunk::Hash(*cblock, map);
|
||||||
SubChunk::Hash(cblock, map) if map.len() < 1024 => {
|
Ok(())
|
||||||
map.insert(rpos, block);
|
},
|
||||||
Ok(())
|
SubChunk::Hash(cblock, map) if block == *cblock => Ok(()),
|
||||||
}
|
SubChunk::Hash(cblock, map) if map.len() < 4096 => {
|
||||||
SubChunk::Hash(cblock, map) => {
|
map.insert(rpos.map(|e| e as u8), block);
|
||||||
let mut new_chunk = Chunk::filled(*cblock, ());
|
Ok(())
|
||||||
new_chunk.set(rpos, block).unwrap(); // Can't fail (I hope)
|
},
|
||||||
|
SubChunk::Hash(cblock, map) => {
|
||||||
for (map_pos, map_block) in map {
|
let mut new_chunk = Chunk::filled(*cblock, ());
|
||||||
new_chunk.set(*map_pos, *map_block).unwrap(); // Can't fail (I hope!)
|
new_chunk.set(rpos, block).unwrap(); // Can't fail (I hope)
|
||||||
}
|
|
||||||
|
for (map_pos, map_block) in map {
|
||||||
self.sub_chunks[sub_chunk_idx] = SubChunk::Heterogeneous(new_chunk);
|
new_chunk.set(map_pos.map(|e| e as i32), *map_block).unwrap(); // Can't fail (I hope!)
|
||||||
Ok(())
|
}
|
||||||
}
|
|
||||||
|
self.sub_chunks[sub_chunk_idx] = SubChunk::Heterogeneous(new_chunk);
|
||||||
/*
|
Ok(())
|
||||||
SubChunk::Homogeneous(cblock) => {
|
},
|
||||||
let mut new_chunk = Chunk::filled(*cblock, ());
|
|
||||||
|
/*
|
||||||
new_chunk.set(rpos, block).unwrap(); // Can't fail (I hope!)
|
SubChunk::Homogeneous(cblock) => {
|
||||||
|
let mut new_chunk = Chunk::filled(*cblock, ());
|
||||||
self.sub_chunks[sub_chunk_idx] = SubChunk::Heterogeneous(new_chunk);
|
|
||||||
Ok(())
|
new_chunk.set(rpos, block).unwrap(); // Can't fail (I hope!)
|
||||||
}
|
|
||||||
*/
|
self.sub_chunks[sub_chunk_idx] = SubChunk::Heterogeneous(new_chunk);
|
||||||
SubChunk::Heterogeneous(chunk) => chunk
|
Ok(())
|
||||||
.set(rpos, block)
|
|
||||||
.map_err(|err| ChonkError::ChunkError(err)),
|
|
||||||
//_ => unimplemented!(),
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
SubChunk::Heterogeneous(chunk) => chunk
|
||||||
|
.set(rpos, block)
|
||||||
|
.map_err(|err| ChonkError::ChunkError(err)),
|
||||||
|
//_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -152,7 +175,7 @@ impl WriteVol for Chonk {
|
|||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub enum SubChunk {
|
pub enum SubChunk {
|
||||||
Homogeneous(Block),
|
Homogeneous(Block),
|
||||||
Hash(Block, HashMap<Vec3<i32>, Block>),
|
Hash(Block, HashMap<Vec3<u8>, Block>),
|
||||||
Heterogeneous(Chunk<Block, TerrainChunkSize, ()>),
|
Heterogeneous(Chunk<Block, TerrainChunkSize, ()>),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,3 +184,35 @@ impl SubChunk {
|
|||||||
SubChunk::Homogeneous(block)
|
SubChunk::Homogeneous(block)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ChonkMetrics {
|
||||||
|
chonks: usize,
|
||||||
|
homogeneous: usize,
|
||||||
|
hash: usize,
|
||||||
|
heterogeneous: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ChonkMetrics {
|
||||||
|
fn default() -> Self {
|
||||||
|
ChonkMetrics {
|
||||||
|
chonks: 0,
|
||||||
|
homogeneous: 0,
|
||||||
|
hash: 0,
|
||||||
|
heterogeneous: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Add for ChonkMetrics {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn add(self, other: Self::Output) -> Self {
|
||||||
|
Self::Output {
|
||||||
|
chonks: self.chonks + other.chonks,
|
||||||
|
homogeneous: self.homogeneous + other.homogeneous,
|
||||||
|
hash: self.hash + other.hash,
|
||||||
|
heterogeneous: self.heterogeneous + other.heterogeneous,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -151,8 +151,8 @@ impl Terrain {
|
|||||||
.fold(i32::MIN, |max, (_, chunk)| chunk.get_z_max().max(max));
|
.fold(i32::MIN, |max, (_, chunk)| chunk.get_z_max().max(max));
|
||||||
|
|
||||||
let aabb = Aabb {
|
let aabb = Aabb {
|
||||||
min: Vec3::from(aabr.min) + Vec3::unit_z() * z_min,
|
min: Vec3::from(aabr.min) + Vec3::unit_z() * (z_min - 1),
|
||||||
max: Vec3::from(aabr.max) + Vec3::unit_z() * z_max,
|
max: Vec3::from(aabr.max) + Vec3::unit_z() * (z_max + 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Clone various things so that they can be moved into the thread.
|
// Clone various things so that they can be moved into the thread.
|
||||||
|
@ -49,7 +49,10 @@ impl World {
|
|||||||
|
|
||||||
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)) {
|
let base_z = match self.sim
|
||||||
|
.get(chunk_pos.map(|e| e as u32))
|
||||||
|
.map(|chunk| chunk.get_base_z())
|
||||||
|
{
|
||||||
Some(base_z) => base_z as i32,
|
Some(base_z) => base_z as i32,
|
||||||
None => return TerrainChunk::new(0, water, air, TerrainChunkMeta::void()),
|
None => return TerrainChunk::new(0, water, air, TerrainChunkMeta::void()),
|
||||||
};
|
};
|
||||||
@ -64,12 +67,17 @@ impl World {
|
|||||||
+ Vec3::from(chunk_pos) * TerrainChunkSize::SIZE.map(|e| e as i32);
|
+ Vec3::from(chunk_pos) * TerrainChunkSize::SIZE.map(|e| e as i32);
|
||||||
let wposf2d = wpos2d.map(|e| e as f64);
|
let wposf2d = wpos2d.map(|e| e as f64);
|
||||||
|
|
||||||
|
let min_z = self
|
||||||
|
.sim
|
||||||
|
.get_interpolated(wpos2d, |chunk| chunk.get_min_z())
|
||||||
|
.unwrap_or(0.0) as i32;
|
||||||
|
|
||||||
let max_z = self
|
let max_z = self
|
||||||
.sim
|
.sim
|
||||||
.get_interpolated(wpos2d, |chunk| chunk.get_max_z())
|
.get_interpolated(wpos2d, |chunk| chunk.get_max_z())
|
||||||
.unwrap_or(0.0) as i32;
|
.unwrap_or(0.0) as i32;
|
||||||
|
|
||||||
for z in base_z..max_z.max(sim::SEA_LEVEL as i32) {
|
for z in min_z..max_z {
|
||||||
let lpos = Vec3::new(x, y, z);
|
let lpos = Vec3::new(x, y, z);
|
||||||
let wpos =
|
let wpos =
|
||||||
lpos + Vec3::from(chunk_pos) * TerrainChunkSize::SIZE.map(|e| e as i32);
|
lpos + Vec3::from(chunk_pos) * TerrainChunkSize::SIZE.map(|e| e as i32);
|
||||||
|
@ -746,10 +746,14 @@ impl SimChunk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_base_z(&self) -> f32 {
|
pub fn get_base_z(&self) -> f32 {
|
||||||
|
self.alt - 8.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_min_z(&self) -> f32 {
|
||||||
self.alt - Z_TOLERANCE.0 * (self.chaos + 0.3)
|
self.alt - Z_TOLERANCE.0 * (self.chaos + 0.3)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_max_z(&self) -> f32 {
|
pub fn get_max_z(&self) -> f32 {
|
||||||
self.alt + Z_TOLERANCE.1
|
(self.alt + Z_TOLERANCE.1).max(SEA_LEVEL)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user