mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
implement a new version, that uses a more ecs approach of LOD.
the old implementation needed a Vec per Element, which itself needs 24 bytes, which is a huge overhead for a single byte element. the new implementation has global Vec per region and only needs a index for the first element, which might be 8 bytes (implementation 4 bytes because of some assumptions) or none at all. It's still not ideal, because it will requiere alot of duplicate coding. Former-commit-id: 7172829c18ceabe67689487ffd269ebe62d1647b
This commit is contained in:
parent
1456497bd0
commit
a3c36f135a
@ -1,34 +1,148 @@
|
|||||||
use vek::*;
|
use vek::*;
|
||||||
|
use std::ops::Sub;
|
||||||
|
use std::ops::Add;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
For our LodStructures we need a type that covers the values from 0 - 2047 in steps of 1/32.
|
For our LodStructures we need a type that covers the values from 0 - 2047 in steps of 1/32.
|
||||||
which is 11 bits for the digits before the decimal point and 5 bits for the digits after the decimal point.
|
which is 11 bits for the digits before the decimal point and 5 bits for the digits after the decimal point.
|
||||||
Because for accessing the decimal point makes no difference we use a u16 to represent this value.
|
Because for accessing the decimal point makes no difference we use a u16 to represent this value.
|
||||||
The value needs to be shiftet to get it's "real inworld size",
|
The value needs to be shiftet to get it's "real inworld size",
|
||||||
e.g. 1 represents 1/32
|
|
||||||
32 represents 1
|
Edit: now it actually implements a value from 0 - 3*2048 - 1/32, covering over 3 regions for accessing neighbor region values
|
||||||
65535 represents 2047 + 31/32
|
|
||||||
|
-- lower neighbor
|
||||||
|
0 -> 0
|
||||||
|
1 -> 2047 31/32
|
||||||
|
-- owned
|
||||||
|
65536 -> 2048
|
||||||
|
131071 -> 4095 31/32
|
||||||
|
-- upper neighbor
|
||||||
|
196607 -> 6143 31/32
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pub type LodIndex = Vec3<u16>;
|
#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
|
||||||
|
pub struct LodIndex {
|
||||||
pub fn to_lod_i(pos: Vec3<u16>) -> LodIndex {
|
/*
|
||||||
pos.map(|x| x * 32)
|
bit 0..17 -> x
|
||||||
|
bit 18..35 -> y
|
||||||
|
bit 36..53 -> z
|
||||||
|
bit 54..63 -> unused
|
||||||
|
*/
|
||||||
|
data: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*will round*/
|
/*does not work on big endian!*/
|
||||||
pub fn to_lod_f(pos: Vec3<f32>) -> LodIndex {
|
const BIT_X_MASK: u64 = 0b0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0011_1111_1111_1111_1111;
|
||||||
pos.map(|x| (x * 32.0).round() as u16)
|
const BIT_Y_MASK: u64 = 0b0000_0000_0000_0000_0000_0000_0000_1111_1111_1111_1111_1100_0000_0000_0000_0000;
|
||||||
|
const BIT_Z_MASK: u64 = 0b0000_0000_0011_1111_1111_1111_1111_0000_0000_0000_0000_0000_0000_0000_0000_0000;
|
||||||
|
const BIT_X_MASK32: u32 = 0b0000_0000_0000_0011_1111_1111_1111_1111;
|
||||||
|
|
||||||
|
impl LodIndex {
|
||||||
|
pub fn new(data: Vec3<u32>) -> Self {
|
||||||
|
let mut index = LodIndex {data: 0};
|
||||||
|
index.set(data);
|
||||||
|
index
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(&self) -> Vec3<u32> {
|
||||||
|
let x = (self.data & BIT_X_MASK) as u32;
|
||||||
|
let y = ((self.data & BIT_Y_MASK) >> 18 ) as u32;
|
||||||
|
let z = ((self.data & BIT_Z_MASK) >> 36 ) as u32;
|
||||||
|
Vec3{x,y,z}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set(&mut self, data: Vec3<u32>) {
|
||||||
|
let x = (data.x & BIT_X_MASK32) as u64;
|
||||||
|
let y = ((data.y & BIT_X_MASK32) as u64 ) << 18;
|
||||||
|
let z = ((data.z & BIT_X_MASK32) as u64 ) << 36;
|
||||||
|
self.data = x + y + z;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn align_to_layer_id(&self, level: u8) -> LodIndex {
|
||||||
|
let xyz = self.get();
|
||||||
|
let f = two_pow_u(level) as u32;
|
||||||
|
LodIndex::new(xyz.map(|i| {
|
||||||
|
(i / f) * f
|
||||||
|
}))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_pos_i(index: LodIndex) -> Vec3<u16> {
|
|
||||||
index.map(|x| x / 32)
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::{
|
||||||
|
lodstore::index::LodIndex,
|
||||||
|
};
|
||||||
|
use vek::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn setter_getter() {
|
||||||
|
let i = LodIndex::new(Vec3::new(0,0,0));
|
||||||
|
assert_eq!(i.get(), Vec3::new(0,0,0));
|
||||||
|
|
||||||
|
let i = LodIndex::new(Vec3::new(1337,0,0));
|
||||||
|
assert_eq!(i.get(), Vec3::new(1337,0,0));
|
||||||
|
|
||||||
|
let i = LodIndex::new(Vec3::new(0,1337,0));
|
||||||
|
assert_eq!(i.get(), Vec3::new(0,1337,0));
|
||||||
|
|
||||||
|
let i = LodIndex::new(Vec3::new(0,0,1337));
|
||||||
|
assert_eq!(i.get(), Vec3::new(0,0,1337));
|
||||||
|
|
||||||
|
let i = LodIndex::new(Vec3::new(1,1,1));
|
||||||
|
assert_eq!(i.get(), Vec3::new(1,1,1));
|
||||||
|
|
||||||
|
let i = LodIndex::new(Vec3::new(262143,262143,262143));
|
||||||
|
assert_eq!(i.get(), Vec3::new(262143,262143,262143));
|
||||||
|
|
||||||
|
let i = LodIndex::new(Vec3::new(262144,262144,262144)); //overflow
|
||||||
|
assert_eq!(i.get(), Vec3::new(0,0,0));
|
||||||
|
|
||||||
|
let i = LodIndex::new(Vec3::new(42,1337,69));
|
||||||
|
assert_eq!(i.get(), Vec3::new(42,1337,69));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_pos_f(index: LodIndex) -> Vec3<f32> {
|
impl Sub for LodIndex {
|
||||||
index.map(|x| x as f32 / 32.0)
|
type Output = LodIndex;
|
||||||
|
fn sub(self, rhs: LodIndex) -> Self::Output {
|
||||||
|
LodIndex {
|
||||||
|
data: self.data - rhs.data /*fast but has overflow issues*/
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Add for LodIndex {
|
||||||
|
type Output = LodIndex;
|
||||||
|
fn add(self, rhs: LodIndex) -> Self::Output {
|
||||||
|
LodIndex {
|
||||||
|
data: self.data + rhs.data /*fast but has overflow issues*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
impl LodIndex {
|
||||||
|
pub fn new(pos: Vec3<i32>) -> Self {
|
||||||
|
Self {
|
||||||
|
data: pos.map(|x| (x * 32 + 65535) as u32),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn newf(pos: Vec3<f32>) -> Self {
|
||||||
|
Self {
|
||||||
|
data: pos.map(|x| (x * 32.0).round() as u32 + 65535),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_pos_i(&self) -> Vec3<i32> { self.data.map(|x| (x / 32 - 2048) as i32) }
|
||||||
|
|
||||||
|
pub fn to_pos_f(&self) -> Vec3<f32> {
|
||||||
|
self.data.map(|x| x as f32 / 32.0 - 2048.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub const LEVEL_LENGTH_POW_MAX: i8 = 11;
|
pub const LEVEL_LENGTH_POW_MAX: i8 = 11;
|
||||||
pub const LEVEL_LENGTH_POW_MIN: i8 = -4;
|
pub const LEVEL_LENGTH_POW_MIN: i8 = -4;
|
||||||
@ -44,4 +158,15 @@ pub const fn two_pow_u(n: u8) -> u16 {
|
|||||||
|
|
||||||
pub fn two_pow_i(n: i8) -> f32 {
|
pub fn two_pow_i(n: i8) -> f32 {
|
||||||
2.0_f32.powi(n as i32)
|
2.0_f32.powi(n as i32)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pub const fn two_pow_u(n: u8) -> u16 {
|
||||||
|
1 << n
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn relative_to_1d(index: LodIndex, relative_size: Vec3<u32>) -> usize {
|
||||||
|
let index = index.get();
|
||||||
|
(index[0] + index[1] * relative_size[0] + index[2] * relative_size[0] * relative_size[1]) as usize
|
||||||
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
273
worldsim/src/region/lod/example.rs
Normal file
273
worldsim/src/region/lod/example.rs
Normal file
@ -0,0 +1,273 @@
|
|||||||
|
use crate::lodstore::{
|
||||||
|
LodData,
|
||||||
|
LayerInfo,
|
||||||
|
LodConfig,
|
||||||
|
index::LodIndex,
|
||||||
|
};
|
||||||
|
use vek::*;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Example9 {
|
||||||
|
data: [u8; 700],
|
||||||
|
child_id: Option<u32>, // Chunk5 2^(7*3), this is valid
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Example5 {
|
||||||
|
data: [u8; 130],
|
||||||
|
child_id: Option<u32>, // see Block0 2^(12*3)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Example0 {
|
||||||
|
data: u32,
|
||||||
|
child_id: Option<u32>,// In reality 2^(16*3) SubBlock_4 should be possible, but 2^48 subblocks would kill anything anyway, so save 2 bytes here
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Example_4 {
|
||||||
|
data: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Example9 {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Example9{
|
||||||
|
data: [0; 700],
|
||||||
|
child_id: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LayerInfo for Example9 {
|
||||||
|
fn get_child_index(self: &Self) -> Option<usize> {
|
||||||
|
self.child_id.map(|n| n as usize)
|
||||||
|
}
|
||||||
|
const child_layer_id: Option<u8> = Some(9);
|
||||||
|
const layer_volume: Vec3<u32> = Vec3{x: 16, y: 16, z: 16};
|
||||||
|
const child_len: usize = 4096;//2_usize.pow(Self::child_dim*3);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LayerInfo for Example5 {
|
||||||
|
fn get_child_index(self: &Self) -> Option<usize> {
|
||||||
|
self.child_id.map(|n| n as usize)
|
||||||
|
}
|
||||||
|
const child_layer_id: Option<u8> = Some(4);
|
||||||
|
const layer_volume: Vec3<u32> = Vec3{x: 32, y: 32, z: 32};
|
||||||
|
const child_len: usize = 32768;//2_usize.pow(Self::child_dim*3);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LayerInfo for Example0 {
|
||||||
|
fn get_child_index(self: &Self) -> Option<usize> {
|
||||||
|
self.child_id.map(|n| n as usize)
|
||||||
|
}
|
||||||
|
const child_layer_id: Option<u8> = Some(0);
|
||||||
|
const layer_volume: Vec3<u32> = Vec3{x: 16, y: 16, z: 16};
|
||||||
|
const child_len: usize = 4096;//2_usize.pow(Self::child_dim*3);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LayerInfo for Example_4 {
|
||||||
|
fn get_child_index(self: &Self) -> Option<usize> { None }
|
||||||
|
const child_layer_id: Option<u8> = None;
|
||||||
|
const layer_volume: Vec3<u32> = Vec3{x: 1, y: 1, z: 1};
|
||||||
|
const child_len: usize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct ExampleLodConfig {}
|
||||||
|
|
||||||
|
impl LodConfig for ExampleLodConfig {
|
||||||
|
type L0 = Example_4;
|
||||||
|
type L1 = ();
|
||||||
|
type L2 = ();
|
||||||
|
type L3 = ();
|
||||||
|
type L4 = Example0;
|
||||||
|
type L5 = ();
|
||||||
|
type L6 = ();
|
||||||
|
type L7 = ();
|
||||||
|
type L8 = ();
|
||||||
|
type L9 = Example5;
|
||||||
|
type L10 = ();
|
||||||
|
type L11 = ();
|
||||||
|
type L12 = ();
|
||||||
|
type L13 = Example9;
|
||||||
|
type L14 = ();
|
||||||
|
type L15 = ();
|
||||||
|
|
||||||
|
const anchor_layer_id: u8 = 13;
|
||||||
|
|
||||||
|
fn setup(&mut self) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn drill_down(data: &mut LodData::<Self>, level: u8, index: usize) {
|
||||||
|
match level {
|
||||||
|
0 => {
|
||||||
|
panic!("cannot drill down further");
|
||||||
|
},
|
||||||
|
4 => {
|
||||||
|
if data.layer4[index].child_id.is_some() {return;}
|
||||||
|
let insert = data.layer0.len();
|
||||||
|
data.layer4.reserve(Example_4::child_len);
|
||||||
|
data.layer4[index].child_id = Some(insert as u32);
|
||||||
|
for i in 0..Example0::child_len {
|
||||||
|
data.layer0.push(Example_4{
|
||||||
|
data: 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
9 => {
|
||||||
|
if data.layer9[index].child_id.is_some() {return;}
|
||||||
|
let insert = data.layer4.len();
|
||||||
|
data.layer9.reserve(Example0::child_len);
|
||||||
|
data.layer9[index].child_id = Some(insert as u32);
|
||||||
|
for i in 0..Example5::child_len {
|
||||||
|
data.layer4.push(Example0{
|
||||||
|
data: 0,
|
||||||
|
child_id: None,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
13 => {
|
||||||
|
if data.layer13[index].child_id.is_some() {return;}
|
||||||
|
let insert = data.layer9.len();
|
||||||
|
data.layer13.reserve(Example9::child_len);
|
||||||
|
data.layer13[index].child_id = Some(insert as u32);
|
||||||
|
for i in 0..Example9::child_len {
|
||||||
|
data.layer9.push(Example5{
|
||||||
|
data: [0; 130],
|
||||||
|
child_id: None,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn drill_up(data: &mut LodData::<Self>, level: u8, parent_index: usize) {
|
||||||
|
match level {
|
||||||
|
0 => {
|
||||||
|
panic!("SubBlocks_4 does not have children");
|
||||||
|
},
|
||||||
|
4 => {
|
||||||
|
let delete = data.layer4[parent_index].child_id.expect("has no childs to drill up") as usize;
|
||||||
|
data.layer4[parent_index].child_id = None;
|
||||||
|
data.layer0.drain(delete..delete+Example0::child_len);
|
||||||
|
},
|
||||||
|
9 => {
|
||||||
|
let delete = data.layer9[parent_index].child_id.expect("has no childs to drill up") as usize;
|
||||||
|
data.layer9[parent_index].child_id = None;
|
||||||
|
data.layer4.drain(delete..delete+Example5::child_len);
|
||||||
|
},
|
||||||
|
13 => {
|
||||||
|
let delete = data.layer13[parent_index].child_id.expect("has no childs to drill up") as usize;
|
||||||
|
data.layer13[parent_index].child_id = None;
|
||||||
|
data.layer9.drain(delete..delete+Example9::child_len);
|
||||||
|
},
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::{
|
||||||
|
region::lod::example::ExampleLodConfig,
|
||||||
|
region::lod::example::*,
|
||||||
|
lodstore::LodData,
|
||||||
|
lodstore::index::LodIndex,
|
||||||
|
lodstore::index,
|
||||||
|
};
|
||||||
|
use std::{thread, time, mem::size_of};
|
||||||
|
use vek::*;
|
||||||
|
use rand::Rng;
|
||||||
|
use rand::ThreadRng;
|
||||||
|
|
||||||
|
fn randIndex(rng: &mut ThreadRng) -> LodIndex {
|
||||||
|
let x: u16 = rng.gen();
|
||||||
|
let y: u16 = rng.gen();
|
||||||
|
let z: u16 = rng.gen();
|
||||||
|
LodIndex::new(Vec3::new(x,y,z).map(|x| x as u32))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub type Example = LodData<ExampleLodConfig>;
|
||||||
|
|
||||||
|
fn createRegion(p_e5: f32, p_e0: f32, p_e_4: f32, p_foreign: f32) -> Example {
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
let mut result = Example::new();
|
||||||
|
let abs9 = (index::two_pow_u(15-13) as u64).pow(3);
|
||||||
|
let abs5 = (index::two_pow_u(15-9) as u64).pow(3);
|
||||||
|
let abs0 = (index::two_pow_u(15-4) as u64).pow(3);
|
||||||
|
let abs_4 = (index::two_pow_u(15) as u64).pow(3);
|
||||||
|
let act9 = (abs9 as f32 * (1.0+p_foreign) ) as u32;
|
||||||
|
let act5 = (abs5 as f32 * (p_e5*(1.0+p_foreign))) as u32;
|
||||||
|
let act0 = (abs0 as f32 * (p_e0*(1.0+p_foreign))) as u32;
|
||||||
|
let act_4 = (abs_4 as f32 * (p_e_4*(1.0+p_foreign))) as u32;
|
||||||
|
|
||||||
|
let w9 = index::two_pow_u(13) as u32;
|
||||||
|
result.layer13 = vec![Example9::new(); 8*8*8];
|
||||||
|
for x in 0..8 {
|
||||||
|
for y in 0..8 {
|
||||||
|
for z in 0..8 {
|
||||||
|
println!("{:?}", Vec3::new(x*w9,y*w9,z*w9));
|
||||||
|
println!("{:?}", LodIndex::new(Vec3::new(x*w9,y*w9,z*w9)));
|
||||||
|
result.anchor.insert(LodIndex::new(Vec3::new(x*w9,y*w9,z*w9)), (x+y*8+z*8*8) as usize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while result.layer9.len() < act5 as usize {
|
||||||
|
let index = randIndex(&mut rng);
|
||||||
|
let low = index.align_to_layer_id(9);
|
||||||
|
result.make_at_least(low,low,9);
|
||||||
|
}/*
|
||||||
|
while result.layer5.len() < act0 as usize {
|
||||||
|
let index = randIndex(&mut rng);
|
||||||
|
let low = index.align_to_layer_id(5);
|
||||||
|
result.make_at_least(low,low,5);
|
||||||
|
println!("{}", result.layer5.len());
|
||||||
|
}*//*
|
||||||
|
while result.layer0.len() < act_4 as usize {
|
||||||
|
let index = randIndex(&mut rng);
|
||||||
|
let low = index.align_to_layer_id(0);
|
||||||
|
result.make_at_least(low,low,0);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
println!("creating Region with {} 5er, {} 0er, {} -4er", act5, act0 , act_4);
|
||||||
|
println!("created Region l13: {} l9: {} l5: {} l0: {}", result.layer13.len(), result.layer9.len(), result.layer5.len(), result.layer0.len());
|
||||||
|
println!("size {} {} {}", size_of::<Example>(), size_of::<Example9>(), size_of::<Example5>());
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn reagiontest() {
|
||||||
|
let reg = createRegion(0.15, 0.01, 0.001, 0.1);
|
||||||
|
|
||||||
|
thread::sleep(time::Duration::from_secs(4));
|
||||||
|
/*
|
||||||
|
let i = LodIndex::new(Vec3::new(0,0,0));
|
||||||
|
assert_eq!(i.get(), Vec3::new(0,0,0));
|
||||||
|
|
||||||
|
let i = LodIndex::new(Vec3::new(1337,0,0));
|
||||||
|
assert_eq!(i.get(), Vec3::new(1337,0,0));
|
||||||
|
|
||||||
|
let i = LodIndex::new(Vec3::new(0,1337,0));
|
||||||
|
assert_eq!(i.get(), Vec3::new(0,1337,0));
|
||||||
|
|
||||||
|
let i = LodIndex::new(Vec3::new(0,0,1337));
|
||||||
|
assert_eq!(i.get(), Vec3::new(0,0,1337));
|
||||||
|
|
||||||
|
let i = LodIndex::new(Vec3::new(1,1,1));
|
||||||
|
assert_eq!(i.get(), Vec3::new(1,1,1));
|
||||||
|
|
||||||
|
let i = LodIndex::new(Vec3::new(262143,262143,262143));
|
||||||
|
assert_eq!(i.get(), Vec3::new(262143,262143,262143));
|
||||||
|
|
||||||
|
let i = LodIndex::new(Vec3::new(262144,262144,262144)); //overflow
|
||||||
|
assert_eq!(i.get(), Vec3::new(0,0,0));
|
||||||
|
|
||||||
|
let i = LodIndex::new(Vec3::new(42,1337,69));
|
||||||
|
assert_eq!(i.get(), Vec3::new(42,1337,69));
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
@ -1 +1,2 @@
|
|||||||
pub mod terrain;
|
pub mod terrain;
|
||||||
|
mod example;
|
@ -1,144 +1,168 @@
|
|||||||
use crate::lodstore::Layer;
|
use crate::lodstore::{
|
||||||
use crate::lodstore::LodLayer;
|
LodData,
|
||||||
|
LayerInfo,
|
||||||
|
LodConfig,
|
||||||
|
index::LodIndex,
|
||||||
|
};
|
||||||
|
use vek::*;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Terrain {
|
pub struct Region9 {
|
||||||
// 11 is max
|
precent_air: f32,
|
||||||
Unused11,
|
percent_forrest: f32,
|
||||||
Region9 { //512m this is for normal simulation if no player nearby
|
percent_lava: f32,
|
||||||
precent_air: f32,
|
percent_water: f32,
|
||||||
percent_forrest: f32,
|
child_id: Option<u32>, // Chunk5 2^(7*3), this is valid
|
||||||
percent_lava: f32,
|
|
||||||
percent_water: f32,
|
|
||||||
},
|
|
||||||
Chunk5 {//32m, same detail as region, but to not force block1 everywhere in 512 area
|
|
||||||
precent_air: f32,
|
|
||||||
percent_forrest: f32,
|
|
||||||
percent_lava: f32,
|
|
||||||
percent_water: f32,
|
|
||||||
},
|
|
||||||
Block1 {
|
|
||||||
material: u32,
|
|
||||||
},
|
|
||||||
SubBlock_4 {
|
|
||||||
material: u32,
|
|
||||||
},
|
|
||||||
// -4 is min
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Terrain {
|
#[derive(Debug, Clone)]
|
||||||
fn new() -> Self {
|
pub struct Chunk5 {
|
||||||
Terrain::Unused11
|
precent_air: f32,
|
||||||
|
percent_forrest: f32,
|
||||||
|
percent_lava: f32,
|
||||||
|
percent_water: f32,
|
||||||
|
child_id: Option<u32>, // see Block0 2^(12*3)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Block0 {
|
||||||
|
material: u32,
|
||||||
|
child_id: Option<u32>,// In reality 2^(16*3) SubBlock_4 should be possible, but 2^48 subblocks would kill anything anyway, so save 2 bytes here
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct SubBlock_4 {
|
||||||
|
material: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LayerInfo for Region9 {
|
||||||
|
fn get_child_index(self: &Self) -> Option<usize> {
|
||||||
|
self.child_id.map(|n| n as usize)
|
||||||
|
}
|
||||||
|
const child_layer_id: Option<u8> = Some(9);
|
||||||
|
const layer_volume: Vec3<u32> = Vec3{x: 16, y: 16, z: 16};
|
||||||
|
const child_len: usize = 4096;//2_usize.pow(Self::child_dim*3);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LayerInfo for Chunk5 {
|
||||||
|
fn get_child_index(self: &Self) -> Option<usize> {
|
||||||
|
self.child_id.map(|n| n as usize)
|
||||||
|
}
|
||||||
|
const child_layer_id: Option<u8> = Some(4);
|
||||||
|
const layer_volume: Vec3<u32> = Vec3{x: 32, y: 32, z: 32};
|
||||||
|
const child_len: usize = 32768;//2_usize.pow(Self::child_dim*3);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LayerInfo for Block0 {
|
||||||
|
fn get_child_index(self: &Self) -> Option<usize> {
|
||||||
|
self.child_id.map(|n| n as usize)
|
||||||
|
}
|
||||||
|
const child_layer_id: Option<u8> = Some(0);
|
||||||
|
const layer_volume: Vec3<u32> = Vec3{x: 16, y: 16, z: 16};
|
||||||
|
const child_len: usize = 4096;//2_usize.pow(Self::child_dim*3);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LayerInfo for SubBlock_4 {
|
||||||
|
fn get_child_index(self: &Self) -> Option<usize> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
const child_layer_id: Option<u8> = None;
|
||||||
|
const layer_volume: Vec3<u32> = Vec3{x: 1, y: 1, z: 1};
|
||||||
|
const child_len: usize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct TerrainLodConfig {}
|
||||||
|
|
||||||
|
impl LodConfig for TerrainLodConfig {
|
||||||
|
type L0 = SubBlock_4;
|
||||||
|
type L1 = ();
|
||||||
|
type L2 = ();
|
||||||
|
type L3 = ();
|
||||||
|
type L4 = Block0;
|
||||||
|
type L5 = ();
|
||||||
|
type L6 = ();
|
||||||
|
type L7 = ();
|
||||||
|
type L8 = ();
|
||||||
|
type L9 = Chunk5;
|
||||||
|
type L10 = ();
|
||||||
|
type L11 = ();
|
||||||
|
type L12 = ();
|
||||||
|
type L13 = Region9;
|
||||||
|
type L14 = ();
|
||||||
|
type L15 = ();
|
||||||
|
|
||||||
|
const anchor_layer_id: u8 = 13;
|
||||||
|
|
||||||
|
fn setup(&mut self) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn drill_down(data: &mut LodData::<Self>, level: u8, index: usize) {
|
||||||
|
match level {
|
||||||
|
0 => {
|
||||||
|
panic!("cannot drill down further");
|
||||||
|
},
|
||||||
|
4 => {
|
||||||
|
let insert = data.layer0.len();
|
||||||
|
data.layer4[index].child_id = Some(insert as u32);
|
||||||
|
for i in 0..Block0::child_len {
|
||||||
|
data.layer0[i+insert] = SubBlock_4{
|
||||||
|
material: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
9 => {
|
||||||
|
let insert = data.layer4.len();
|
||||||
|
data.layer9[index].child_id = Some(insert as u32);
|
||||||
|
for i in 0..Chunk5::child_len {
|
||||||
|
data.layer4[i+insert] = Block0{
|
||||||
|
material: 0,
|
||||||
|
child_id: None,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
13 => {
|
||||||
|
let insert = data.layer9.len();
|
||||||
|
data.layer13[index].child_id = Some(insert as u32);
|
||||||
|
for i in 0..Region9::child_len {
|
||||||
|
data.layer9[i+insert] = Chunk5{
|
||||||
|
precent_air: 0.2,
|
||||||
|
percent_forrest: 0.3,
|
||||||
|
percent_lava: 0.4,
|
||||||
|
percent_water: 0.1,
|
||||||
|
child_id: None,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn drill_up(data: &mut LodData::<Self>, level: u8, parent_index: usize) {
|
||||||
|
match level {
|
||||||
|
0 => {
|
||||||
|
panic!("SubBlocks_4 does not have children");
|
||||||
|
},
|
||||||
|
4 => {
|
||||||
|
let delete = data.layer4[parent_index].child_id.expect("has no childs to drill up") as usize;
|
||||||
|
data.layer4[parent_index].child_id = None;
|
||||||
|
data.layer0.drain(delete..delete+Block0::child_len);
|
||||||
|
},
|
||||||
|
9 => {
|
||||||
|
let delete = data.layer9[parent_index].child_id.expect("has no childs to drill up") as usize;
|
||||||
|
data.layer9[parent_index].child_id = None;
|
||||||
|
data.layer4.drain(delete..delete+Chunk5::child_len);
|
||||||
|
},
|
||||||
|
13 => {
|
||||||
|
let delete = data.layer13[parent_index].child_id.expect("has no childs to drill up") as usize;
|
||||||
|
data.layer13[parent_index].child_id = None;
|
||||||
|
data.layer9.drain(delete..delete+Region9::child_len);
|
||||||
|
},
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const LAYER5: i8 = 11;
|
pub type Terrain = LodData<TerrainLodConfig>;
|
||||||
const LAYER4: i8 = 9;
|
|
||||||
const LAYER3: i8 = 5;
|
|
||||||
const LAYER2: i8 = 0;
|
|
||||||
const LAYER1: i8 = -4;
|
|
||||||
|
|
||||||
|
|
||||||
impl Layer for Terrain {
|
|
||||||
fn new() -> LodLayer<Terrain> {
|
|
||||||
let mut n = LodLayer::<Terrain>::new_data(Terrain::Unused11);
|
|
||||||
Self::drill_down(&mut n);
|
|
||||||
n
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_level(layer: &LodLayer<Self>) -> i8 {
|
|
||||||
match &layer.data {
|
|
||||||
Terrain::Unused11 => LAYER5,
|
|
||||||
Terrain::Region9{..} => LAYER4,
|
|
||||||
Terrain::Chunk5{..} => LAYER3,
|
|
||||||
Terrain::Block1{..} => LAYER2,
|
|
||||||
Terrain::SubBlock_4{..} => -LAYER1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_lower_level(layer: &LodLayer<Self>) -> Option<i8> {
|
|
||||||
match &layer.data {
|
|
||||||
Terrain::Unused11 => Some(LAYER4),
|
|
||||||
Terrain::Region9{..} => Some(LAYER3),
|
|
||||||
Terrain::Chunk5{..} => Some(LAYER2),
|
|
||||||
Terrain::Block1{..} => Some(LAYER1),
|
|
||||||
Terrain::SubBlock_4{..} => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn drill_down(layer: &mut LodLayer<Terrain>) {
|
|
||||||
match &layer.data {
|
|
||||||
Terrain::Unused11 => {
|
|
||||||
let n = LodLayer::new_data(Terrain::Region9{
|
|
||||||
precent_air: 1.0,
|
|
||||||
percent_forrest: 0.0,
|
|
||||||
percent_lava: 0.0,
|
|
||||||
percent_water: 0.0,
|
|
||||||
});
|
|
||||||
layer.childs = vec![n; 2_usize.pow((LAYER5-LAYER4) as u32 *3)];
|
|
||||||
},
|
|
||||||
Terrain::Region9{..} => {
|
|
||||||
let n = LodLayer::new_data(Terrain::Chunk5{
|
|
||||||
precent_air: 1.0,
|
|
||||||
percent_forrest: 0.0,
|
|
||||||
percent_lava: 0.0,
|
|
||||||
percent_water: 0.0,
|
|
||||||
});
|
|
||||||
layer.childs = vec![n; 2_usize.pow((LAYER4-LAYER3) as u32 *3)];
|
|
||||||
},
|
|
||||||
Terrain::Chunk5{..} => {
|
|
||||||
let n = LodLayer::new_data( Terrain::Block1{
|
|
||||||
material: 10,
|
|
||||||
});
|
|
||||||
layer.childs = vec![n; 2_usize.pow((LAYER3-LAYER2) as u32 *3)];
|
|
||||||
},
|
|
||||||
Terrain::Block1{..} => {
|
|
||||||
let n = LodLayer::new_data( Terrain::SubBlock_4{
|
|
||||||
material: 10,
|
|
||||||
});
|
|
||||||
layer.childs = vec![n; 2_usize.pow((LAYER2-LAYER1) as u32 *3)];
|
|
||||||
},
|
|
||||||
Terrain::SubBlock_4{..} => {
|
|
||||||
panic!("cannot drillDown further")
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn drill_up(parent: &mut LodLayer<Terrain>) {
|
|
||||||
match &parent.data {
|
|
||||||
Terrain::Unused11 => {
|
|
||||||
panic!("cannot drillUp further")
|
|
||||||
},
|
|
||||||
Terrain::Region9{..} => {
|
|
||||||
//recalculate values here
|
|
||||||
parent.data = Terrain::Region9{
|
|
||||||
precent_air: 1.0,
|
|
||||||
percent_forrest: 0.0,
|
|
||||||
percent_lava: 0.0,
|
|
||||||
percent_water: 0.0,
|
|
||||||
};
|
|
||||||
parent.childs = vec![];
|
|
||||||
},
|
|
||||||
Terrain::Chunk5{..} => {
|
|
||||||
parent.data = Terrain::Chunk5{
|
|
||||||
precent_air: 1.0,
|
|
||||||
percent_forrest: 0.0,
|
|
||||||
percent_lava: 0.0,
|
|
||||||
percent_water: 0.0,
|
|
||||||
};
|
|
||||||
parent.childs = vec![];
|
|
||||||
},
|
|
||||||
Terrain::Block1{..} => {
|
|
||||||
parent.data = Terrain::Block1{
|
|
||||||
material: 10,
|
|
||||||
};
|
|
||||||
parent.childs = vec![];
|
|
||||||
},
|
|
||||||
Terrain::SubBlock_4{..} => {
|
|
||||||
parent.data = Terrain::SubBlock_4{
|
|
||||||
material: 10,
|
|
||||||
};
|
|
||||||
parent.childs = vec![];
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,8 +5,6 @@ use std::sync::Arc;
|
|||||||
use crate::{
|
use crate::{
|
||||||
regionmanager::meta::RegionId,
|
regionmanager::meta::RegionId,
|
||||||
job::JobManager,
|
job::JobManager,
|
||||||
lodstore::LodLayer,
|
|
||||||
lodstore::Layer,
|
|
||||||
};
|
};
|
||||||
use lod::terrain::Terrain;
|
use lod::terrain::Terrain;
|
||||||
|
|
||||||
@ -15,11 +13,11 @@ pub struct Region {
|
|||||||
id: RegionId,
|
id: RegionId,
|
||||||
jobmanager: Arc<JobManager>,
|
jobmanager: Arc<JobManager>,
|
||||||
|
|
||||||
pub block: LodLayer<Terrain>,
|
pub block: Terrain,
|
||||||
temp: LodLayer<Terrain>,
|
temp: Terrain,
|
||||||
light: LodLayer<Terrain>,
|
light: Terrain,
|
||||||
evil: LodLayer<Terrain>,
|
evil: Terrain,
|
||||||
civ: LodLayer<Terrain>,
|
civ: Terrain,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Region {
|
impl Region {
|
||||||
@ -36,6 +34,39 @@ impl Region {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn rasterize(region: &Region) -> Vec<u64> {
|
||||||
|
let mut res = Vec::new();
|
||||||
|
|
||||||
|
// iterate over all Region9 / chunk5 / Block0 / subBlock that dont have children in RECT XYZ
|
||||||
|
//region.block
|
||||||
|
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
fn plant_trees(region: &Region) -> Vec<u64> {
|
||||||
|
let mut res = Vec::new();
|
||||||
|
|
||||||
|
// iterate over all Region9 / chunk5 / Block0 / subBlock that dont have children in RECT XYZ
|
||||||
|
// acces blocks around
|
||||||
|
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
fn corrosion(region: &Region) -> Vec<u64> {
|
||||||
|
let mut res = Vec::new();
|
||||||
|
|
||||||
|
// iterate over all Region9 / chunk5 / Block0 / subBlock that dont have children in RECT XYZ
|
||||||
|
// access neighbours
|
||||||
|
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
pub type aaa = LodLayer<e::Terain>;
|
pub type aaa = LodLayer<e::Terain>;
|
||||||
@ -48,6 +79,7 @@ fn example() {
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -84,4 +116,6 @@ mod tests {
|
|||||||
let mut r = Region::new((0,0), Arc::new(JobManager::new()));
|
let mut r = Region::new((0,0), Arc::new(JobManager::new()));
|
||||||
r.block.make_at_least(Vec3::new(0,0,0), Vec3::new(65535,65535,65535), -4);
|
r.block.make_at_least(Vec3::new(0,0,0), Vec3::new(65535,65535,65535), -4);
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*/
|
@ -71,9 +71,11 @@ impl Server {
|
|||||||
println!("new server found");
|
println!("new server found");
|
||||||
},
|
},
|
||||||
RegionManagerMsg::CreateRegion{region_id} => {
|
RegionManagerMsg::CreateRegion{region_id} => {
|
||||||
|
/*
|
||||||
let mut r = Region::new(region_id, self.jobmanager.clone());
|
let mut r = Region::new(region_id, self.jobmanager.clone());
|
||||||
r.block.make_at_least(Vec3::new(0,0,0), Vec3::new(65535,65535,65535), 9);
|
r.block.make_at_least(Vec3::new(0,0,0), Vec3::new(65535,65535,65535), 9);
|
||||||
self.region.insert(region_id, r);
|
self.region.insert(region_id, r);
|
||||||
|
*/
|
||||||
println!("create region");
|
println!("create region");
|
||||||
},
|
},
|
||||||
RegionManagerMsg::TakeOverRegionFrom{region_id, server_id} => {
|
RegionManagerMsg::TakeOverRegionFrom{region_id, server_id} => {
|
||||||
|
Loading…
Reference in New Issue
Block a user