diff --git a/worldsim/src/lodstore/data.rs b/worldsim/src/lodstore/data.rs index 6a5d088645..44199d7434 100644 --- a/worldsim/src/lodstore/data.rs +++ b/worldsim/src/lodstore/data.rs @@ -1,64 +1,13 @@ use super::index::ToOptionUsize; -use super::lodpos::{multily_with_2_pow_n, relative_to_1d, two_pow_u32, LodPos}; +use super::lodpos::LodPos; +use super::layer::{Layer, ParentLayer}; +#[allow(unused_imports)] //not unsued, cargo is just to stupud to detect that +use super::traversable::Traversable; +#[allow(unused_imports)] +use super::materializeable::Materializeable; +#[allow(unused_imports)] +use super::entrylayer::EntryLayer; use fxhash::FxHashMap; -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 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. - - DetailStoreMut: allows mut borrow for Vec types (Hash not supported) - !!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. - - EntryLayer: the topmost layer which can generate a Traversable for a LodPos must implement this, e.g. needed by delta - - 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; - const CHILDS_PER_OWN_TOTAL: usize = two_pow_u32(Self::LOG2_OF_CHILDS_PER_OWN_TOTAL) as usize; - const LOG2_OF_CHILDS_PER_OWN_TOTAL: u8 = 3 * ({ Self::LEVEL } - Self::CHILD::LEVEL); - const 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; @@ -70,23 +19,12 @@ pub trait DetailStore: Layer { fn load(&self, key: Self::KEY) -> &Self::DETAIL; fn save(&mut self, key: Self::KEY, detail: Self::DETAIL); } +// TODO: There should be a Trait: to provide a independent Hash which doesnt choose even when having mut access to an element. +// then we can store e.g. an ID within the detail of every region (wich are prob 1kb, and get load_mut behavior for free pub trait DetailStoreMut: DetailStore { fn load_mut(&mut self, key: Self::KEY) -> &mut Self::DETAIL; } -pub trait Traversable { - type TRAV_CHILD; - fn get(self) -> Self::TRAV_CHILD; -} -pub trait Materializeable { - type MAT_CHILD; - fn mat(self) -> Self::MAT_CHILD; -} -pub trait EntryLayer<'a> { - type TRAV: Traversable; - fn trav(&'a self, pos: LodPos) -> Self::TRAV; -} - //####################################################### #[derive(Default, Clone)] @@ -110,63 +48,15 @@ pub struct HashNestLayer { } pub struct HashIter<'a, C: DetailStore> { - layer: &'a C, - wanted: LodPos, - layer_lod: LodPos, //LodPos aligned to layer::LEVEL + pub( super ) layer: &'a C, + pub( super ) wanted: LodPos, + pub( super ) 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, -} - -impl Layer for VecLayer { - type KEY = (usize); - const LEVEL: u8 = { L }; -} -impl Layer for HashLayer { - type KEY = (LodPos); - const LEVEL: u8 = { L }; -} -impl Layer for VecNestLayer { - type KEY = (usize); - const LEVEL: u8 = { L }; -} -impl Layer for HashNestLayer { - type KEY = (LodPos); - const LEVEL: u8 = { L }; -} - -impl ParentLayer - for VecNestLayer -{ - type CHILD = C; - fn child(&self) -> &Self::CHILD { - &self.child - } -} -impl ParentLayer - for HashNestLayer -{ - type CHILD = C; - fn child(&self) -> &Self::CHILD { - &self.child - } -} - -impl<'a, C: 'a + DetailStore, T: 'a, I: 'a + ToOptionUsize, const L: u8> EntryLayer<'a> - for HashNestLayer -{ - type TRAV = HashIter<'a, HashNestLayer>; - - fn trav(&'a self, pos: LodPos) -> Self::TRAV { - HashIter { - layer: &self, - wanted: pos, - layer_lod: pos.align_to_level({ L }), - } - } + pub( super ) layer: &'a C, + pub( super ) wanted: LodPos, + pub( super ) layer_lod: LodPos, //LodPos aligned to layer::LEVEL + pub( super ) layer_key: usize, } impl IndexStore for VecNestLayer { @@ -241,80 +131,11 @@ impl DetailStore for HashLayer { } } -impl<'a, L: DetailStore + IndexStore> Traversable for HashIter<'a, L> -where - L::CHILD: DetailStore, -{ - type TRAV_CHILD = VecIter<'a, L::CHILD>; - - 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, -{ - type TRAV_CHILD = VecIter<'a, L::CHILD>; - - 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 for HashIter<'a, L> { - type MAT_CHILD = &'a L::DETAIL; - - fn mat(self) -> &'a L::DETAIL { - DetailStore::load(self.layer, self.layer_lod) - } -} - -impl<'a, L: DetailStore> Materializeable for VecIter<'a, L> { - type MAT_CHILD = &'a L::DETAIL; - - fn mat(self) -> &'a L::DETAIL { - DetailStore::load(self.layer, self.layer_key) - } -} - #[cfg(test)] pub mod tests { use crate::lodstore::data::*; use test::Bencher; + use std::{u16, u32}; #[rustfmt::skip] pub type ExampleData = diff --git a/worldsim/src/lodstore/delta.rs b/worldsim/src/lodstore/delta.rs index 8846a99cd0..f3063c0d49 100644 --- a/worldsim/src/lodstore/delta.rs +++ b/worldsim/src/lodstore/delta.rs @@ -1,5 +1,12 @@ -use super::data::{DetailStore, EntryLayer, Layer, Materializeable, ParentLayer, Traversable}; +use super::data::{DetailStore}; use super::lodpos::LodPos; +use super::layer::{Layer}; +#[allow(unused_imports)] //not unsued, cargo is just to stupud to detect that +use super::entrylayer::EntryLayer; +#[allow(unused_imports)] +use super::traversable::Traversable; +#[allow(unused_imports)] +use super::materializeable::Materializeable; use std::marker::PhantomData; /* A LodDelta applies a change to a Lod @@ -12,13 +19,6 @@ use std::marker::PhantomData; However i belive that most algorithms only change every Value once. */ -/* -The Idea is to create a DeltaWriter that has a mutable Detla and Data and implements the Data interaces. -While it borrows a mutable reference to both it locks both with rusts system -When the writing is done, we destroy the Writer but keep the Delta and Data. -The DeltaWriter will output its own iterator, -We only need a traversable trait -*/ pub trait Delta: Layer {} #[derive(Default, Clone)] @@ -37,96 +37,23 @@ pub struct DeltaWriter<'a, C: EntryLayer<'a> + DetailStore, D: EntryLayer<'a> + } pub struct VecDataIter<'a, D: Delta> { - layer: &'a D, + pub( super ) layer: &'a D, } pub struct DataWriterIter<'a, DT: 'a, CT: 'a> { - delta_iter: DT, - data_iter: CT, - _a: PhantomData<&'a ()>, + pub( super ) delta_iter: DT, + pub( super ) data_iter: CT, + pub( super ) _a: PhantomData<&'a ()>, } //####################################################### -impl Layer for VecDelta { - type KEY = (usize); - const LEVEL: u8 = { L }; -} -impl Layer for VecNestDelta { - type KEY = (usize); - const LEVEL: u8 = { L }; -} - -impl ParentLayer for VecNestDelta { - type CHILD = D; - fn child(&self) -> &Self::CHILD { - &self.child - } -} - impl<'a, C: DetailStore + EntryLayer<'a>, D: Delta + EntryLayer<'a>> DeltaWriter<'a, C, D> { pub fn new(delta: &'a mut D, data: &'a mut C) -> Self { DeltaWriter { delta, data } } } -impl<'a, D: 'a + Delta, T: 'a, const L: u8> EntryLayer<'a> for VecNestDelta { - type TRAV = VecDataIter<'a, VecNestDelta>; - - fn trav(&'a self, _pos: LodPos) -> Self::TRAV { - VecDataIter { layer: &self } - } -} - -impl<'a, C: DetailStore + EntryLayer<'a>, D: Delta + EntryLayer<'a>> EntryLayer<'a> - for DeltaWriter<'a, C, D> -where - <>::TRAV as Traversable>::TRAV_CHILD: Traversable, - <>::TRAV as Traversable>::TRAV_CHILD: Traversable, -{ - type TRAV = DataWriterIter<'a, D::TRAV, C::TRAV>; - fn trav(&'a self, pos: LodPos) -> DataWriterIter { - DataWriterIter { - delta_iter: self.delta.trav(pos), - data_iter: self.data.trav(pos), - _a: PhantomData::<&'a ()>::default(), - } - } -} - -impl<'a, D: Delta + ParentLayer> Traversable for VecDataIter<'a, D> -where - D::CHILD: Delta, -{ - type TRAV_CHILD = VecDataIter<'a, D::CHILD>; - - fn get(self) -> VecDataIter<'a, D::CHILD> { - VecDataIter { - layer: self.layer.child(), - } - } -} - -impl<'a, DT: Traversable, CT: Traversable> Traversable for DataWriterIter<'a, DT, CT> { - type TRAV_CHILD = DataWriterIter<'a, DT::TRAV_CHILD, CT::TRAV_CHILD>; - - fn get(self) -> DataWriterIter<'a, DT::TRAV_CHILD, CT::TRAV_CHILD> { - DataWriterIter { - delta_iter: self.delta_iter.get(), - data_iter: self.data_iter.get(), - _a: PhantomData::<&'a ()>::default(), - } - } -} - -impl<'a, DT, CT: Materializeable> Materializeable for DataWriterIter<'a, DT, CT> { - type MAT_CHILD = CT::MAT_CHILD; - - fn mat(self) -> CT::MAT_CHILD { - self.data_iter.mat() - } -} - impl Delta for VecDelta {} impl Delta for VecNestDelta {} @@ -136,7 +63,6 @@ impl Delta for VecNestDelta {} mod tests { use crate::lodstore::data::tests::gen_simple_example; use crate::lodstore::data::tests::ExampleData; - use crate::lodstore::data::*; use crate::lodstore::delta::*; use test::Bencher; diff --git a/worldsim/src/lodstore/entrylayer.rs b/worldsim/src/lodstore/entrylayer.rs new file mode 100644 index 0000000000..1bf7f77bf6 --- /dev/null +++ b/worldsim/src/lodstore/entrylayer.rs @@ -0,0 +1,53 @@ +use super::index::ToOptionUsize; +use super::lodpos::LodPos; +use super::data::{HashNestLayer, DetailStore, HashIter}; +use super::delta::{VecNestDelta, Delta, VecDataIter, DataWriterIter, DeltaWriter}; +use super::traversable::Traversable; +use std::marker::PhantomData; + +pub trait EntryLayer<'a> { + type TRAV: Traversable; + fn trav(&'a self, pos: LodPos) -> Self::TRAV; +} + +///////////////// data types + +impl<'a, C: 'a + DetailStore, T: 'a, I: 'a + ToOptionUsize, const L: u8> EntryLayer<'a> +for HashNestLayer +{ + type TRAV = HashIter<'a, HashNestLayer>; + + fn trav(&'a self, pos: LodPos) -> Self::TRAV { + HashIter { + layer: &self, + wanted: pos, + layer_lod: pos.align_to_level({ L }), + } + } +} + +///////////////// delta types + +impl<'a, D: 'a + Delta, T: 'a, const L: u8> EntryLayer<'a> for VecNestDelta { + type TRAV = VecDataIter<'a, VecNestDelta>; + + fn trav(&'a self, _pos: LodPos) -> Self::TRAV { + VecDataIter { layer: &self } + } +} + +impl<'a, C: DetailStore + EntryLayer<'a>, D: Delta + EntryLayer<'a>> EntryLayer<'a> +for DeltaWriter<'a, C, D> + where + <>::TRAV as Traversable>::TRAV_CHILD: Traversable, + <>::TRAV as Traversable>::TRAV_CHILD: Traversable, +{ + type TRAV = DataWriterIter<'a, D::TRAV, C::TRAV>; + fn trav(&'a self, pos: LodPos) -> DataWriterIter { + DataWriterIter { + delta_iter: self.delta.trav(pos), + data_iter: self.data.trav(pos), + _a: PhantomData::<&'a ()>::default(), + } + } +} \ No newline at end of file diff --git a/worldsim/src/lodstore/layer.rs b/worldsim/src/lodstore/layer.rs new file mode 100644 index 0000000000..d1035f95b1 --- /dev/null +++ b/worldsim/src/lodstore/layer.rs @@ -0,0 +1,76 @@ +use super::index::ToOptionUsize; +use super::lodpos::{two_pow_u, LodPos}; +use super::data::{VecLayer, HashLayer, VecNestLayer, HashNestLayer, DetailStore}; +use super::delta::{VecDelta, VecNestDelta, Delta}; +use vek::Vec3; + +pub trait Layer { + type KEY; + const LEVEL: u8; +} + +pub trait ParentLayer: Layer { + type CHILD: Layer; + fn child(&self) -> &Self::CHILD; + const CHILDS_PER_OWN_TOTAL: usize = two_pow_u(Self::LOG2_OF_CHILDS_PER_OWN_TOTAL) as usize; + const LOG2_OF_CHILDS_PER_OWN_TOTAL: u8 = 3 * ({ Self::LEVEL } - Self::CHILD::LEVEL); + const CHILDS_PER_OWN: Vec3 = Vec3 { + x: two_pow_u(Self::LEVEL - Self::CHILD::LEVEL) as u32, + y: two_pow_u(Self::LEVEL - Self::CHILD::LEVEL) as u32, + z: two_pow_u(Self::LEVEL - Self::CHILD::LEVEL) as u32, + }; +} + +///////////////// data types + +impl Layer for VecLayer { + type KEY = (usize); + const LEVEL: u8 = { L }; +} +impl Layer for HashLayer { + type KEY = (LodPos); + const LEVEL: u8 = { L }; +} +impl Layer for VecNestLayer { + type KEY = (usize); + const LEVEL: u8 = { L }; +} +impl Layer for HashNestLayer { + type KEY = (LodPos); + const LEVEL: u8 = { L }; +} + +impl ParentLayer + for VecNestLayer +{ + type CHILD = C; + fn child(&self) -> &Self::CHILD { + &self.child + } +} +impl ParentLayer + for HashNestLayer +{ + type CHILD = C; + fn child(&self) -> &Self::CHILD { + &self.child + } +} + +///////////////// delta types + +impl Layer for VecDelta { + type KEY = (usize); + const LEVEL: u8 = { L }; +} +impl Layer for VecNestDelta { + type KEY = (usize); + const LEVEL: u8 = { L }; +} + +impl ParentLayer for VecNestDelta { + type CHILD = D; + fn child(&self) -> &Self::CHILD { + &self.child + } +} \ No newline at end of file diff --git a/worldsim/src/lodstore/area.rs b/worldsim/src/lodstore/lodarea.rs similarity index 100% rename from worldsim/src/lodstore/area.rs rename to worldsim/src/lodstore/lodarea.rs diff --git a/worldsim/src/lodstore/lodpos.rs b/worldsim/src/lodstore/lodpos.rs index 2ff4f22fc0..5a99a5c6c1 100644 --- a/worldsim/src/lodstore/lodpos.rs +++ b/worldsim/src/lodstore/lodpos.rs @@ -84,17 +84,6 @@ impl LodPos { let f = two_pow_u(layer) as u32; LodPos::new(xyz.map(|i| (i / f) * f)) } - - pub fn get_highest_level_that_fits(&self) -> u8 { - let pos = self.get(); - cmp::min( - cmp::min( - cmp::min(pos[0].trailing_zeros(), pos[1].trailing_zeros()), - pos[2].trailing_zeros(), - ), - 15, - ) as u8 - } } impl fmt::Display for LodPos { @@ -105,24 +94,6 @@ impl fmt::Display for LodPos { } } -#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)] -pub struct AbsIndex { - pub layer: u8, - pub index: usize, -} - -impl AbsIndex { - pub fn new(layer: u8, index: usize) -> Self { - AbsIndex { layer, index } - } -} - -impl fmt::Display for AbsIndex { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "[{}:{}]", self.layer, self.index) - } -} - impl Sub for LodPos { type Output = LodPos; fn sub(self, rhs: LodPos) -> Self::Output { @@ -141,10 +112,7 @@ impl Add for LodPos { } } -pub const fn two_pow_u(n: u8) -> u16 { - 1 << n -} -pub const fn two_pow_u32(n: u8) -> u32 { +pub const fn two_pow_u(n: u8) -> u32 { 1 << n } @@ -159,7 +127,7 @@ pub fn relative_to_1d( child_layer: u8, relative_size: Vec3, ) -> usize { - let width = two_pow_u32(child_layer) as u32; + 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 @@ -183,7 +151,7 @@ pub fn max(lhs: LodPos, rhs: LodPos) -> LodPos { #[cfg(test)] mod tests { - use crate::{lodstore::lodpos::two_pow_u32, lodstore::lodpos::LodPos}; + use crate::{lodstore::lodpos::two_pow_u, lodstore::lodpos::LodPos}; use test::Bencher; use vek::*; @@ -238,58 +206,9 @@ mod tests { assert_eq!(i.get(), Vec3::new(0, 0, 0)); } - #[test] - fn get_highest_level_that_fits() { - let i = LodPos::xyz(0, 0, 0); - assert_eq!(i.get_highest_level_that_fits(), 15); - let i = LodPos::xyz(1, 0, 0); - assert_eq!(i.get_highest_level_that_fits(), 0); - let i = LodPos::xyz(2, 0, 0); - assert_eq!(i.get_highest_level_that_fits(), 1); - let i = LodPos::xyz(3, 0, 0); - assert_eq!(i.get_highest_level_that_fits(), 0); - let i = LodPos::xyz(4, 0, 0); - assert_eq!(i.get_highest_level_that_fits(), 2); - let i = LodPos::xyz(5, 0, 0); - assert_eq!(i.get_highest_level_that_fits(), 0); - - let i = LodPos::xyz(1337, 0, 0); - assert_eq!(i.get_highest_level_that_fits(), 0); - - let i = LodPos::xyz(1337, 1800, 0); - assert_eq!(i.get_highest_level_that_fits(), 0); - - let i = LodPos::xyz(1338, 0, 50); - assert_eq!(i.get_highest_level_that_fits(), 1); - - let i = LodPos::xyz(1336, 0, 0); - assert_eq!(i.get_highest_level_that_fits(), 3); - - let i = LodPos::xyz(31348, 22000, 25000); - assert_eq!(i.get_highest_level_that_fits(), 2); - - let i = LodPos::xyz(0, 0, 0); - assert_eq!(i.get_highest_level_that_fits(), 15); - - let i = LodPos::xyz(65536, 0, 0); - assert_eq!(i.get_highest_level_that_fits(), 15); - - let i = LodPos::xyz(32768, 0, 0); - assert_eq!(i.get_highest_level_that_fits(), 15); - - let i = LodPos::xyz(16384, 0, 0); - assert_eq!(i.get_highest_level_that_fits(), 14); - - let i = LodPos::xyz(8192, 0, 0); - assert_eq!(i.get_highest_level_that_fits(), 13); - - let i = LodPos::xyz(65536, 0, 8192); - assert_eq!(i.get_highest_level_that_fits(), 13); - } - #[bench] fn bench_access_two_pow(b: &mut Bencher) { - b.iter(|| two_pow_u32(6)); + b.iter(|| two_pow_u(6)); } #[bench] diff --git a/worldsim/src/lodstore/materializeable.rs b/worldsim/src/lodstore/materializeable.rs new file mode 100644 index 0000000000..fad466d7e6 --- /dev/null +++ b/worldsim/src/lodstore/materializeable.rs @@ -0,0 +1,36 @@ +use super::lodpos::{LodPos}; +use super::data::{DetailStore, HashIter, VecIter}; +use super::delta::DataWriterIter; + +pub trait Materializeable { + type MAT_CHILD; + fn mat(self) -> Self::MAT_CHILD; +} + +///////////////// data types + +impl<'a, L: DetailStore> Materializeable for HashIter<'a, L> { + type MAT_CHILD = &'a L::DETAIL; + + fn mat(self) -> &'a L::DETAIL { + DetailStore::load(self.layer, self.layer_lod) + } +} + +impl<'a, L: DetailStore> Materializeable for VecIter<'a, L> { + type MAT_CHILD = &'a L::DETAIL; + + fn mat(self) -> &'a L::DETAIL { + DetailStore::load(self.layer, self.layer_key) + } +} + +///////////////// delta types + +impl<'a, DT, CT: Materializeable> Materializeable for DataWriterIter<'a, DT, CT> { + type MAT_CHILD = CT::MAT_CHILD; + + fn mat(self) -> CT::MAT_CHILD { + self.data_iter.mat() + } +} diff --git a/worldsim/src/lodstore/mod.rs b/worldsim/src/lodstore/mod.rs index 5499a3ce48..6745c8cb20 100644 --- a/worldsim/src/lodstore/mod.rs +++ b/worldsim/src/lodstore/mod.rs @@ -1,7 +1,50 @@ -pub mod area; +pub mod lodpos; +pub mod lodarea; +pub mod layer; +pub mod traversable; +pub mod materializeable; +pub mod entrylayer; pub mod data; pub mod delta; pub mod drill; pub mod index; -pub mod lodpos; pub use data::{HashLayer, HashNestLayer, VecLayer, VecNestLayer}; + +/* + 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 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. + - DetailStoreMut: allows mut borrow for Vec types (Hash not supported) + !!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. + - EntryLayer: the topmost layer which can generate a Traversable for a LodPos must implement this, e.g. needed by delta + + 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 +*/ diff --git a/worldsim/src/lodstore/traversable.rs b/worldsim/src/lodstore/traversable.rs new file mode 100644 index 0000000000..54d3743d01 --- /dev/null +++ b/worldsim/src/lodstore/traversable.rs @@ -0,0 +1,95 @@ +use super::index::ToOptionUsize; +use super::lodpos::{multily_with_2_pow_n, relative_to_1d, LodPos}; +use super::data::{DetailStore, IndexStore, HashIter, VecIter}; +use super::delta::{Delta, VecDataIter, DataWriterIter}; +#[allow(unused_imports)] //not unsued, cargo is just to stupud to detect that +use super::layer::{Layer, ParentLayer}; +use std::marker::PhantomData; + +pub trait Traversable { + type TRAV_CHILD; + fn get(self) -> Self::TRAV_CHILD; +} + +///////////////// data types + +impl<'a, L: DetailStore + IndexStore> Traversable for HashIter<'a, L> + where + L::CHILD: DetailStore, +{ + type TRAV_CHILD = VecIter<'a, L::CHILD>; + + 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, +{ + type TRAV_CHILD = VecIter<'a, L::CHILD>; + + 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, + } + } +} + +///////////////// delta types + +impl<'a, D: Delta + ParentLayer> Traversable for VecDataIter<'a, D> + where + D::CHILD: Delta, +{ + type TRAV_CHILD = VecDataIter<'a, D::CHILD>; + + fn get(self) -> VecDataIter<'a, D::CHILD> { + VecDataIter { + layer: self.layer.child(), + } + } +} + +impl<'a, DT: Traversable, CT: Traversable> Traversable for DataWriterIter<'a, DT, CT> { + type TRAV_CHILD = DataWriterIter<'a, DT::TRAV_CHILD, CT::TRAV_CHILD>; + + fn get(self) -> DataWriterIter<'a, DT::TRAV_CHILD, CT::TRAV_CHILD> { + DataWriterIter { + delta_iter: self.delta_iter.get(), + data_iter: self.data_iter.get(), + _a: PhantomData::<&'a ()>::default(), + } + } +} \ No newline at end of file