From b297f3b47991799b70636b9d800f965d66db2f68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=A4rtens?= Date: Wed, 16 Oct 2019 11:08:23 +0200 Subject: [PATCH] remove old LodStore Implementation completly, making the new one default. Regression: as of this commit, it failes to compile with rust nightly 2019-10-02 Regression: LodDelta is not implemented yet Regression: LodMakeAtLeast is not implemented yet Regression: Tests are missing --- worldsim/src/lodstore/data.rs | 900 +++++++++++------------------ worldsim/src/lodstore/delta.rs | 2 + worldsim/src/lodstore/mod.rs | 9 +- worldsim/src/lodstore/newdata.rs | 352 ----------- worldsim/src/region/lod/mod.rs | 3 +- worldsim/src/region/lod/npcs.rs | 189 ------ worldsim/src/region/lod/terrain.rs | 195 +------ worldsim/src/region/mod.rs | 22 +- 8 files changed, 371 insertions(+), 1301 deletions(-) delete mode 100644 worldsim/src/lodstore/newdata.rs delete mode 100644 worldsim/src/region/lod/npcs.rs diff --git a/worldsim/src/lodstore/data.rs b/worldsim/src/lodstore/data.rs index 5e886dfe80..7a1e3cde5c 100644 --- a/worldsim/src/lodstore/data.rs +++ b/worldsim/src/lodstore/data.rs @@ -1,596 +1,352 @@ -use std::u32; +use super::area::LodArea; +//use super::delta::LodDelta; +use super::lodpos::{self, multily_with_2_pow_n, relative_to_1d, two_pow_u32, AbsIndex, LodPos}; +use super::index::ToOptionUsize; +use fxhash::FxHashMap; use std::collections::HashMap; +use std::{u16, u32}; use vek::*; -use super::lodpos::{ - self, - LodPos, - AbsIndex, - relative_to_1d, - two_pow_u, -}; -use super::area::{ - LodArea, -}; -use super::delta::{ - LodDelta, -}; - -pub type LodIndex = LodPos; /* -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 + Terminology: + - Layer: the layer of the LoDTree, a tree can have n layers, every layer contains their child layer, except for the last one. + Each layer contains a level, a number from 15-0. the level of each child must be lower than the parents layer! + - Detail: Each Layer contains information about that layer, here called Detail. This is the usable information we want to store in the LoDTree + - LodPos: A LodPos marks a specific position inside the LoDTree, but not their layer. + Each Detail has a LodPos. Multiple Details can exist at the same LodPos on different layers! + - Index: This refers to the actually storage for the index for the next layer (often a u16,u32). + The Index is used to find the child in a spare storage. + - Key: always refers to the storage of a LAYER. Any keyword with KEY is either of type usize or LodPos. + + traits: + - Layer: Every layer must implement this. KEY is the storage Type and either usize/LodPos. Layer is also defined here. + - ParentLayer: Is a Layer that contains a CHILD layer and some const functions based on their const properties + - IndexStore: Every layer must implement this for their Layer::KEY and INDEX is often u16/u32. + The index is accessed by this layer to get the corresponding child. + Every Indexstore is a ParentLayer. + - DetailStore: Every layer must implement this for their KEY. + This is used to store the actual DETAIL of every layer. + !!Calculations will be implemented on these 2 Stores, rather than the actual structs to reduce duplciate coding!! + - ToOptionUsize: to store INDEX in z16/u32 efficiently and move up to usize on calculation + - Traversable: trait is used to get child layer and child Index for a concrete position. + - Materializeable: trait is used to actually return a Detail for a concrete position. + + Actual structs regarding of position in the chain. They represent the Layers and contain the Details, they implement (some of) the 2 Store traits + Naming Scheme is [Nest]Layer + - VecLayer: KEY=usize, stores in Vec, leaf layer + - HashLayer:KEY=LodPos, stores in Vec, leaf layer + - VecNestLayer: KEY=usize, stores in Vec, has childs + - HashNestLayer: KEY=LodPos, stores in Vec, has childs + + Result Structs: + - HashIter/VecIter: Is used to access a layer meta information or Detail via LoDTree.trav().get().get().get().mat(). + When LoDTree.trav() returns a HashIter. + It keeps information to next layer to not recalculate it */ -pub trait LodIntoOptionUsize: Copy { - fn is_some(self) -> bool; - fn into_usize(self) -> usize; +pub trait Layer { + type KEY; + const LEVEL: u8; } -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 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) where Self: Sized; - fn drill_up(data: &mut LodData::, parent_abs: AbsIndex) where Self: Sized; -} - -pub struct CacheLine { - last_parent_abs: AbsIndex, - last_parent_area: LodArea, - //Cache for performance - last_parent_lod: LodIndex, - //unsafe performance improvement if LodData changes between 2 accesses: - last_parent_child_index: usize, - -} - -impl CacheLine { - pub fn new() -> Self { - CacheLine { - last_parent_abs: AbsIndex::new(0,0), /*invalid*/ - last_parent_area: LodArea::new(LodIndex::new(Vec3::new(1,1,1)), LodIndex::new(Vec3::new(0,0,0))), /*never matches*/ - last_parent_lod: LodIndex::new(Vec3::new(0,0,0)), - last_parent_child_index: 0, +pub trait ParentLayer: Layer { + type CHILD: Layer; + fn child(&self) -> &Self::CHILD; + fn CHILDS_PER_OWN_TOTAL() -> usize { + two_pow_u32(Self::LOG2_OF_CHILDS_PER_OWN_TOTAL()) as usize + } + fn LOG2_OF_CHILDS_PER_OWN_TOTAL() -> u8 { + 3 * ({ Self::LEVEL } - Self::CHILD::LEVEL) + } + fn CHILDS_PER_OWN() -> Vec3 { + Vec3 { + x: two_pow_u32(Self::LEVEL - Self::CHILD::LEVEL) as u32, + y: two_pow_u32(Self::LEVEL - Self::CHILD::LEVEL) as u32, + z: two_pow_u32(Self::LEVEL - Self::CHILD::LEVEL) as u32, } } } -#[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, +pub trait IndexStore: ParentLayer { + type INDEX: ToOptionUsize; + fn load(&self, key: Self::KEY) -> Self::INDEX; } -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, +pub trait DetailStore: Layer { + type DETAIL; + fn load(&self, key: Self::KEY) -> &Self::DETAIL; +} + +pub trait Traversable { + fn get(self) -> C; +} +pub trait Materializeable { + fn mat(self) -> T; +} + +//####################################################### + +#[derive(Default, Clone, Debug)] +pub struct VecLayer { + pub detail: Vec, +} +#[derive(Default, Clone, Debug)] +pub struct HashLayer { + pub detail: FxHashMap, +} +#[derive(Default, Clone, Debug)] +pub struct VecNestLayer { + pub detail: Vec, + pub index: Vec, + pub child: C, +} +#[derive(Default, Clone, Debug)] +pub struct HashNestLayer { + pub detail_index: FxHashMap, + pub child: C, +} + +pub struct HashIter<'a, C: DetailStore> { + layer: &'a C, + wanted: LodPos, + layer_lod: LodPos, //LodPos aligned to layer::LEVEL +} +pub struct VecIter<'a, C: DetailStore> { + layer: &'a C, + wanted: LodPos, + layer_lod: LodPos, //LodPos aligned to layer::LEVEL + layer_key: usize, +} + +#[rustfmt::skip] +impl Layer for VecLayer { + type KEY = ( usize ); const LEVEL: u8 = { L }; +} +#[rustfmt::skip] +impl Layer for HashLayer { + type KEY = ( LodPos ); const LEVEL: u8 = { L }; +} +#[rustfmt::skip] +impl Layer for VecNestLayer { + type KEY = ( usize ); const LEVEL: u8 = { L }; +} +#[rustfmt::skip] +impl Layer for HashNestLayer { + type KEY = ( LodPos ); const LEVEL: u8 = { L }; +} + +#[rustfmt::skip] +impl ParentLayer for VecNestLayer { + type CHILD = C; + fn child(&self) -> &Self::CHILD { &self.child } +} +#[rustfmt::skip] +impl ParentLayer for HashNestLayer { + type CHILD = C; + fn child(&self) -> &Self::CHILD { &self.child } +} + +impl HashNestLayer { + fn trav(&self, pos: LodPos) -> HashIter { + HashIter { + layer: &self, + wanted: pos, + layer_lod: pos.align_to_level({ L }), } } - - // 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_level(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_level(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_level(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 - } - - // target_layer is requiered because same LodIndex can exist for multiple layers, and guessing is stupid here - fn int_recursive_get_cached(&self, cache: &mut CacheLine, parent_abs: AbsIndex, child_lod: LodIndex, target_layer:u8) -> AbsIndex { - let mut parent_abs = parent_abs; - let mut old_parent_abs = parent_abs; - while true { - //println!("{} int_recursive_get {} - {}", Self::debug_offset(parent_abs.layer), parent_abs, target_layer); - old_parent_abs = parent_abs; - parent_abs = self.int_get_lockup(parent_abs, child_lod); - if parent_abs.layer <= target_layer { - let parent_width = two_pow_u(old_parent_abs.layer ) as u32; - let parent_lod = child_lod.align_to_level(old_parent_abs.layer); - //TODO: Dont recalc the first 3 values - cache.last_parent_area = LodArea::new(parent_lod, parent_lod + LodIndex::new(Vec3::new(parent_width,parent_width,parent_width))); - cache.last_parent_lod = child_lod.align_to_level(old_parent_abs.layer); - cache.last_parent_child_index = self.int_get_child_index(old_parent_abs); - cache.last_parent_abs = old_parent_abs; - return parent_abs; - } - } - unreachable!(); - } - - pub fn int_get_n_cached(&self, cache: &mut CacheLine, index: LodIndex, layer: u8) -> AbsIndex { - let wanted_abs = if cache.last_parent_area.is_inside(index) { - //println!("yay"); - Self::int_get(cache.last_parent_abs, index, cache.last_parent_lod, cache.last_parent_child_index) - } else { - //println!("nay"); - //println!("{} {}", cache.last_parent_area.lower, cache.last_parent_area.upper); - //println!("{}", index); - let anchor_lod = index.align_to_level(X::anchor_layer_id); - let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]); - self.int_recursive_get_cached(cache, 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 get0_cached(&self, cache: &mut CacheLine, index: LodIndex) -> &X::L0 { &self.layer0[self.int_get_n_cached(cache, index, 0).index] } - - pub fn set15(&mut self, index: LodIndex, value: X::L15, delta: Option<&mut LodDelta>) { - let n = self.int_get_n(index,15).index; - delta.map(|d| d.layer15.push((index, Some(value.clone())))); - self.layer15[n] = value; - } - - pub fn set14(&mut self, index: LodIndex, value: X::L14, delta: Option<&mut LodDelta>) { - let n = self.int_get_n(index,14).index; - delta.map(|d| d.layer14.push((index, Some(value.clone())))); - self.layer14[n] = value; - } - - pub fn set13(&mut self, index: LodIndex, value: X::L13, delta: Option<&mut LodDelta>) { - let n = self.int_get_n(index,13).index; - delta.map(|d| d.layer13.push((index, Some(value.clone())))); - self.layer13[n] = value; - } - - pub fn set12(&mut self, index: LodIndex, value: X::L12, delta: Option<&mut LodDelta>) { - let n = self.int_get_n(index,12).index; - delta.map(|d| d.layer12.push((index, Some(value.clone())))); - self.layer12[n] = value; - } - - pub fn set11(&mut self, index: LodIndex, value: X::L11, delta: Option<&mut LodDelta>) { - let n = self.int_get_n(index,11).index; - delta.map(|d| d.layer11.push((index, Some(value.clone())))); - self.layer11[n] = value; - } - - pub fn set10(&mut self, index: LodIndex, value: X::L10, delta: Option<&mut LodDelta>) { - let n = self.int_get_n(index,10).index; - delta.map(|d| d.layer10.push((index, Some(value.clone())))); - self.layer10[n] = value; - } - - pub fn set9(&mut self, index: LodIndex, value: X::L9, delta: Option<&mut LodDelta>) { - let n = self.int_get_n(index,9).index; - delta.map(|d| d.layer9.push((index, Some(value.clone())))); - self.layer9[n] = value; - } - - pub fn set8(&mut self, index: LodIndex, value: X::L8, delta: Option<&mut LodDelta>) { - let n = self.int_get_n(index,8).index; - delta.map(|d| d.layer8.push((index, Some(value.clone())))); - self.layer8[n] = value; - } - - pub fn set7(&mut self, index: LodIndex, value: X::L7, delta: Option<&mut LodDelta>) { - let n = self.int_get_n(index,7).index; - delta.map(|d| d.layer7.push((index, Some(value.clone())))); - self.layer7[n] = value; - } - - pub fn set6(&mut self, index: LodIndex, value: X::L6, delta: Option<&mut LodDelta>) { - let n = self.int_get_n(index,6).index; - delta.map(|d| d.layer6.push((index, Some(value.clone())))); - self.layer6[n] = value; - } - - pub fn set5(&mut self, index: LodIndex, value: X::L5, delta: Option<&mut LodDelta>) { - let n = self.int_get_n(index,5).index; - delta.map(|d| d.layer5.push((index, Some(value.clone())))); - self.layer5[n] = value; - } - - pub fn set4(&mut self, index: LodIndex, value: X::L4, delta: Option<&mut LodDelta>) { - let n = self.int_get_n(index,4).index; - delta.map(|d| d.layer4.push((index, Some(value.clone())))); - self.layer4[n] = value; - } - - pub fn set3(&mut self, index: LodIndex, value: X::L3, delta: Option<&mut LodDelta>) { - let n = self.int_get_n(index,3).index; - delta.map(|d| d.layer3.push((index, Some(value.clone())))); - self.layer3[n] = value; - } - - pub fn set2(&mut self, index: LodIndex, value: X::L2, delta: Option<&mut LodDelta>) { - let n = self.int_get_n(index,2).index; - delta.map(|d| d.layer2.push((index, Some(value.clone())))); - self.layer2[n] = value; - } - - pub fn set1(&mut self, index: LodIndex, value: X::L1, delta: Option<&mut LodDelta>) { - let n = self.int_get_n(index,1).index; - delta.map(|d| d.layer1.push((index, Some(value.clone())))); - self.layer1[n] = value; - } - - pub fn set0(&mut self, index: LodIndex, value: X::L0, delta: Option<&mut LodDelta>) { - let n = self.int_get_n(index,0).index; - delta.map(|d| d.layer0.push((index, Some(value.clone())))); - self.layer0[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: &Option<&mut LodDelta>) { - 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_level(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); - //let delta = delta.unwrap(); - if parent.layer > target_layer { - // create necessary childs: - X::drill_down(self, parent); - // TODO: Handle correct Delta - /* - if let Some(delta) = delta { - 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 { - let child_lod = LodIndex::new(Vec3::new(x,y,z)); - let i = relative_to_1d(child_lod, parent_lod, child_layer.unwrap(), relative_size: Vec3::new(child_lod_width,child_lod_width,child_lod_width)); - delta.layer15.push((index,self.layer15.get(parent.abs + i))) - } - } - } - }*/ - //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_level(child_layer); - let child_upper = area.upper.align_to_level(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 = lodpos::max(area.lower, child_lower); - let inner_upper = lodpos::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: Option<&mut LodDelta>) { - let anchor_layer_id = X::anchor_layer_id; - let anchor_lower = area.lower.align_to_level(anchor_layer_id); - let anchor_upper = area.upper.align_to_level(anchor_layer_id); - let lower_xyz = anchor_lower.get(); - let upper_xyz = anchor_upper.get(); - let anchor_width = lodpos::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 { - let child_lod_upper = Self::get_last_child_lod(anchor_lod, anchor_abs.layer); - - let inner_lower = lodpos::max(area.lower, anchor_lod); - let inner_upper = lodpos::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") +#[rustfmt::skip] +impl IndexStore for VecNestLayer { + type INDEX = I; + fn load(&self, key: Self::KEY) -> Self::INDEX { self.index[key] } +} +#[rustfmt::skip] +impl IndexStore for HashNestLayer { + type INDEX = I; + fn load(&self, key: Self::KEY) -> Self::INDEX { + debug_assert_eq!(key, key.align_to_level({ L })); + self.detail_index[&key].1 } } -impl LodIntoOptionUsize for u32 { - fn is_some(self) -> bool { - self != u32::MAX +#[rustfmt::skip] +impl DetailStore for VecNestLayer { + type DETAIL = T; + fn load(&self, key: Self::KEY) -> &Self::DETAIL { + &self.detail[key] } - fn into_usize(self) -> usize { - self as usize +} +#[rustfmt::skip] +impl DetailStore for HashNestLayer { + type DETAIL = T; + fn load(&self, key: LodPos) -> &Self::DETAIL { + debug_assert_eq!(key, key.align_to_level({ L })); + &self.detail_index[&key].0 + } +} +#[rustfmt::skip] +impl DetailStore for VecLayer { + type DETAIL = T; + fn load(&self, key: usize) -> &Self::DETAIL { + &self.detail[key] + } +} +#[rustfmt::skip] +impl DetailStore for HashLayer { + type DETAIL = T; + fn load(&self, key: LodPos) -> &Self::DETAIL { + debug_assert_eq!(key, key.align_to_level({ L })); + &self.detail[&key] + } +} + +impl<'a, L: DetailStore + IndexStore> Traversable> +for HashIter<'a, L> + where + L::CHILD: DetailStore, { + fn get(self) -> VecIter<'a, L::CHILD> { + let child_lod = self.wanted.align_to_level(L::CHILD::LEVEL ); + let pos_offset = relative_to_1d(child_lod, self.layer_lod, L::CHILD::LEVEL, L::CHILDS_PER_OWN()); + let layer_key = ( multily_with_2_pow_n( IndexStore::load(self.layer, self.layer_lod).into_usize(), L::LOG2_OF_CHILDS_PER_OWN_TOTAL()) ) + pos_offset; + VecIter { + layer: self.layer.child(), + wanted: self.wanted, + layer_key, + layer_lod: child_lod, + } + } +} + +impl<'a, L: DetailStore + IndexStore> Traversable> +for VecIter<'a, L> + where + L::CHILD: DetailStore, { + fn get(self) -> VecIter<'a, L::CHILD> { + let child_lod = self.wanted.align_to_level(L::CHILD::LEVEL ); + let pos_offset = relative_to_1d(child_lod, self.layer_lod, L::CHILD::LEVEL, L::CHILDS_PER_OWN()); + let layer_key = ( multily_with_2_pow_n( IndexStore::load(self.layer, self.layer_key).into_usize(), L::LOG2_OF_CHILDS_PER_OWN_TOTAL()) ) + pos_offset; + VecIter { + layer: self.layer.child(), + wanted: self.wanted, + layer_key, + layer_lod: child_lod, + } + } +} + +impl<'a, L: DetailStore> Materializeable<&'a L::DETAIL> for HashIter<'a, L> { + fn mat(self) -> &'a L::DETAIL { + DetailStore::load(self.layer, self.layer_lod) + } +} + +impl<'a, L: DetailStore> Materializeable<&'a L::DETAIL> for VecIter<'a, L> { + fn mat(self) -> &'a L::DETAIL { + DetailStore::load(self.layer, self.layer_key) + } +} + +#[rustfmt::skip] +pub type ExampleData = +HashNestLayer< + VecNestLayer< + VecNestLayer< + VecLayer< + i8, 0 + > ,Option<()>, u16, 2 + > ,() , u32, 3 + > ,() ,u16, 4 +>; + +#[cfg(test)] +mod tests { + use crate::lodstore::data::*; + use test::Bencher; + + fn gen_simple_example() -> ExampleData { + let mut detail_index = FxHashMap::default(); + detail_index.insert(LodPos::xyz(0, 0, 0), ((), 0)); + ExampleData { + detail_index, + child: VecNestLayer { + detail: vec!((),(),()), + index: vec!(0,1,u32::MAX), + child: VecNestLayer { + detail: vec!(None,None,None,Some(()),Some(()),None,None,None,None,None,None,None,None,None,None,None), + index: vec!(0,u16::MAX,u16::MAX,0,u16::MAX,u16::MAX,u16::MAX,u16::MAX,u16::MAX,u16::MAX,u16::MAX,u16::MAX,u16::MAX,u16::MAX,u16::MAX,u16::MAX), + child: VecLayer { + detail: vec!(7,6,5,4,3,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), + }, + }, + }, + } + } + + + #[test] + fn compilation() { + let x = ExampleData::default(); + let i = LodPos::xyz(0, 1, 2); + if false { + let y = x.trav(i); + let ttc = y.get().get().get(); + let tt = ttc.mat(); + } + } + + #[test] + fn access_first_element() { + let x = gen_simple_example(); + let i = LodPos::xyz(0, 0, 0); + assert_eq!(*x.trav(i).get().get().get().mat(), 7_i8); + } + + #[test] + fn access_simple_elements() { + let x = gen_simple_example(); + assert_eq!(*x.trav(LodPos::xyz(0, 0, 0)).get().get().get().mat(), 7_i8); + assert_eq!(*x.trav(LodPos::xyz(0, 0, 1)).get().get().get().mat(), 6_i8); + assert_eq!(*x.trav(LodPos::xyz(0, 0, 2)).get().get().get().mat(), 5_i8); + assert_eq!(*x.trav(LodPos::xyz(0, 0, 3)).get().get().get().mat(), 4_i8); + assert_eq!(*x.trav(LodPos::xyz(0, 1, 0)).get().get().get().mat(), 3_i8); + assert_eq!(*x.trav(LodPos::xyz(0, 1, 1)).get().get().get().mat(), 2_i8); + assert_eq!(*x.trav(LodPos::xyz(0, 1, 2)).get().get().get().mat(), 1_i8); + assert_eq!(*x.trav(LodPos::xyz(0, 1, 3)).get().get().get().mat(), 0_i8); + assert_eq!(*x.trav(LodPos::xyz(0, 3, 0)).get().get().get().mat(), 0_i8); + assert_eq!(*x.trav(LodPos::xyz(1, 0, 0)).get().get().get().mat(), 0_i8); + assert_eq!(*x.trav(LodPos::xyz(0, 2, 0)).get().get().get().mat(), 0_i8); + } + + #[bench] + fn bench_access_trav(b: &mut Bencher) { + let x = gen_simple_example(); + let access = LodPos::xyz(0, 0, 0); + b.iter(|| x.trav(access)); + } + + #[bench] + fn bench_access_3(b: &mut Bencher) { + let x = gen_simple_example(); + let access = LodPos::xyz(0, 0, 0); + b.iter(|| x.trav(access).mat()); + } + + #[bench] + fn bench_access_0(b: &mut Bencher) { + let x = gen_simple_example(); + let access = LodPos::xyz(0, 0, 0); + b.iter(|| x.trav(access).get().get().get().mat()); + } + + #[bench] + fn bench_access_0_best_time(b: &mut Bencher) { + let x = gen_simple_example(); + let access = LodPos::xyz(0, 0, 0); + for _ in 0..10000 { + //fill up the caches + x.trav(access).get().get().get().mat(); + } + b.iter(|| x.trav(access).get().get().get().mat()); } } \ No newline at end of file diff --git a/worldsim/src/lodstore/delta.rs b/worldsim/src/lodstore/delta.rs index b420998f25..c322a24c30 100644 --- a/worldsim/src/lodstore/delta.rs +++ b/worldsim/src/lodstore/delta.rs @@ -1,3 +1,4 @@ +/* use super::{ data::{ LodData, @@ -167,3 +168,4 @@ impl LodDelta { } } } +*/ \ No newline at end of file diff --git a/worldsim/src/lodstore/mod.rs b/worldsim/src/lodstore/mod.rs index 6b82d63994..973df97e16 100644 --- a/worldsim/src/lodstore/mod.rs +++ b/worldsim/src/lodstore/mod.rs @@ -1,8 +1,11 @@ pub mod lodpos; pub mod area; pub mod index; -pub mod newdata; pub mod data; pub mod delta; -pub use data::LodData; -pub use data::LodConfig; \ No newline at end of file +pub use data::{ + HashNestLayer, + VecNestLayer, + HashLayer, + VecLayer, +}; \ No newline at end of file diff --git a/worldsim/src/lodstore/newdata.rs b/worldsim/src/lodstore/newdata.rs deleted file mode 100644 index 5f5a668f85..0000000000 --- a/worldsim/src/lodstore/newdata.rs +++ /dev/null @@ -1,352 +0,0 @@ -use super::area::LodArea; -use super::delta::LodDelta; -use super::lodpos::{self, multily_with_2_pow_n, relative_to_1d, two_pow_u32, AbsIndex, LodPos}; -use super::index::ToOptionUsize; -use fxhash::FxHashMap; -use std::collections::HashMap; -use std::{u16, u32}; -use vek::*; - -/* - Terminology: - - Layer: the layer of the LoDTree, a tree can have n layers, every layer contains their child layer, except for the last one. - Each layer contains a level, a number from 15-0. the level of each child must be lower than the parents layer! - - Detail: Each Layer contains information about that layer, here called Detail. This is the usable information we want to store in the LoDTree - - LodPos: A LodPos marks a specific position inside the LoDTree, but not their layer. - Each Detail has a LodPos. Multiple Details can exist at the same LodPos on different layers! - - Index: This refers to the actually storage for the index for the next layer (often a u16,u32). - The Index is used to find the child in a spare storage. - - Key: always refers to the storage of a LAYER. Any keyword with KEY is either of type usize or LodPos. - - traits: - - Layer: Every layer must implement this. KEY is the storage Type and either usize/LodPos. Layer is also defined here. - - ParentLayer: Is a Layer that contains a CHILD layer and some const functions based on their const properties - - IndexStore: Every layer must implement this for their Layer::KEY and INDEX is often u16/u32. - The index is accessed by this layer to get the corresponding child. - Every Indexstore is a ParentLayer. - - DetailStore: Every layer must implement this for their KEY. - This is used to store the actual DETAIL of every layer. - !!Calculations will be implemented on these 2 Stores, rather than the actual structs to reduce duplciate coding!! - - ToOptionUsize: to store INDEX in z16/u32 efficiently and move up to usize on calculation - - Traversable: trait is used to get child layer and child Index for a concrete position. - - Materializeable: trait is used to actually return a Detail for a concrete position. - - Actual structs regarding of position in the chain. They represent the Layers and contain the Details, they implement (some of) the 2 Store traits - Naming Scheme is [Nest]Layer - - VecLayer: KEY=usize, stores in Vec, leaf layer - - HashLayer:KEY=LodPos, stores in Vec, leaf layer - - VecNestLayer: KEY=usize, stores in Vec, has childs - - HashNestLayer: KEY=LodPos, stores in Vec, has childs - - Result Structs: - - HashIter/VecIter: Is used to access a layer meta information or Detail via LoDTree.trav().get().get().get().mat(). - When LoDTree.trav() returns a HashIter. - It keeps information to next layer to not recalculate it -*/ - -pub trait Layer { - type KEY; - const LEVEL: u8; -} - -pub trait ParentLayer: Layer { - type CHILD: Layer; - fn child(&self) -> &Self::CHILD; - fn CHILDS_PER_OWN_TOTAL() -> usize { - two_pow_u32(Self::LOG2_OF_CHILDS_PER_OWN_TOTAL()) as usize - } - fn LOG2_OF_CHILDS_PER_OWN_TOTAL() -> u8 { - 3 * ({ Self::LEVEL } - Self::CHILD::LEVEL) - } - fn CHILDS_PER_OWN() -> Vec3 { - Vec3 { - x: two_pow_u32(Self::LEVEL - Self::CHILD::LEVEL) as u32, - y: two_pow_u32(Self::LEVEL - Self::CHILD::LEVEL) as u32, - z: two_pow_u32(Self::LEVEL - Self::CHILD::LEVEL) as u32, - } - } -} - -pub trait IndexStore: ParentLayer { - type INDEX: ToOptionUsize; - fn load(&self, key: Self::KEY) -> Self::INDEX; -} - -pub trait DetailStore: Layer { - type DETAIL; - fn load(&self, key: Self::KEY) -> &Self::DETAIL; -} - -pub trait Traversable { - fn get(self) -> C; -} -pub trait Materializeable { - fn mat(self) -> T; -} - -//####################################################### - -#[derive(Default)] -pub struct VecLayer { - pub detail: Vec, -} -#[derive(Default)] -pub struct HashLayer { - pub detail: FxHashMap, -} -#[derive(Default)] -pub struct VecNestLayer { - pub detail: Vec, - pub index: Vec, - pub child: C, -} -#[derive(Default)] -pub struct HashNestLayer { - pub detail_index: FxHashMap, - pub child: C, -} - -pub struct HashIter<'a, C: DetailStore> { - layer: &'a C, - wanted: LodPos, - layer_lod: LodPos, //LodPos aligned to layer::LEVEL -} -pub struct VecIter<'a, C: DetailStore> { - layer: &'a C, - wanted: LodPos, - layer_lod: LodPos, //LodPos aligned to layer::LEVEL - layer_key: usize, -} - -#[rustfmt::skip] -impl Layer for VecLayer { - type KEY = ( usize ); const LEVEL: u8 = { L }; -} -#[rustfmt::skip] -impl Layer for HashLayer { - type KEY = ( LodPos ); const LEVEL: u8 = { L }; -} -#[rustfmt::skip] -impl Layer for VecNestLayer { - type KEY = ( usize ); const LEVEL: u8 = { L }; -} -#[rustfmt::skip] -impl Layer for HashNestLayer { - type KEY = ( LodPos ); const LEVEL: u8 = { L }; -} - -#[rustfmt::skip] -impl ParentLayer for VecNestLayer { - type CHILD = C; - fn child(&self) -> &Self::CHILD { &self.child } -} -#[rustfmt::skip] -impl ParentLayer for HashNestLayer { - type CHILD = C; - fn child(&self) -> &Self::CHILD { &self.child } -} - -impl HashNestLayer { - fn trav(&self, pos: LodPos) -> HashIter { - HashIter { - layer: &self, - wanted: pos, - layer_lod: pos.align_to_level({ L }), - } - } -} - -#[rustfmt::skip] -impl IndexStore for VecNestLayer { - type INDEX = I; - fn load(&self, key: Self::KEY) -> Self::INDEX { self.index[key] } -} -#[rustfmt::skip] -impl IndexStore for HashNestLayer { - type INDEX = I; - fn load(&self, key: Self::KEY) -> Self::INDEX { - debug_assert_eq!(key, key.align_to_level({ L })); - self.detail_index[&key].1 - } -} - -#[rustfmt::skip] -impl DetailStore for VecNestLayer { - type DETAIL = T; - fn load(&self, key: Self::KEY) -> &Self::DETAIL { - &self.detail[key] - } -} -#[rustfmt::skip] -impl DetailStore for HashNestLayer { - type DETAIL = T; - fn load(&self, key: LodPos) -> &Self::DETAIL { - debug_assert_eq!(key, key.align_to_level({ L })); - &self.detail_index[&key].0 - } -} -#[rustfmt::skip] -impl DetailStore for VecLayer { - type DETAIL = T; - fn load(&self, key: usize) -> &Self::DETAIL { - &self.detail[key] - } -} -#[rustfmt::skip] -impl DetailStore for HashLayer { - type DETAIL = T; - fn load(&self, key: LodPos) -> &Self::DETAIL { - debug_assert_eq!(key, key.align_to_level({ L })); - &self.detail[&key] - } -} - -impl<'a, L: DetailStore + IndexStore> Traversable> - for HashIter<'a, L> -where - L::CHILD: DetailStore, { - fn get(self) -> VecIter<'a, L::CHILD> { - let child_lod = self.wanted.align_to_level(L::CHILD::LEVEL ); - let pos_offset = relative_to_1d(child_lod, self.layer_lod, L::CHILD::LEVEL, L::CHILDS_PER_OWN()); - let layer_key = ( multily_with_2_pow_n( IndexStore::load(self.layer, self.layer_lod).into_usize(), L::LOG2_OF_CHILDS_PER_OWN_TOTAL()) ) + pos_offset; - VecIter { - layer: self.layer.child(), - wanted: self.wanted, - layer_key, - layer_lod: child_lod, - } - } -} - -impl<'a, L: DetailStore + IndexStore> Traversable> - for VecIter<'a, L> -where - L::CHILD: DetailStore, { - fn get(self) -> VecIter<'a, L::CHILD> { - let child_lod = self.wanted.align_to_level(L::CHILD::LEVEL ); - let pos_offset = relative_to_1d(child_lod, self.layer_lod, L::CHILD::LEVEL, L::CHILDS_PER_OWN()); - let layer_key = ( multily_with_2_pow_n( IndexStore::load(self.layer, self.layer_key).into_usize(), L::LOG2_OF_CHILDS_PER_OWN_TOTAL()) ) + pos_offset; - VecIter { - layer: self.layer.child(), - wanted: self.wanted, - layer_key, - layer_lod: child_lod, - } - } -} - -impl<'a, L: DetailStore> Materializeable<&'a L::DETAIL> for HashIter<'a, L> { - fn mat(self) -> &'a L::DETAIL { - DetailStore::load(self.layer, self.layer_lod) - } -} - -impl<'a, L: DetailStore> Materializeable<&'a L::DETAIL> for VecIter<'a, L> { - fn mat(self) -> &'a L::DETAIL { - DetailStore::load(self.layer, self.layer_key) - } -} - -#[rustfmt::skip] -pub type ExampleData = - HashNestLayer< - VecNestLayer< - VecNestLayer< - VecLayer< - i8, 0 - > ,Option<()>, u16, 2 - > ,() , u32, 3 - > ,() ,u16, 4 - >; - -#[cfg(test)] -mod tests { - use crate::lodstore::newdata::*; - use test::Bencher; - - fn gen_simple_example() -> ExampleData { - let mut detail_index = FxHashMap::default(); - detail_index.insert(LodPos::xyz(0, 0, 0), ((), 0)); - ExampleData { - detail_index, - child: VecNestLayer { - detail: vec!((),(),()), - index: vec!(0,1,u32::MAX), - child: VecNestLayer { - detail: vec!(None,None,None,Some(()),Some(()),None,None,None,None,None,None,None,None,None,None,None), - index: vec!(0,u16::MAX,u16::MAX,0,u16::MAX,u16::MAX,u16::MAX,u16::MAX,u16::MAX,u16::MAX,u16::MAX,u16::MAX,u16::MAX,u16::MAX,u16::MAX,u16::MAX), - child: VecLayer { - detail: vec!(7,6,5,4,3,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), - }, - }, - }, - } - } - - - #[test] - fn compilation() { - let x = ExampleData::default(); - let i = LodPos::xyz(0, 1, 2); - if false { - let y = x.trav(i); - let ttc = y.get().get().get(); - let tt = ttc.mat(); - } - } - - #[test] - fn access_first_element() { - let x = gen_simple_example(); - let i = LodPos::xyz(0, 0, 0); - assert_eq!(*x.trav(i).get().get().get().mat(), 7_i8); - } - - #[test] - fn access_simple_elements() { - let x = gen_simple_example(); - assert_eq!(*x.trav(LodPos::xyz(0, 0, 0)).get().get().get().mat(), 7_i8); - assert_eq!(*x.trav(LodPos::xyz(0, 0, 1)).get().get().get().mat(), 6_i8); - assert_eq!(*x.trav(LodPos::xyz(0, 0, 2)).get().get().get().mat(), 5_i8); - assert_eq!(*x.trav(LodPos::xyz(0, 0, 3)).get().get().get().mat(), 4_i8); - assert_eq!(*x.trav(LodPos::xyz(0, 1, 0)).get().get().get().mat(), 3_i8); - assert_eq!(*x.trav(LodPos::xyz(0, 1, 1)).get().get().get().mat(), 2_i8); - assert_eq!(*x.trav(LodPos::xyz(0, 1, 2)).get().get().get().mat(), 1_i8); - assert_eq!(*x.trav(LodPos::xyz(0, 1, 3)).get().get().get().mat(), 0_i8); - assert_eq!(*x.trav(LodPos::xyz(0, 3, 0)).get().get().get().mat(), 0_i8); - assert_eq!(*x.trav(LodPos::xyz(1, 0, 0)).get().get().get().mat(), 0_i8); - assert_eq!(*x.trav(LodPos::xyz(0, 2, 0)).get().get().get().mat(), 0_i8); - } - - #[bench] - fn bench_access_trav(b: &mut Bencher) { - let x = gen_simple_example(); - let access = LodPos::xyz(0, 0, 0); - b.iter(|| x.trav(access)); - } - - #[bench] - fn bench_access_3(b: &mut Bencher) { - let x = gen_simple_example(); - let access = LodPos::xyz(0, 0, 0); - b.iter(|| x.trav(access).mat()); - } - - #[bench] - fn bench_access_0(b: &mut Bencher) { - let x = gen_simple_example(); - let access = LodPos::xyz(0, 0, 0); - b.iter(|| x.trav(access).get().get().get().mat()); - } - - #[bench] - fn bench_access_0_best_time(b: &mut Bencher) { - let x = gen_simple_example(); - let access = LodPos::xyz(0, 0, 0); - for _ in 0..10000 { - //fill up the caches - x.trav(access).get().get().get().mat(); - } - b.iter(|| x.trav(access).get().get().get().mat()); - } -} \ No newline at end of file diff --git a/worldsim/src/region/lod/mod.rs b/worldsim/src/region/lod/mod.rs index bbd449f607..71b893d511 100644 --- a/worldsim/src/region/lod/mod.rs +++ b/worldsim/src/region/lod/mod.rs @@ -1,2 +1 @@ -pub mod terrain; -mod example; \ No newline at end of file +pub mod terrain; \ No newline at end of file diff --git a/worldsim/src/region/lod/npcs.rs b/worldsim/src/region/lod/npcs.rs deleted file mode 100644 index 4ec479837e..0000000000 --- a/worldsim/src/region/lod/npcs.rs +++ /dev/null @@ -1,189 +0,0 @@ -use crate::lodstore::{ - LodData, - LodConfig, - index::LodPos, - index::AbsIndex, - delta::LodDelta, -}; -use vek::*; -use std::u32; -pub type LodIndex = LodPos; - -#[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 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) { - 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) { - 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 37e3bed9fc..55b68c653d 100644 --- a/worldsim/src/region/lod/terrain.rs +++ b/worldsim/src/region/lod/terrain.rs @@ -1,199 +1,50 @@ use crate::lodstore::{ - LodData, - LodConfig, + HashNestLayer, + VecNestLayer, + HashLayer, + VecLayer, lodpos::LodPos, lodpos::AbsIndex, - delta::LodDelta, }; use vek::*; use std::u32; pub type LodIndex = LodPos; -#[derive(Debug, Clone)] -pub struct Region9 { +#[derive(Debug, Clone, Default)] +pub struct Region { precent_air: f32, percent_forrest: f32, percent_lava: f32, percent_water: f32, } -#[derive(Debug, Clone)] -pub struct Chunk5 { +#[derive(Debug, Clone, Default)] +pub struct Chunk { precent_air: f32, percent_forrest: f32, percent_lava: f32, percent_water: f32, } -#[derive(Debug, Clone)] -pub struct Block0 { +#[derive(Debug, Clone, Default)] +pub struct Block { material: u32, } -#[derive(Debug, Clone)] -pub struct SubBlock_4 { +#[derive(Debug, Clone, Default)] +pub struct SubBlock { material: u32, } -#[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 = (); - - type I0 = (); - type I1 = (); - type I2 = (); - type I3 = (); - type I4 = u32; // In reality 2^(16*3) SubBlock_4 should be possible, but 2^48 subblocks would kill anything anyway, so save 2 bytes here - type I5 = (); - type I6 = (); - type I7 = (); - type I8 = (); - type I9 = u32; // see Block0 2^(12*3) - type I10 = (); - type I11 = (); - type I12 = (); - type I13 = u32; // Chunk5 2^(7*3), this is valid - type I14 = (); - type I15 = (); - - type Additional = (); - - const anchor_layer_id: u8 = 13; - - const layer_volume: [Vec3; 16] = [ - Vec3{x: 16, y: 16, z: 16}, - Vec3{x: 0, y: 0, z: 0}, - Vec3{x: 0, y: 0, z: 0}, - Vec3{x: 0, y: 0, z: 0}, - Vec3{x: 32, y: 32, z: 32}, - 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: 16, y: 16, z: 16}, - 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}, - ]; - const child_layer_id: [Option; 16] = [ - None, - None, - None, - None, - Some(0), - None, - None, - None, - None, - Some(5), - None, - None, - None, - Some(9), - None, - None, - ]; - - fn setup(&mut self) { - - } - - fn drill_down(data: &mut LodData::, abs: AbsIndex) { - 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) { - 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 +#[rustfmt::skip] +pub type TerrainLod = + HashNestLayer< + VecNestLayer< + VecNestLayer< + VecLayer< + SubBlock, 0 + > ,Block, u16, 4 // In reality 2^(16*3) SubBlock_4 should be possible, but 2^48 subblocks would kill anything anyway, so save 75% bytes here. Limit is 65536 full blocks in SubBlocks, means (2^16) * ((2^4)^3) = 268 million + > ,Chunk , u32,9 // we coult use u16 which would allow 2^31 blocks, however the world could have 2^33 blocks inside, which would mean only 25% could ever be on block level, which is prob never reacher, however ue to handling neibors and that this only would save 1/4 MB on this level, we just skip it for now + > ,Region ,u16, 13 + >; \ No newline at end of file diff --git a/worldsim/src/region/mod.rs b/worldsim/src/region/mod.rs index 2a2608ad2e..17a6f98251 100644 --- a/worldsim/src/region/mod.rs +++ b/worldsim/src/region/mod.rs @@ -6,18 +6,18 @@ use crate::{ regionmanager::meta::RegionId, job::JobManager, }; -use lod::terrain::Terrain; +use lod::terrain::TerrainLod; #[derive(Debug, Clone)] pub struct Region { id: RegionId, jobmanager: Arc, - pub block: Terrain, - temp: Terrain, - light: Terrain, - evil: Terrain, - civ: Terrain, + pub block: TerrainLod, + temp: TerrainLod, + light: TerrainLod, + evil: TerrainLod, + civ: TerrainLod, } impl Region { @@ -25,11 +25,11 @@ impl Region { Self { id, jobmanager, - block: Terrain::new(), - temp: Terrain::new(), - light: Terrain::new(), - evil: Terrain::new(), - civ: Terrain::new(), + block: TerrainLod::default(), + temp: TerrainLod::default(), + light: TerrainLod::default(), + evil: TerrainLod::default(), + civ: TerrainLod::default(), } } }