From d5dca4f6e874bf40ea02c422fefef6e9ffc592ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=A4rtens?= Date: Wed, 24 Jul 2019 15:47:15 +0200 Subject: [PATCH] work on a deltas, to store the diff while working on data. this state does not work, because i tried to iplement delta in a trait type. however this is not necessary, i will revert this. Just keep this commit for historical reasons - it wont build. --- worldsim/src/lodstore/area.rs | 22 ++ worldsim/src/lodstore/data.rs | 433 ++++++++++++++++++++++++++ worldsim/src/lodstore/delta.rs | 97 ++++++ worldsim/src/lodstore/index.rs | 101 +++--- worldsim/src/lodstore/mod.rs | 473 +---------------------------- worldsim/src/region/lod/example.rs | 97 +++--- worldsim/src/region/lod/npcs.rs | 190 ++++++++++++ worldsim/src/region/lod/terrain.rs | 70 +++-- worldsim/src/server/mod.rs | 1 - 9 files changed, 889 insertions(+), 595 deletions(-) create mode 100644 worldsim/src/lodstore/area.rs create mode 100644 worldsim/src/lodstore/data.rs create mode 100644 worldsim/src/lodstore/delta.rs create mode 100644 worldsim/src/region/lod/npcs.rs diff --git a/worldsim/src/lodstore/area.rs b/worldsim/src/lodstore/area.rs new file mode 100644 index 0000000000..f941248400 --- /dev/null +++ b/worldsim/src/lodstore/area.rs @@ -0,0 +1,22 @@ +use super::index::{ + LodIndex, +}; + +/* + A LodArea is the area between 2 LodIndex +*/ + +#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)] +pub struct LodArea { + pub lower: LodIndex, + pub upper: LodIndex, +} + +impl LodArea { + pub fn new(lower: LodIndex, upper: LodIndex) -> Self { + LodArea { + lower, + upper, + } + } +} \ No newline at end of file diff --git a/worldsim/src/lodstore/data.rs b/worldsim/src/lodstore/data.rs new file mode 100644 index 0000000000..6e8798e07e --- /dev/null +++ b/worldsim/src/lodstore/data.rs @@ -0,0 +1,433 @@ +use std::u32; +use std::collections::HashMap; +use vek::*; +use super::index::{ + self, + LodIndex, + AbsIndex, + relative_to_1d, + two_pow_u, +}; +use super::area::{ + LodArea, +}; +use super::delta::{ + LodDelta, +}; + +/* +LOD Data contains different Entries in different Vecs, every entry has a "pointer" to it's child start. +This is the structure to store a region and all subscribed information +*/ + +pub trait LodIntoOptionUsize: Copy { + fn is_some(self) -> bool; + fn into_usize(self) -> usize; +} + +pub trait LodConfig { + type L0: Clone; // 2^-4 + type L1: Clone; + type L2: Clone; + type L3: Clone; + type L4: Clone; // 2^0 + type L5: Clone; + type L6: Clone; + type L7: Clone; + type L8: Clone; + type L9: Clone; + type L10: Clone; + type L11: Clone; + type L12: Clone; + type L13: Clone; + type L14: Clone; + type L15: Clone; // 2^11 + + type I0: LodIntoOptionUsize; + type I1: LodIntoOptionUsize; + type I2: LodIntoOptionUsize; + type I3: LodIntoOptionUsize; + type I4: LodIntoOptionUsize; + type I5: LodIntoOptionUsize; + type I6: LodIntoOptionUsize; + type I7: LodIntoOptionUsize; + type I8: LodIntoOptionUsize; + type I9: LodIntoOptionUsize; + type I10: LodIntoOptionUsize; + type I11: LodIntoOptionUsize; + type I12: LodIntoOptionUsize; + type I13: LodIntoOptionUsize; + type I14: LodIntoOptionUsize; + type I15: LodIntoOptionUsize; + + type Delta: LodDelta; + type Additional; + + /* + The Anchor marks the entrypoint for the LodStore, every access is done by HashLookup > VecAccess > VecAccess > VecAccess > ... + The first lookup is done in a HashMap, because this way we don't need to create alot of data + //TODO: Evaluate if we should drop the anchor design and make L15 as anchor, but on the other hand allow empty data where we have index data + Choose the anchor_layer wisely in order to minimize CPU and MEMORY consumption + */ + const anchor_layer_id: u8; + + const layer_volume: [Vec3; 16]; // number of elements on this layer as Vec3 (not on child layer!) + const child_layer_id: [Option; 16]; // layer below this one + const layer_len: [usize; 16] = [ // optimisation for layer_volume, total no of elements as usize + (Self::layer_volume[0].x * Self::layer_volume[0].y * Self::layer_volume[0].z) as usize, + (Self::layer_volume[1].x * Self::layer_volume[1].y * Self::layer_volume[1].z) as usize, + (Self::layer_volume[2].x * Self::layer_volume[2].y * Self::layer_volume[2].z) as usize, + (Self::layer_volume[3].x * Self::layer_volume[3].y * Self::layer_volume[3].z) as usize, + (Self::layer_volume[4].x * Self::layer_volume[4].y * Self::layer_volume[4].z) as usize, + (Self::layer_volume[5].x * Self::layer_volume[5].y * Self::layer_volume[5].z) as usize, + (Self::layer_volume[6].x * Self::layer_volume[6].y * Self::layer_volume[6].z) as usize, + (Self::layer_volume[7].x * Self::layer_volume[7].y * Self::layer_volume[7].z) as usize, + (Self::layer_volume[8].x * Self::layer_volume[8].y * Self::layer_volume[8].z) as usize, + (Self::layer_volume[9].x * Self::layer_volume[9].y * Self::layer_volume[9].z) as usize, + (Self::layer_volume[10].x * Self::layer_volume[10].y * Self::layer_volume[10].z) as usize, + (Self::layer_volume[11].x * Self::layer_volume[11].y * Self::layer_volume[11].z) as usize, + (Self::layer_volume[12].x * Self::layer_volume[12].y * Self::layer_volume[12].z) as usize, + (Self::layer_volume[13].x * Self::layer_volume[13].y * Self::layer_volume[13].z) as usize, + (Self::layer_volume[14].x * Self::layer_volume[14].y * Self::layer_volume[14].z) as usize, + (Self::layer_volume[15].x * Self::layer_volume[15].y * Self::layer_volume[15].z) as usize, + ]; + + fn setup(&mut self); + fn drill_down(data: &mut LodData::, abs: AbsIndex, delta: &mut Option) where Self: Sized; + fn drill_up(data: &mut LodData::, parent_abs: AbsIndex, delta: &mut Option) where Self: Sized; +} + +#[derive(Debug, Clone)] +pub struct LodData { + pub layer0: Vec, // 1/16 + pub layer1: Vec, // 1/8 + pub layer2: Vec, // 1/4 + pub layer3: Vec, // 1/2 + pub layer4: Vec, // 1 + pub layer5: Vec, // 2 + pub layer6: Vec, // 4 + pub layer7: Vec, // 8 + pub layer8: Vec, // 16 + pub layer9: Vec, // 32 + pub layer10: Vec, // 64 + pub layer11: Vec, // 128 + pub layer12: Vec, // 256 + pub layer13: Vec, // 512 + pub layer14: Vec, // 1024 + pub layer15: Vec, // 2048 + + pub child0: Vec, + pub child1: Vec, + pub child2: Vec, + pub child3: Vec, + pub child4: Vec, + pub child5: Vec, + pub child6: Vec, + pub child7: Vec, + pub child8: Vec, + pub child9: Vec, + pub child10: Vec, + pub child11: Vec, + pub child12: Vec, + pub child13: Vec, + pub child14: Vec, + pub child15: Vec, + + pub anchor: HashMap, + pub additional: Option, +} + +impl LodData +{ + pub fn new() -> Self { + Self { + layer0: Vec::new(), + layer1: Vec::new(), + layer2: Vec::new(), + layer3: Vec::new(), + layer4: Vec::new(), + layer5: Vec::new(), + layer6: Vec::new(), + layer7: Vec::new(), + layer8: Vec::new(), + layer9: Vec::new(), + layer10: Vec::new(), + layer11: Vec::new(), + layer12: Vec::new(), + layer13: Vec::new(), + layer14: Vec::new(), + layer15: Vec::new(), + child0: Vec::new(), + child1: Vec::new(), + child2: Vec::new(), + child3: Vec::new(), + child4: Vec::new(), + child5: Vec::new(), + child6: Vec::new(), + child7: Vec::new(), + child8: Vec::new(), + child9: Vec::new(), + child10: Vec::new(), + child11: Vec::new(), + child12: Vec::new(), + child13: Vec::new(), + child14: Vec::new(), + child15: Vec::new(), + anchor: HashMap::new(), + additional: None, + } + } + + // dynamically dispatches the get_child_index, this is most prob the bottleneck function. + // evaluate the performacne impact!!! + fn int_get_child_index(&self, abs: AbsIndex) -> usize { + match abs.layer { + 0 => self.child0[abs.index].into_usize(), + 1 => self.child1[abs.index].into_usize(), + 2 => self.child2[abs.index].into_usize(), + 3 => self.child3[abs.index].into_usize(), + 4 => self.child4[abs.index].into_usize(), + 5 => self.child5[abs.index].into_usize(), + 6 => self.child6[abs.index].into_usize(), + 7 => self.child7[abs.index].into_usize(), + 8 => self.child8[abs.index].into_usize(), + 9 => self.child9[abs.index].into_usize(), + 10 => self.child10[abs.index].into_usize(), + 11 => self.child11[abs.index].into_usize(), + 12 => self.child12[abs.index].into_usize(), + 13 => self.child13[abs.index].into_usize(), + 14 => self.child14[abs.index].into_usize(), + 15 => self.child15[abs.index].into_usize(), + _ => panic!("wrong abs index"), + } + } + + // Returns the childs AbsIndex of Parent AbsIndex + // child_lod must lie within parent + // uses parent_lod as buffer, to not calculate it again + // uses parent_child_index as a buffer, to not calculate it again + fn int_get(parent_abs: AbsIndex, child_lod: LodIndex, parent_lod: LodIndex, parent_child_index: usize) -> AbsIndex { + let child_layer = X::child_layer_id[parent_abs.layer as usize].unwrap(); + let child_lod = child_lod.align_to_layer_id(child_layer); + let child_offset = relative_to_1d(child_lod, parent_lod, child_layer, X::layer_volume[child_layer as usize]); + //println!("{} int_get - parent_abs {} child_lod {} parent_lod {} parent_child_index {} child_offset {}", Self::debug_offset(parent_abs.layer), parent_abs, child_lod, parent_lod, parent_child_index, child_offset); + AbsIndex::new(child_layer, parent_child_index + child_offset) + } + + // slower variant of int_get which requiere self lookups + fn int_get_lockup(&self, parent_abs: AbsIndex, child_lod: LodIndex) -> AbsIndex { + let parent_lod = child_lod.align_to_layer_id(parent_abs.layer); + let parent_child_index = self.int_get_child_index(parent_abs); + Self::int_get(parent_abs, child_lod, parent_lod, parent_child_index) + } + + // target_layer is requiered because same LodIndex can exist for multiple layers, and guessing is stupid here + fn int_recursive_get(&self, parent_abs: AbsIndex, child_lod: LodIndex, target_layer:u8) -> AbsIndex { + let mut parent_abs = parent_abs; + while true { + //println!("{} int_recursive_get {} - {}", Self::debug_offset(parent_abs.layer), parent_abs, target_layer); + parent_abs = self.int_get_lockup(parent_abs, child_lod); + if parent_abs.layer <= target_layer { + return parent_abs; + } + } + unreachable!(); + } + + pub fn int_get_n(&self, index: LodIndex, layer: u8) -> AbsIndex { + let anchor_lod = index.align_to_layer_id(X::anchor_layer_id); + let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]); + let wanted_abs = self.int_recursive_get(anchor_abs, index, layer); + debug_assert_eq!(wanted_abs.layer, layer); + wanted_abs + } + + pub fn get15(&self, index: LodIndex) -> &X::L15 { &self.layer15[self.int_get_n(index,15).index] } + + pub fn get14(&self, index: LodIndex) -> &X::L14 { &self.layer14[self.int_get_n(index,14).index] } + + pub fn get13(&self, index: LodIndex) -> &X::L13 { &self.layer13[self.int_get_n(index,13).index] } + + pub fn get12(&self, index: LodIndex) -> &X::L12 { &self.layer12[self.int_get_n(index,12).index] } + + pub fn get11(&self, index: LodIndex) -> &X::L11 { &self.layer11[self.int_get_n(index,11).index] } + + pub fn get10(&self, index: LodIndex) -> &X::L10 { &self.layer10[self.int_get_n(index,10).index] } + + pub fn get9(&self, index: LodIndex) -> &X::L9 { + &self.layer9[self.int_get_n(index,9).index] + } + + pub fn get8(&self, index: LodIndex) -> &X::L8 { + &self.layer8[self.int_get_n(index,8).index] + } + + pub fn get7(&self, index: LodIndex) -> &X::L7 { + &self.layer7[self.int_get_n(index,7).index] + } + + pub fn get6(&self, index: LodIndex) -> &X::L6 { + &self.layer6[self.int_get_n(index,6).index] + } + + pub fn get5(&self, index: LodIndex) -> &X::L5 { + &self.layer5[self.int_get_n(index,5).index] + } + + pub fn get4(&self, index: LodIndex) -> &X::L4 { + &self.layer4[self.int_get_n(index,4).index] + } + + pub fn get3(&self, index: LodIndex) -> &X::L3 { + &self.layer3[self.int_get_n(index,3).index] + } + + pub fn get2(&self, index: LodIndex) -> &X::L2 { + &self.layer2[self.int_get_n(index,2).index] + } + + pub fn get1(&self, index: LodIndex) -> &X::L1 { + &self.layer1[self.int_get_n(index,1).index] + } + + pub fn get0(&self, index: LodIndex) -> &X::L0 { + &self.layer0[self.int_get_n(index,0).index] + } + + pub fn set15(&mut self, index: LodIndex, value: X::L15, delta: Option) { + let n = self.int_get_n(index,15).index; + delta.map(|d| d.changed15(index, Some(value.clone()))); + self.layer15[n] = value; + } + + // returns the last LodIndex, that belongs to a parent AbsIndex + fn get_last_child_lod(parent: LodIndex, parent_layer: u8) -> LodIndex { + let child_width = two_pow_u(X::child_layer_id[parent_layer as usize].unwrap()) as u32; + parent + LodIndex::new(X::layer_volume[X::child_layer_id[parent_layer as usize].unwrap() as usize].map(|e| (e-1)*child_width)) + } + + fn debug_offset(layer: u8) -> &'static str { + match layer { + 0 => " | ", + 4 => " ---- ", + 5 => " ----- ", + 9 => " ---------- ", + 13 => " ------------- ", + _ => panic!("aaa"), + } + } + + /* + lower: must always be a LodIndex inside parent + upper: must always have same parent as lower -> parent + */ + fn int_make_at_least(&mut self, parent: AbsIndex, /*parent_lod2: LodIndex,*/ area: LodArea, target_layer: u8, delta: &mut Option) { + let child_layer = X::child_layer_id[parent.layer as usize]; + let parent_lod_width = two_pow_u(parent.layer) as u32; + let parent_lod = area.lower.align_to_layer_id(parent.layer); + //assert_eq!(parent_lod, parent_lod2); + //println!("{} lower, upper {} {} {} - {:?}", Self::debug_offset(parent.layer), area.lower, area.upper, parent_lod_width, child_layer); + if parent.layer > target_layer { + // create necessary childs: + X::drill_down(self, parent, delta); + //println!("{} DRILLED DOWN", Self::debug_offset(parent.layer)); + if child_layer.is_some() && child_layer.unwrap() > target_layer { + let child_layer = child_layer.unwrap(); + let child_lod_width = two_pow_u(child_layer) as u32; + //calc childs which needs to be called recusivly, there childs will be the new parents + let child_lower = area.lower.align_to_layer_id(child_layer); + let child_upper = area.upper.align_to_layer_id(child_layer); + let child_base_abs_index = self.int_get_child_index(parent); + let child_volume = X::layer_volume[child_layer as usize]; + // loop over childs and calculate correct lower and + let lower_xyz = (child_lower.get()-parent_lod.get()).map(|e| e / child_lod_width); + let upper_xyz = (child_upper.get()-parent_lod.get()).map(|e| e / child_lod_width); + //println!("{} lxyz {}", Self::debug_offset(parent.layer), lower_xyz); + //println!("{} uxyz {}", Self::debug_offset(parent.layer), upper_xyz); + //println!("{} child_lod_width {}", Self::debug_offset(parent.layer), child_lod_width); + for x in lower_xyz[0]..upper_xyz[0]+1 { + for y in lower_xyz[1]..upper_xyz[1]+1 { + for z in lower_xyz[2]..upper_xyz[2]+1 { + //println!("{} xyz {} {} {}", Self::debug_offset(parent.layer), x, y, z); + //calculate individual abs values, because we now, how they are ordered in the vec + let child_abs_index = child_base_abs_index + (x * child_volume[2] * child_volume[1] + y * child_volume[2] + z) as usize; + let child_abs = AbsIndex::new(child_layer, child_abs_index); + let child_lower = parent_lod + LodIndex::new(Vec3::new(x * child_lod_width, y * child_lod_width, z * child_lod_width)); + let child_upper = child_lower + LodIndex::new(Vec3::new(child_lod_width-1, child_lod_width-1, child_lod_width-1)); + + let inner_lower = index::max(area.lower, child_lower); + let inner_upper = index::min(area.upper, child_upper); + //println!("{} restrict {} {} to {} {}", Self::debug_offset(parent.layer), area.lower, area.upper, inner_lower, inner_upper); + let inner_area = LodArea::new(inner_lower, inner_upper); + Self::int_make_at_least(self, child_abs, inner_area, target_layer, delta); + } + } + } + } + } + } + + /* + These functions allow you to make the LodLayer provide a certain LOD for the specified area + */ + /*is at least minimum or maximum*/ + + pub fn make_at_least(&mut self, area: LodArea, target_layer: u8, delta: &mut Option) { + let anchor_layer_id = X::anchor_layer_id; + let anchor_lower = area.lower.align_to_layer_id(anchor_layer_id); + let anchor_upper = area.upper.align_to_layer_id(anchor_layer_id); + let lower_xyz = anchor_lower.get(); + let upper_xyz = anchor_upper.get(); + let anchor_width = index::two_pow_u(anchor_layer_id) as u32; + let mut x = lower_xyz[0]; + //println!("{} xxx lower, upper {} {} {}", Self::debug_offset(anchor_layer_id), lower_xyz, upper_xyz, anchor_width); + while x <= upper_xyz[0] { + let mut y = lower_xyz[1]; + while y <= upper_xyz[1] { + let mut z = lower_xyz[2]; + while z <= upper_xyz[2] { + let anchor_lod = LodIndex::new(Vec3::new(x,y,z)); + let anchor_abs = AbsIndex::new(anchor_layer_id, self.anchor[&anchor_lod]); ; + if anchor_abs.layer > target_layer { + X::drill_down(self, anchor_abs, delta); + let child_lod_upper = Self::get_last_child_lod(anchor_lod, anchor_abs.layer); + + let inner_lower = index::max(area.lower, anchor_lod); + let inner_upper = index::min(area.upper, child_lod_upper); + + //println!("{}call child with lower, upper {} {} instead of {} {} ", Self::debug_offset(anchor_layer_id), inner_lower, inner_upper, anchor_lod, child_lod_upper); + let inner_area = LodArea::new(inner_lower, inner_upper); + self.int_make_at_least(anchor_abs, inner_area, target_layer, delta); + } + z += anchor_width; + } + y += anchor_width; + } + x += anchor_width; + } + } + fn make_at_most(&mut self, area: LodArea, layer: i8) { + + } + fn make_exactly(&mut self, area: LodArea, layer: i8) { + + } +} + +impl LodIntoOptionUsize for () { + fn is_some(self) -> bool { + false + } + fn into_usize(self) -> usize { + unreachable!("dummyUsize") + } +} + +impl LodIntoOptionUsize for u32 { + fn is_some(self) -> bool { + self != u32::MAX + } + fn into_usize(self) -> usize { + self as usize + } +} \ No newline at end of file diff --git a/worldsim/src/lodstore/delta.rs b/worldsim/src/lodstore/delta.rs new file mode 100644 index 0000000000..b21122cc57 --- /dev/null +++ b/worldsim/src/lodstore/delta.rs @@ -0,0 +1,97 @@ +use super::{ + data::{ + LodData, + LodConfig, + }, + index::LodIndex, + area::LodArea, +}; + +/* + A LodDelta applies a change to a Lod + The rules for LodDeltas are strict in order to make them as simple as possible. + A LodDelta created from LodData A can only be applied safely to another LodData equal to A. + However LodDeltas can be combined and reverted + + I am not sure about a Vec or Hashmap, the thing is Vec is easier to fill, but might contain duplicate entries: + E.g. change a item multiple time, bloats the Delta, with a Hashmap only the lastest state is kept. + However i belive that most algorithms only change every Value once. +*/ + +pub trait LodDelta { + type Config: LodConfig; + + fn apply(&self, data: &mut LodData::); + fn filter(&self, area: LodArea) -> Self; + + fn changed0(&mut self, index: LodIndex, value: Option<::L0>); + fn changed15(&mut self, index: LodIndex, value: Option<::L15>); +} + +#[derive(Debug, Clone)] +pub struct DefaultLodDelta { + pub layer0: Vec<(LodIndex, Option)>, // 1/16 + pub layer1: Vec<(LodIndex, Option)>, // 1/8 + pub layer2: Vec<(LodIndex, Option)>, // 1/4 + pub layer3: Vec<(LodIndex, Option)>, // 1/2 + pub layer4: Vec<(LodIndex, Option)>, // 1 + pub layer5: Vec<(LodIndex, Option)>, // 2 + pub layer6: Vec<(LodIndex, Option)>, // 4 + pub layer7: Vec<(LodIndex, Option)>, // 8 + pub layer8: Vec<(LodIndex, Option)>, // 16 + pub layer9: Vec<(LodIndex, Option)>, // 32 + pub layer10: Vec<(LodIndex, Option)>, // 64 + pub layer11: Vec<(LodIndex, Option)>, // 128 + pub layer12: Vec<(LodIndex, Option)>, // 256 + pub layer13: Vec<(LodIndex, Option)>, // 512 + pub layer14: Vec<(LodIndex, Option)>, // 1024 + pub layer15: Vec<(LodIndex, Option)>, // 2048 +} + +impl DefaultLodDelta { + fn new() -> Self { + Self { + layer0: Vec::new(), + layer1: Vec::new(), + layer2: Vec::new(), + layer3: Vec::new(), + layer4: Vec::new(), + layer5: Vec::new(), + layer6: Vec::new(), + layer7: Vec::new(), + layer8: Vec::new(), + layer9: Vec::new(), + layer10: Vec::new(), + layer11: Vec::new(), + layer12: Vec::new(), + layer13: Vec::new(), + layer14: Vec::new(), + layer15: Vec::new(), + } + } +} + +impl LodDelta for DefaultLodDelta { + type Config = X; + + //TODO: apply that moves out + fn apply(&self, data: &mut LodData::) { + for (index, item) in &self.layer15 { + if item.is_some() { + data.set15(*index, item.clone().unwrap(), None); + } + } + } + + fn filter(&self, area: LodArea) -> Self { + Self::new() + } + + fn changed0(&mut self, index: LodIndex, value: Option<::L0>) { + self.layer0.push((index, value)); + } + + fn changed15(&mut self, index: LodIndex, value: Option<::L15>){ + self.layer15.push((index, value)); + } +} \ No newline at end of file diff --git a/worldsim/src/lodstore/index.rs b/worldsim/src/lodstore/index.rs index 3b553348f0..3bc3ecd4d8 100644 --- a/worldsim/src/lodstore/index.rs +++ b/worldsim/src/lodstore/index.rs @@ -5,22 +5,20 @@ use std::cmp; use std::fmt; /* -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. -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", +A region owns the Values from in (0, 2048) in steps of 1/32. +But because regions can also subscribe we add support to the range (0, 2048*3). +which is 13 bits for the digits before the decimal point and 5 bits for the digits after the decimal point. +We use our own LodIndex type to store and compute based on these values, because u16 arithmetic (inside the owned area) is super easy to archive and allows us to optimize a lot. -Edit: now it actually implements a value from 0 - 3*2048 - 1/32, covering over 3 regions for accessing neighbor region values -- lower neighbor 0 -> 0 -1 -> 2047 31/32 +65535 -> 2047 31/32 -- owned 65536 -> 2048 131071 -> 4095 31/32 -- upper neighbor 196607 -> 6143 31/32 - */ #[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)] @@ -40,6 +38,7 @@ const BIT_Y_MASK: u64 = 0b0000_0000_0000_0000_0000_0000_0000_1111_1111_1111_1111 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; +//TODO: Optimize! impl LodIndex { pub fn new(data: Vec3) -> Self { let mut index = LodIndex {data: 0}; @@ -61,9 +60,9 @@ impl LodIndex { self.data = x + y + z; } - pub fn align_to_layer_id(&self, level: u8) -> LodIndex { + pub fn align_to_layer_id(&self, layer: u8) -> LodIndex { let xyz = self.get(); - let f = two_pow_u(level) as u32; + let f = two_pow_u(layer) as u32; LodIndex::new(xyz.map(|i| { (i / f) * f })) @@ -105,6 +104,50 @@ impl fmt::Display for AbsIndex { } } +impl Sub for LodIndex { + 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*/ + } + } +} + +pub const fn two_pow_u(n: u8) -> u16 { + 1 << n +} + +pub fn relative_to_1d(child_lod: LodIndex, parent_lod: LodIndex, child_layer: u8, relative_size: Vec3) -> usize { + let width = two_pow_u(child_layer) as u32; + let index = (child_lod.get() - parent_lod.get()).map(|e| e / width); + (index[0] * relative_size[2] * relative_size[1] + index[1] * relative_size[2] + index[2]) as usize +} + +pub fn min(lhs: LodIndex, rhs: LodIndex) -> LodIndex { + let lhs = lhs.get(); + let rhs = rhs.get(); + LodIndex::new(lhs.map2(rhs, |a,b| cmp::min(a,b))) +} + +pub fn max(lhs: LodIndex, rhs: LodIndex) -> LodIndex { + let lhs = lhs.get(); + let rhs = rhs.get(); + LodIndex::new(lhs.map2(rhs, |a,b| cmp::max(a,b))) +} + +/************* + TESTS +**************/ + #[cfg(test)] mod tests { use crate::{ @@ -213,43 +256,3 @@ mod tests { } } -impl Sub for LodIndex { - 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*/ - } - } -} - -pub const fn two_pow_u(n: u8) -> u16 { - 1 << n -} - -pub fn relative_to_1d(child_lod: LodIndex, parent_lod: LodIndex, child_layer: u8, relative_size: Vec3) -> usize { - let width = two_pow_u(child_layer) as u32; - let index = (child_lod.get() - parent_lod.get()).map(|e| e / width); - (index[0] * relative_size[2] * relative_size[1] + index[1] * relative_size[2] + index[2]) as usize -} - -pub fn min(lhs: LodIndex, rhs: LodIndex) -> LodIndex { - let lhs = lhs.get(); - let rhs = rhs.get(); - LodIndex::new(lhs.map2(rhs, |a,b| cmp::min(a,b))) -} - -pub fn max(lhs: LodIndex, rhs: LodIndex) -> LodIndex { - let lhs = lhs.get(); - let rhs = rhs.get(); - LodIndex::new(lhs.map2(rhs, |a,b| cmp::max(a,b))) -} - diff --git a/worldsim/src/lodstore/mod.rs b/worldsim/src/lodstore/mod.rs index dd63dd9540..f16ea2eb33 100644 --- a/worldsim/src/lodstore/mod.rs +++ b/worldsim/src/lodstore/mod.rs @@ -1,469 +1,6 @@ pub mod index; -use std::u32; -use std::sync::Arc; -use std::collections::HashMap; -use vek::*; -use index::{ - LodIndex, - AbsIndex, - relative_to_1d, -}; - -/* -LOD Data contains different Entries in different vecs, every entry has a "pointer" to it's child start. -This is the structure to store a region and all subscribed information -*/ - -pub trait LodIntoOptionUsize: Copy { - fn is_some(self) -> bool; - fn into_usize(self) -> usize; -} - -pub trait LodConfig { - type L0; // 2^-4 - type L1; - type L2; - type L3; - type L4; // 2^0 - type L5; - type L6; - type L7; - type L8; - type L9; - type L10; - type L11; - type L12; - type L13; - type L14; - type L15; // 2^11 - - type I0: LodIntoOptionUsize; - type I1: LodIntoOptionUsize; - type I2: LodIntoOptionUsize; - type I3: LodIntoOptionUsize; - type I4: LodIntoOptionUsize; - type I5: LodIntoOptionUsize; - type I6: LodIntoOptionUsize; - type I7: LodIntoOptionUsize; - type I8: LodIntoOptionUsize; - type I9: LodIntoOptionUsize; - type I10: LodIntoOptionUsize; - type I11: LodIntoOptionUsize; - type I12: LodIntoOptionUsize; - type I13: LodIntoOptionUsize; - type I14: LodIntoOptionUsize; - type I15: LodIntoOptionUsize; - - const anchor_layer_id: u8; - - const layer_volume: [Vec3; 16]; // number of elements on this layer as Vec3 (not on child layer!) - const child_layer_id: [Option; 16]; // layer below this one - const layer_len: [usize; 16]; // optimisation for layer_volume, total no of elements as usize - - fn setup(&mut self); - fn drill_down(data: &mut LodData::, abs: AbsIndex) where Self: Sized; - fn drill_up(data: &mut LodData::, parent_abs: AbsIndex) where Self: Sized; -} - -/* -There is another optimization problem: We have OWNED data and foreign DATA in the struct, but we don't want the foreign data to take a lot of space if unused -But both needs to be accessible transparent without overhead in calculation, difficult. -Imagine a Terrain, which top level is L13, so it would have 64 entries for the owned and 1664 for foreign data if everything is filled. -So we really only fill the boarder giving us 152 border areas. -One could think about multiple entry levels for foreign and owned data, but that means, that foreign data without a parent would exist, which might break algorithms.... -So for now we go with a single anchorlevel for now, and hope the designer chooses good levels -*/ - -#[derive(Debug, Clone)] -pub struct LodData { - pub layer0: Vec, // 1/16 - pub layer1: Vec, // 1/8 - pub layer2: Vec, // 1/4 - pub layer3: Vec, // 1/2 - pub layer4: Vec, // 1 - pub layer5: Vec, // 2 - pub layer6: Vec, // 4 - pub layer7: Vec, // 8 - pub layer8: Vec, // 16 - pub layer9: Vec, // 32 - pub layer10: Vec, // 64 - pub layer11: Vec, // 128 - pub layer12: Vec, // 256 - pub layer13: Vec, // 512 - pub layer14: Vec, // 1024 - pub layer15: Vec, // 2048 - - pub child0: Vec, - pub child1: Vec, - pub child2: Vec, - pub child3: Vec, - pub child4: Vec, - pub child5: Vec, - pub child6: Vec, - pub child7: Vec, - pub child8: Vec, - pub child9: Vec, - pub child10: Vec, - pub child11: Vec, - pub child12: Vec, - pub child13: Vec, - pub child14: Vec, - pub child15: Vec, - pub anchor: HashMap, -} - -impl LodData -{ - pub fn new() -> Self { - Self { - layer0: Vec::new(), - layer1: Vec::new(), - layer2: Vec::new(), - layer3: Vec::new(), - layer4: Vec::new(), - layer5: Vec::new(), - layer6: Vec::new(), - layer7: Vec::new(), - layer8: Vec::new(), - layer9: Vec::new(), - layer10: Vec::new(), - layer11: Vec::new(), - layer12: Vec::new(), - layer13: Vec::new(), - layer14: Vec::new(), - layer15: Vec::new(), - child0: Vec::new(), - child1: Vec::new(), - child2: Vec::new(), - child3: Vec::new(), - child4: Vec::new(), - child5: Vec::new(), - child6: Vec::new(), - child7: Vec::new(), - child8: Vec::new(), - child9: Vec::new(), - child10: Vec::new(), - child11: Vec::new(), - child12: Vec::new(), - child13: Vec::new(), - child14: Vec::new(), - child15: Vec::new(), - anchor: HashMap::new(), - } - } - - // dynamically dispatches the get_child_index, this is most prob the bottleneck function. - // evaluate the performacne impact!!! - fn int_get_child_index(&self, abs: AbsIndex) -> usize { - match abs.layer { - 0 => self.child0[abs.index].into_usize(), - 1 => self.child1[abs.index].into_usize(), - 2 => self.child2[abs.index].into_usize(), - 3 => self.child3[abs.index].into_usize(), - 4 => self.child4[abs.index].into_usize(), - 5 => self.child5[abs.index].into_usize(), - 6 => self.child6[abs.index].into_usize(), - 7 => self.child7[abs.index].into_usize(), - 8 => self.child8[abs.index].into_usize(), - 9 => self.child9[abs.index].into_usize(), - 10 => self.child10[abs.index].into_usize(), - 11 => self.child11[abs.index].into_usize(), - 12 => self.child12[abs.index].into_usize(), - 13 => self.child13[abs.index].into_usize(), - 14 => self.child14[abs.index].into_usize(), - 15 => self.child15[abs.index].into_usize(), - _ => panic!("wrong abs index"), - } - } - - // Returns the childs AbsIndex of Parent AbsIndex - // child_lod must lie within parent - // uses parent_lod as buffer, to not calculate it again - // uses parent_child_index as a buffer, to not calculate it again - fn int_get(parent_abs: AbsIndex, child_lod: LodIndex, parent_lod: LodIndex, parent_child_index: usize) -> AbsIndex { - let child_layer = X::child_layer_id[parent_abs.layer as usize].unwrap(); - let child_lod = child_lod.align_to_layer_id(child_layer); - let child_offset = relative_to_1d(child_lod, parent_lod, child_layer, X::layer_volume[child_layer as usize]); - //println!("{} int_get - parent_abs {} child_lod {} parent_lod {} parent_child_index {} child_offset {}", Self::ppp(parent_abs.layer), parent_abs, child_lod, parent_lod, parent_child_index, child_offset); - AbsIndex::new(child_layer, parent_child_index + child_offset) - } - - // slower variant of int_get which requiere self lookups - fn int_get_lockup(&self, parent_abs: AbsIndex, child_lod: LodIndex) -> AbsIndex { - let parent_lod = child_lod.align_to_layer_id(parent_abs.layer); - let parent_child_index = self.int_get_child_index(parent_abs); - Self::int_get(parent_abs, child_lod, parent_lod, parent_child_index) - } - - // target_layer is requiered because same LodIndex can exist for multiple layers, and guessing is stupid here - fn int_recursive_get(&self, parent_abs: AbsIndex, child_lod: LodIndex, target_layer:u8) -> AbsIndex { - let mut parent_abs = parent_abs; - while true { - //println!("{} int_recursive_get {} - {}", Self::ppp(parent_abs.layer), parent_abs, target_layer); - parent_abs = self.int_get_lockup(parent_abs, child_lod); - if parent_abs.layer <= target_layer { - return parent_abs; - } - } - unreachable!(); - } - - pub fn get15(&self, index: LodIndex) -> &X::L15 { - let anchor_lod = index.align_to_layer_id(X::anchor_layer_id); - let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]); - let wanted_abs = self.int_recursive_get(anchor_abs, index, 15); - debug_assert_eq!(wanted_abs.layer, 15); - &self.layer15[wanted_abs.index] - } - - pub fn get14(&self, index: LodIndex) -> &X::L14 { - let anchor_lod = index.align_to_layer_id(X::anchor_layer_id); - let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]); - let wanted_abs = self.int_recursive_get(anchor_abs, index, 14); - debug_assert_eq!(wanted_abs.layer, 14); - &self.layer14[wanted_abs.index] - } - - pub fn get13(&self, index: LodIndex) -> &X::L13 { - let anchor_lod = index.align_to_layer_id(X::anchor_layer_id); - let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]); - let wanted_abs = self.int_recursive_get(anchor_abs, index, 13); - debug_assert_eq!(wanted_abs.layer, 13); - &self.layer13[wanted_abs.index] - } - - pub fn get12(&self, index: LodIndex) -> &X::L12 { - let anchor_lod = index.align_to_layer_id(X::anchor_layer_id); - let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]); - let wanted_abs = self.int_recursive_get(anchor_abs, index, 12); - debug_assert_eq!(wanted_abs.layer, 12); - &self.layer12[wanted_abs.index] - } - - pub fn get11(&self, index: LodIndex) -> &X::L11 { - let anchor_lod = index.align_to_layer_id(X::anchor_layer_id); - let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]); - let wanted_abs = self.int_recursive_get(anchor_abs, index, 11); - debug_assert_eq!(wanted_abs.layer, 11); - &self.layer11[wanted_abs.index] - } - - pub fn get10(&self, index: LodIndex) -> &X::L10 { - let anchor_lod = index.align_to_layer_id(X::anchor_layer_id); - let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]); - let wanted_abs = self.int_recursive_get(anchor_abs, index, 10); - debug_assert_eq!(wanted_abs.layer, 10); - &self.layer10[wanted_abs.index] - } - - pub fn get9(&self, index: LodIndex) -> &X::L9 { - let anchor_lod = index.align_to_layer_id(X::anchor_layer_id); - let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]); - let wanted_abs = self.int_recursive_get(anchor_abs, index, 9); - debug_assert_eq!(wanted_abs.layer, 9); - &self.layer9[wanted_abs.index] - } - - pub fn get8(&self, index: LodIndex) -> &X::L8 { - let anchor_lod = index.align_to_layer_id(X::anchor_layer_id); - let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]); - let wanted_abs = self.int_recursive_get(anchor_abs, index, 8); - debug_assert_eq!(wanted_abs.layer, 8); - &self.layer8[wanted_abs.index] - } - - pub fn get7(&self, index: LodIndex) -> &X::L7 { - let anchor_lod = index.align_to_layer_id(X::anchor_layer_id); - let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]); - let wanted_abs = self.int_recursive_get(anchor_abs, index, 7); - debug_assert_eq!(wanted_abs.layer, 7); - &self.layer7[wanted_abs.index] - } - - pub fn get6(&self, index: LodIndex) -> &X::L6 { - let anchor_lod = index.align_to_layer_id(X::anchor_layer_id); - let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]); - let wanted_abs = self.int_recursive_get(anchor_abs, index, 6); - debug_assert_eq!(wanted_abs.layer, 6); - &self.layer6[wanted_abs.index] - } - - pub fn get5(&self, index: LodIndex) -> &X::L5 { - let anchor_lod = index.align_to_layer_id(X::anchor_layer_id); - let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]); - let wanted_abs = self.int_recursive_get(anchor_abs, index, 5); - debug_assert_eq!(wanted_abs.layer, 5); - &self.layer5[wanted_abs.index] - } - - pub fn get4(&self, index: LodIndex) -> &X::L4 { - let anchor_lod = index.align_to_layer_id(X::anchor_layer_id); - let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]); - //println!("4aa4 {:?} - {:?}", anchor_lod, anchor_abs ); - let wanted_abs = self.int_recursive_get(anchor_abs, index, 4); - debug_assert_eq!(wanted_abs.layer, 4); - &self.layer4[wanted_abs.index] - } - - pub fn get3(&self, index: LodIndex) -> &X::L3 { - let anchor_lod = index.align_to_layer_id(X::anchor_layer_id); - let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]); - let wanted_abs = self.int_recursive_get(anchor_abs, index, 3); - debug_assert_eq!(wanted_abs.layer, 3); - &self.layer3[wanted_abs.index] - } - - pub fn get2(&self, index: LodIndex) -> &X::L2 { - let anchor_lod = index.align_to_layer_id(X::anchor_layer_id); - let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]); - let wanted_abs = self.int_recursive_get(anchor_abs, index, 2); - debug_assert_eq!(wanted_abs.layer, 2); - &self.layer2[wanted_abs.index] - } - - pub fn get1(&self, index: LodIndex) -> &X::L1 { - let anchor_lod = index.align_to_layer_id(X::anchor_layer_id); - let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]); - let wanted_abs = self.int_recursive_get(anchor_abs, index, 1); - debug_assert_eq!(wanted_abs.layer, 1); - &self.layer1[wanted_abs.index] - } - - pub fn get0(&self, index: LodIndex) -> &X::L0 { - let anchor_lod = index.align_to_layer_id(X::anchor_layer_id); - let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]); - let wanted_abs = self.int_recursive_get(anchor_abs, index, 0); - debug_assert_eq!(wanted_abs.layer, 0); - &self.layer0[wanted_abs.index] - } - - // returns the last LodIndex, that belongs to a parent AbsIndex - fn get_last_child_lod(parent: LodIndex, parent_level: u8) -> LodIndex { - let child_width = index::two_pow_u(X::child_layer_id[parent_level as usize].unwrap()) as u32; - parent + LodIndex::new(X::layer_volume[X::child_layer_id[parent_level as usize].unwrap() as usize].map(|e| (e-1)*child_width)) - } - - fn ppp(level: u8) -> &'static str { - match level { - 0 => " | ", - 4 => " ---- ", - 5 => " ----- ", - 9 => " ---------- ", - 13 => " ------------- ", - _ => panic!("aaa"), - } - } - - /* - lower: must always be a LodIndex inside parent - upper: must always have same parent as lower -> parent - */ - fn int_make_at_least(&mut self, parent: AbsIndex, /*parent_lod2: LodIndex,*/ lower: LodIndex, upper: LodIndex, target_level: u8) { - let child_layer = X::child_layer_id[parent.layer as usize]; - let parent_lod_width = index::two_pow_u(parent.layer) as u32; - let parent_lod = lower.align_to_layer_id(parent.layer); - //assert_eq!(parent_lod, parent_lod2); - //println!("{} lower, upper {} {} {} - {:?}", Self::ppp(parent.layer), lower, upper, parent_lod_width, child_layer); - if parent.layer > target_level { - // create necessary childs: - X::drill_down(self, parent); - //println!("{} DRILLED DOWN", Self::ppp(parent.layer)); - if child_layer.is_some() && child_layer.unwrap() > target_level { - let child_layer = child_layer.unwrap(); - let child_lod_width = index::two_pow_u(child_layer) as u32; - //calc childs which needs to be called recusivly, there childs will be the new parents - let child_lower = lower.align_to_layer_id(child_layer); - let child_upper = upper.align_to_layer_id(child_layer); - let child_base_abs_index = self.int_get_child_index(parent); - let child_volume = X::layer_volume[child_layer as usize]; - // loop over childs and calculate correct lower and - let lower_xyz = (child_lower.get()-parent_lod.get()).map(|e| e / child_lod_width); - let upper_xyz = (child_upper.get()-parent_lod.get()).map(|e| e / child_lod_width); - //println!("{} lxyz {}", Self::ppp(parent.layer), lower_xyz); - //println!("{} uxyz {}", Self::ppp(parent.layer), upper_xyz); - //println!("{} child_lod_width {}", Self::ppp(parent.layer), child_lod_width); - for x in lower_xyz[0]..upper_xyz[0]+1 { - for y in lower_xyz[1]..upper_xyz[1]+1 { - for z in lower_xyz[2]..upper_xyz[2]+1 { - //println!("{} xyz {} {} {}", Self::ppp(parent.layer), x, y, z); - //calculate individual abs values, because we now, how they are ordered in the vec - let child_abs_index = child_base_abs_index + (x * child_volume[2] * child_volume[1] + y * child_volume[2] + z) as usize; - let child_abs = AbsIndex::new(child_layer, child_abs_index); - let child_lower = parent_lod + LodIndex::new(Vec3::new(x * child_lod_width, y * child_lod_width, z * child_lod_width)); - let child_upper = child_lower + LodIndex::new(Vec3::new(child_lod_width-1, child_lod_width-1, child_lod_width-1)); - - let inner_lower = index::max(lower, child_lower); - let inner_upper = index::min(upper, child_upper); - //println!("{} restrict {} {} to {} {}", Self::ppp(parent.layer), lower, upper, inner_lower, inner_upper); - Self::int_make_at_least(self, child_abs, inner_lower, inner_upper, target_level); - } - } - } - } - } - } - - /* - These functions allow you to make the LodLayer provide a certain LOD for the specified area - */ - /*is at least minimum or maximum*/ - - pub fn make_at_least(&mut self, lower: LodIndex, upper: LodIndex, target_level: u8) { - //ERROR, DOES NOT RECURSIVLY CALL - let anchor_layer_id = X::anchor_layer_id; - let anchor_lower = lower.align_to_layer_id(anchor_layer_id); - let anchor_upper = upper.align_to_layer_id(anchor_layer_id); - let lower_xyz = anchor_lower.get(); - let upper_xyz = anchor_upper.get(); - let anchor_width = index::two_pow_u(anchor_layer_id) as u32; - let mut x = lower_xyz[0]; - //println!("{} xxx lower, upper {} {} {}", Self::ppp(anchor_layer_id), lower_xyz, upper_xyz, anchor_width); - while x <= upper_xyz[0] { - let mut y = lower_xyz[1]; - while y <= upper_xyz[1] { - let mut z = lower_xyz[2]; - while z <= upper_xyz[2] { - let anchor_lod = LodIndex::new(Vec3::new(x,y,z)); - let anchor_abs = AbsIndex::new(anchor_layer_id, self.anchor[&anchor_lod]); ; - if anchor_abs.layer > target_level { - X::drill_down(self, anchor_abs); - let child_lod_upper = Self::get_last_child_lod(anchor_lod, anchor_abs.layer); - - let inner_lower = index::max(lower, anchor_lod); - let inner_upper = index::min(upper, child_lod_upper); - - //println!("{}call child with lower, upper {} {} instead of {} {} ", Self::ppp(anchor_layer_id), inner_lower, inner_upper, anchor_lod, child_lod_upper); - self.int_make_at_least(anchor_abs, inner_lower, inner_upper, target_level); - } - z += anchor_width; - } - y += anchor_width; - } - x += anchor_width; - } - } - fn make_at_most(&mut self, lower: LodIndex, upper: LodIndex, level: i8) { - - } - fn make_exactly(&mut self, lower: LodIndex, upper: LodIndex, level: i8) { - - } -} - -impl LodIntoOptionUsize for () { - fn is_some(self) -> bool { - false - } - fn into_usize(self) -> usize { - unreachable!("dummyUsize") - } -} - -impl LodIntoOptionUsize for u32 { - fn is_some(self) -> bool { - self != u32::MAX - } - fn into_usize(self) -> usize { - self as usize - } -} \ No newline at end of file +pub mod area; +pub mod data; +pub mod delta; +pub use data::LodData; +pub use data::LodConfig; \ No newline at end of file diff --git a/worldsim/src/region/lod/example.rs b/worldsim/src/region/lod/example.rs index bd071a66bd..27f678edc5 100644 --- a/worldsim/src/region/lod/example.rs +++ b/worldsim/src/region/lod/example.rs @@ -3,6 +3,9 @@ use crate::lodstore::{ LodConfig, index::LodIndex, index::AbsIndex, + area::LodArea, + delta::LodDelta, + delta::DefaultLodDelta, }; use vek::*; use std::u32; @@ -73,6 +76,9 @@ impl LodConfig for ExampleLodConfig { type I14 = (); type I15 = (); + type Delta = DefaultLodDelta; + type Additional = (); + const anchor_layer_id: u8 = 13; // this is not for the children, a layer9 has 32x32x32 childs, not 16x16x16 @@ -90,7 +96,7 @@ impl LodConfig for ExampleLodConfig { Vec3{x: 0, y: 0, z: 0}, Vec3{x: 0, y: 0, z: 0}, Vec3{x: 0, y: 0, z: 0}, - Vec3{x: 16, y: 16, z: 16}, + Vec3{x: 8, y: 8, z: 8}, Vec3{x: 0, y: 0, z: 0}, Vec3{x: 0, y: 0, z: 0}, ]; @@ -113,31 +119,11 @@ impl LodConfig for ExampleLodConfig { None, ]; - const layer_len: [usize; 16] = [ - (Self::layer_volume[0].x * Self::layer_volume[0].y * Self::layer_volume[0].z) as usize, - (Self::layer_volume[1].x * Self::layer_volume[1].y * Self::layer_volume[1].z) as usize, - (Self::layer_volume[2].x * Self::layer_volume[2].y * Self::layer_volume[2].z) as usize, - (Self::layer_volume[3].x * Self::layer_volume[3].y * Self::layer_volume[3].z) as usize, - (Self::layer_volume[4].x * Self::layer_volume[4].y * Self::layer_volume[4].z) as usize, - (Self::layer_volume[5].x * Self::layer_volume[5].y * Self::layer_volume[5].z) as usize, - (Self::layer_volume[6].x * Self::layer_volume[6].y * Self::layer_volume[6].z) as usize, - (Self::layer_volume[7].x * Self::layer_volume[7].y * Self::layer_volume[7].z) as usize, - (Self::layer_volume[8].x * Self::layer_volume[8].y * Self::layer_volume[8].z) as usize, - (Self::layer_volume[9].x * Self::layer_volume[9].y * Self::layer_volume[9].z) as usize, - (Self::layer_volume[10].x * Self::layer_volume[10].y * Self::layer_volume[10].z) as usize, - (Self::layer_volume[11].x * Self::layer_volume[11].y * Self::layer_volume[11].z) as usize, - (Self::layer_volume[12].x * Self::layer_volume[12].y * Self::layer_volume[12].z) as usize, - (Self::layer_volume[13].x * Self::layer_volume[13].y * Self::layer_volume[13].z) as usize, - (Self::layer_volume[14].x * Self::layer_volume[14].y * Self::layer_volume[14].z) as usize, - (Self::layer_volume[15].x * Self::layer_volume[15].y * Self::layer_volume[15].z) as usize, - ]; - - fn setup(&mut self) { } - fn drill_down(data: &mut LodData::, abs: AbsIndex) { + fn drill_down(data: &mut LodData::, abs: AbsIndex, delta: &mut Option>) { match abs.layer { 0 => { panic!("cannot drill down further"); @@ -148,6 +134,12 @@ impl LodConfig for ExampleLodConfig { data.layer0.reserve(Self::layer_len[0]); data.child4[abs.index] = insert as u32; //debug!("set0 {:?} = {}", abs, insert); + // in the future use something like a child_index as parameter and a RawVec for allocations + //data.layer0[child_index..child_index+Self::layer_len[0]].iter_mut().map( + // |e| *e = Example_4{ + // data: 0, + // } + // ); for i in 0..Self::layer_len[0] { data.layer0.push(Example_4{ data: 0, @@ -187,7 +179,7 @@ impl LodConfig for ExampleLodConfig { } - fn drill_up(data: &mut LodData::, parent_abs: AbsIndex) { + fn drill_up(data: &mut LodData::, parent_abs: AbsIndex, delta: &mut Option>) { match parent_abs.layer { 0 => { panic!("SubBlocks_4 does not have children"); @@ -215,6 +207,9 @@ impl LodConfig for ExampleLodConfig { } } +//DELTA + + #[cfg(test)] mod tests { use crate::{ @@ -272,17 +267,20 @@ mod tests { 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); + let area = LodArea::new(low, low); + result.make_at_least(area,9); } while result.layer4.len() < act0 as usize { let index = randIndex(&mut rng); let low = index.align_to_layer_id(4); - result.make_at_least(low,low,4); + let area = LodArea::new(low, low); + result.make_at_least(area, 4); } 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); + let area = LodArea::new(low, low); + result.make_at_least(area, 0); } println!("creating Region with {} 5er, {} 0er, {} -4er", act5, act0 , act_4); @@ -301,7 +299,8 @@ mod tests { let mut reg = createRegion(0.0, 0.0, 0.0, 0.1); let low = LodIndex::new(Vec3::new(8192, 8192, 8192)); let high = LodIndex::new(Vec3::new(16384, 16384, 16384)); - reg.make_at_least(low,high,4); + let area = LodArea::new(low, high); + reg.make_at_least(area, 4); } #[test] @@ -309,7 +308,8 @@ mod tests { let mut reg = createRegion(0.0, 0.0, 0.0, 0.1); let low = LodIndex::new(Vec3::new(0, 0, 0)); let high = LodIndex::new(Vec3::new(4, 4, 4)); - reg.make_at_least(low,high,0); + let area = LodArea::new(low, high); + reg.make_at_least(area, 0); reg.get0(LodIndex::new(Vec3::new(0, 0, 0))); reg.get0(LodIndex::new(Vec3::new(1, 0, 0))); reg.get0(LodIndex::new(Vec3::new(0, 1, 0))); @@ -325,7 +325,8 @@ mod tests { let mut reg = createRegion(0.0, 0.0, 0.0, 0.1); let low = LodIndex::new(Vec3::new(8704, 8704, 8704)); let high = LodIndex::new(Vec3::new(9216, 9216, 9216)); - reg.make_at_least(low,high,0); + let area = LodArea::new(low, high); + reg.make_at_least(area, 0); reg.get0(LodIndex::new(Vec3::new(8704, 8704, 8704))); reg.get0(LodIndex::new(Vec3::new(9000, 9000, 9000))); reg.get0(LodIndex::new(Vec3::new(9000, 9000, 9001))); @@ -342,7 +343,8 @@ mod tests { let mut reg = createRegion(0.0, 0.0, 0.0, 0.1); let low = LodIndex::new(Vec3::new(8704, 8704, 8704)); let high = LodIndex::new(Vec3::new(9216, 9216, 9216)); - reg.make_at_least(low,high,0); + let area = LodArea::new(low, high); + reg.make_at_least(area, 0); reg.get0(LodIndex::new(Vec3::new(8704, 8704, 8703))); } @@ -352,7 +354,8 @@ mod tests { let mut reg = createRegion(0.0, 0.0, 0.0, 0.1); let low = LodIndex::new(Vec3::new(8704, 8704, 8704)); let high = LodIndex::new(Vec3::new(9216, 9216, 9216)); - reg.make_at_least(low,high,0); + let area = LodArea::new(low, high); + reg.make_at_least(area,0); reg.get0(LodIndex::new(Vec3::new(10240, 10240, 10240))); } @@ -361,7 +364,8 @@ mod tests { let mut reg = createRegion(0.0, 0.0, 0.0, 0.1); let low = LodIndex::new(Vec3::new(8192, 8192, 8192)); let high = LodIndex::new(Vec3::new(10240, 10240, 10240)); - reg.make_at_least(low,high,4); + let area = LodArea::new(low, high); + reg.make_at_least(area, 4); } #[test] @@ -370,7 +374,8 @@ mod tests { let mut reg = createRegion(0.0, 0.0, 0.0, 0.1); let low = LodIndex::new(Vec3::new(0, 0, 0)); let high = LodIndex::new(Vec3::new(4, 4, 4)); - reg.make_at_least(low,high,0); + let area = LodArea::new(low, high); + reg.make_at_least(area, 0); reg.get0(LodIndex::new(Vec3::new(5, 5, 5))); //this access is not guaranteed but will work reg.get0(LodIndex::new(Vec3::new(16, 16, 16))); // out of range } @@ -393,7 +398,8 @@ mod tests { let high = LodIndex::new(Vec3::new(255, 255, 255)); b.iter(|| { let mut reg2 = region.clone(); - reg2.make_at_least(low,high,0); + let area = LodArea::new(low, high); + reg2.make_at_least(area, 0); }); } @@ -404,7 +410,8 @@ mod tests { let high = LodIndex::new(Vec3::new(4, 4, 4)); b.iter(|| { let mut reg2 = region.clone(); - reg2.make_at_least(low,high,0); + let area = LodArea::new(low, high); + reg2.make_at_least(area, 0); }); } @@ -415,7 +422,8 @@ mod tests { let high = LodIndex::new(Vec3::new(10240, 10240, 10240)); b.iter(|| { let mut reg2 = region.clone(); - reg2.make_at_least(low,high,4); + let area = LodArea::new(low, high); + reg2.make_at_least(area, 4); }); } @@ -425,7 +433,8 @@ mod tests { let access = LodIndex::new(Vec3::new(8561, 8312, 8412)); let low = LodIndex::new(Vec3::new(8192, 8192, 8192)); let high = LodIndex::new(Vec3::new(8800, 8800, 8800)); - reg.make_at_least(low,high,0); + let area = LodArea::new(low, high); + reg.make_at_least(area, 0); b.iter(|| reg.get0(access)); } @@ -434,7 +443,8 @@ mod tests { let mut reg = createRegion(0.0015, 0.001, 0.001, 0.1); let low = LodIndex::new(Vec3::new(8192, 8192, 8192)); let high = LodIndex::new(Vec3::new(8800, 8800, 8800)); - reg.make_at_least(low,high,0); + let area = LodArea::new(low, high); + reg.make_at_least(area, 0); b.iter(|| { reg.get0(LodIndex::new(Vec3::new(8561, 8312, 8412))); reg.get0(LodIndex::new(Vec3::new(8200, 8599, 8413))); @@ -466,7 +476,8 @@ mod tests { let z: u16 = rng.gen(); accesslist.push(LodIndex::new(Vec3::new(x,y,z).map(|x| (8192 + x / 66) as u32))); } - reg.make_at_least(low,high,0); + let area = LodArea::new(low, high); + reg.make_at_least(area, 0); b.iter(|| { for i in 0..1000000 { reg.get0(accesslist[i]); @@ -487,7 +498,8 @@ mod tests { let z: u16 = rng.gen(); accesslist.push(LodIndex::new(Vec3::new(x,y,z).map(|x| (8192 + x / 66) as u32))); } - reg.make_at_least(low,high,0); + let area = LodArea::new(low, high); + reg.make_at_least(area, 0); b.iter(|| { for i in 0..9990000 { reg.get0(accesslist[i]); @@ -501,8 +513,11 @@ mod tests { let access = LodIndex::new(Vec3::new(9561, 9312, 8412)); let low = LodIndex::new(Vec3::new(8192, 8192, 8192)); let high = LodIndex::new(Vec3::new(10240, 10240, 10240)); - reg.make_at_least(low,high,4); + let area = LodArea::new(low, high); + reg.make_at_least(area, 4); b.iter(|| reg.get4(access)); } + + // DELTA TESTS } \ No newline at end of file diff --git a/worldsim/src/region/lod/npcs.rs b/worldsim/src/region/lod/npcs.rs new file mode 100644 index 0000000000..9dc216d00a --- /dev/null +++ b/worldsim/src/region/lod/npcs.rs @@ -0,0 +1,190 @@ +use crate::lodstore::{ + LodData, + LodConfig, + index::LodIndex, + index::AbsIndex, + delta::LodDelta, + delta::DefaultLodDelta, +}; +use vek::*; +use std::u32; + +#[derive(Debug, Clone)] +pub struct Region9 { + precent_air: f32, + percent_forrest: f32, + percent_lava: f32, + percent_water: f32, +} + +#[derive(Debug, Clone)] +pub struct Chunk6 { + precent_air: f32, + percent_forrest: f32, + percent_lava: f32, + percent_water: f32, +} + +#[derive(Debug, Clone)] +pub struct TerrainLodConfig {} + +impl LodConfig for TerrainLodConfig { + type L0 = (); + type L1 = (); + type L2 = (); + type L3 = (); + type L4 = (); + type L5 = (); + type L6 = (); + type L7 = (); + type L8 = (); + type L9 = (); + type L10 = Chunk6; + type L11 = (); + type L12 = (); + type L13 = Region9; + type L14 = (); + type L15 = (); + + type I0 = (); + type I1 = (); + type I2 = (); + type I3 = (); + type I4 = (); + type I5 = (); + type I6 = (); + type I7 = (); + type I8 = (); + type I9 = (); + type I10 = (); + type I11 = (); + type I12 = (); + type I13 = u16; // Chunk5 2^(6*3), this is valid + type I14 = (); + type I15 = (); + + type Delta = DefaultLodDelta; + type Additional = (); + + const anchor_layer_id: u8 = 13; + + const layer_volume: [Vec3; 16] = [ + Vec3{x: 0, y: 0, z: 0}, + Vec3{x: 0, y: 0, z: 0}, + Vec3{x: 0, y: 0, z: 0}, + Vec3{x: 0, y: 0, z: 0}, + Vec3{x: 0, y: 0, z: 0}, + Vec3{x: 0, y: 0, z: 0}, + Vec3{x: 0, y: 0, z: 0}, + Vec3{x: 0, y: 0, z: 0}, + Vec3{x: 0, y: 0, z: 0}, + Vec3{x: 0, y: 0, z: 0}, + Vec3{x: 8, y: 8, z: 8}, + Vec3{x: 0, y: 0, z: 0}, + Vec3{x: 0, y: 0, z: 0}, + Vec3{x: 8, y: 8, z: 8}, + Vec3{x: 0, y: 0, z: 0}, + Vec3{x: 0, y: 0, z: 0}, + ]; + const child_layer_id: [Option; 16] = [ + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + Some(9), + None, + None, + ]; + + fn setup(&mut self) { + + } + + fn drill_down(data: &mut LodData::, abs: AbsIndex, delta: &mut Option>) { + match abs.layer { + 0 => { + panic!("cannot drill down further"); + }, + 4 => { + if data.child4[abs.index] != u32::MAX {return;} + let insert = data.layer0.len(); + data.layer0.reserve(Self::layer_len[0]); + data.child4[abs.index] = insert as u32; + //debug!("set0 {:?} = {}", abs, insert); + for i in 0..Self::layer_len[0] { + data.layer0.push(SubBlock_4{ + material: 0, + }); + } + }, + 9 => { + if data.child9[abs.index] != u32::MAX {return;} + let insert = data.layer4.len(); + data.layer4.reserve(Self::layer_len[4]); + data.child4.reserve(Self::layer_len[4]); + data.child9[abs.index] = insert as u32; + //debug!("set4 {:?} = {}", abs, insert); + for i in 0..Self::layer_len[4] { + data.layer4.push(Block0{ + material: 0, + }); + data.child4.push(u32::MAX); + } + }, + 13 => { + if data.child13[abs.index] != u32::MAX {return;} + let insert = data.layer9.len(); + data.layer9.reserve(Self::layer_len[9]); + data.child9.reserve(Self::layer_len[9]); + data.child13[abs.index] = insert as u32; + //debug!("set13 {:?} = {}", abs, insert); + for i in 0..Self::layer_len[9] { + data.layer9.push(Chunk5{ + precent_air: 0.2, + percent_forrest: 0.3, + percent_lava: 0.4, + percent_water: 0.1, + }); + data.child9.push(u32::MAX); + } + }, + _ => unreachable!(), + } + } + + fn drill_up(data: &mut LodData::, parent_abs: AbsIndex, delta: &mut Option>) { + unreachable!("finish this like in example"); + match parent_abs.layer { + 0 => { + panic!("SubBlocks_4 does not have children"); + }, + 4 => { + //let delete = data.layer4[parent_abs.index].child_id.expect("has no childs to drill up") as usize; + //data.layer4[parent_abs.index].child_id = None; + //data.layer0.drain(delete..delete+Self::layer_len[0]); + }, + 9 => { + //let delete = data.layer9[parent_abs.index].child_id.expect("has no childs to drill up") as usize; + //data.layer9[parent_abs.index].child_id = None; + //data.layer4.drain(delete..delete+Self::layer_len[4]); + }, + 13 => { + //let delete = data.layer13[parent_abs.index].child_id.expect("has no childs to drill up") as usize; + //data.layer13[parent_abs.index].child_id = None; + //data.layer9.drain(delete..delete+Self::layer_len[9]); + }, + _ => unreachable!(), + } + } +} + +pub type Terrain = LodData; \ No newline at end of file diff --git a/worldsim/src/region/lod/terrain.rs b/worldsim/src/region/lod/terrain.rs index 34f21aacd7..b462dbfcdc 100644 --- a/worldsim/src/region/lod/terrain.rs +++ b/worldsim/src/region/lod/terrain.rs @@ -3,8 +3,11 @@ use crate::lodstore::{ LodConfig, index::LodIndex, index::AbsIndex, + delta::LodDelta, + delta::DefaultLodDelta, }; use vek::*; +use std::u32; #[derive(Debug, Clone)] pub struct Region9 { @@ -70,6 +73,9 @@ impl LodConfig for TerrainLodConfig { type I14 = (); type I15 = (); + type Delta = DefaultLodDelta; + type Additional = (); + const anchor_layer_id: u8 = 13; const layer_volume: [Vec3; 16] = [ @@ -86,7 +92,7 @@ impl LodConfig for TerrainLodConfig { Vec3{x: 0, y: 0, z: 0}, Vec3{x: 0, y: 0, z: 0}, Vec3{x: 0, y: 0, z: 0}, - Vec3{x: 16, y: 16, z: 16}, + Vec3{x: 8, y: 8, z: 8}, Vec3{x: 0, y: 0, z: 0}, Vec3{x: 0, y: 0, z: 0}, ]; @@ -108,72 +114,64 @@ impl LodConfig for TerrainLodConfig { None, None, ]; - const layer_len: [usize; 16] = [ - (Self::layer_volume[0].x * Self::layer_volume[0].y * Self::layer_volume[0].z) as usize, - (Self::layer_volume[1].x * Self::layer_volume[1].y * Self::layer_volume[1].z) as usize, - (Self::layer_volume[2].x * Self::layer_volume[2].y * Self::layer_volume[2].z) as usize, - (Self::layer_volume[3].x * Self::layer_volume[3].y * Self::layer_volume[3].z) as usize, - (Self::layer_volume[4].x * Self::layer_volume[4].y * Self::layer_volume[4].z) as usize, - (Self::layer_volume[5].x * Self::layer_volume[5].y * Self::layer_volume[5].z) as usize, - (Self::layer_volume[6].x * Self::layer_volume[6].y * Self::layer_volume[6].z) as usize, - (Self::layer_volume[7].x * Self::layer_volume[7].y * Self::layer_volume[7].z) as usize, - (Self::layer_volume[8].x * Self::layer_volume[8].y * Self::layer_volume[8].z) as usize, - (Self::layer_volume[9].x * Self::layer_volume[9].y * Self::layer_volume[9].z) as usize, - (Self::layer_volume[10].x * Self::layer_volume[10].y * Self::layer_volume[10].z) as usize, - (Self::layer_volume[11].x * Self::layer_volume[11].y * Self::layer_volume[11].z) as usize, - (Self::layer_volume[12].x * Self::layer_volume[12].y * Self::layer_volume[12].z) as usize, - (Self::layer_volume[13].x * Self::layer_volume[13].y * Self::layer_volume[13].z) as usize, - (Self::layer_volume[14].x * Self::layer_volume[14].y * Self::layer_volume[14].z) as usize, - (Self::layer_volume[15].x * Self::layer_volume[15].y * Self::layer_volume[15].z) as usize, - ]; fn setup(&mut self) { } - fn drill_down(data: &mut LodData::, abs: AbsIndex) { + fn drill_down(data: &mut LodData::, abs: AbsIndex, delta: &mut Option>) { match abs.layer { 0 => { panic!("cannot drill down further"); }, 4 => { + if data.child4[abs.index] != u32::MAX {return;} let insert = data.layer0.len(); + data.layer0.reserve(Self::layer_len[0]); data.child4[abs.index] = insert as u32; + //debug!("set0 {:?} = {}", abs, insert); for i in 0..Self::layer_len[0] { - data.layer0[i+insert] = SubBlock_4{ + data.layer0.push(SubBlock_4{ material: 0, - }; + }); } }, 9 => { + if data.child9[abs.index] != u32::MAX {return;} let insert = data.layer4.len(); + data.layer4.reserve(Self::layer_len[4]); + data.child4.reserve(Self::layer_len[4]); data.child9[abs.index] = insert as u32; + //debug!("set4 {:?} = {}", abs, insert); for i in 0..Self::layer_len[4] { - data.layer4[i+insert] = Block0{ + data.layer4.push(Block0{ material: 0, - }; + }); + data.child4.push(u32::MAX); } }, 13 => { + if data.child13[abs.index] != u32::MAX {return;} let insert = data.layer9.len(); - data.child13[abs.index] = insert as u32; - for i in 0..Self::layer_len[9] { - data.layer9[i+insert] = Chunk5{ - precent_air: 0.2, - percent_forrest: 0.3, - percent_lava: 0.4, - percent_water: 0.1, - }; - //ERROR HERE - unreachable!("finish this like in example"); + data.layer9.reserve(Self::layer_len[9]); + data.child9.reserve(Self::layer_len[9]); + data.child13[abs.index] = insert as u32; + //debug!("set13 {:?} = {}", abs, insert); + for i in 0..Self::layer_len[9] { + data.layer9.push(Chunk5{ + precent_air: 0.2, + percent_forrest: 0.3, + percent_lava: 0.4, + percent_water: 0.1, + }); + data.child9.push(u32::MAX); } }, _ => unreachable!(), } - } - fn drill_up(data: &mut LodData::, parent_abs: AbsIndex) { + fn drill_up(data: &mut LodData::, parent_abs: AbsIndex, delta: &mut Option>) { unreachable!("finish this like in example"); match parent_abs.layer { 0 => { diff --git a/worldsim/src/server/mod.rs b/worldsim/src/server/mod.rs index 2df0a16269..85871ac2ea 100644 --- a/worldsim/src/server/mod.rs +++ b/worldsim/src/server/mod.rs @@ -7,7 +7,6 @@ use std::sync::{ use std::thread::sleep; use std::time::Duration; use std::collections::HashMap; -use vek::*; use crate::{ job::JobManager,