mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
cleanup and modify file structure
now we create seperate files for materializeable and layers which cover A) the trait and B) the implementations of data and delta inside this helps to find the right stuff in this trait chaos :D also those structs/trait are prob often edited at once
This commit is contained in:
parent
e36b9d90db
commit
73e130c097
@ -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 <Own Detail Type>[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<u32> = 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<C: DetailStore, T, I: ToOptionUsize, const L: u8> {
|
||||
}
|
||||
|
||||
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<T, const L: u8> Layer for VecLayer<T, { L }> {
|
||||
type KEY = (usize);
|
||||
const LEVEL: u8 = { L };
|
||||
}
|
||||
impl<T, const L: u8> Layer for HashLayer<T, { L }> {
|
||||
type KEY = (LodPos);
|
||||
const LEVEL: u8 = { L };
|
||||
}
|
||||
impl<C: DetailStore, T, I: ToOptionUsize, const L: u8> Layer for VecNestLayer<C, T, I, { L }> {
|
||||
type KEY = (usize);
|
||||
const LEVEL: u8 = { L };
|
||||
}
|
||||
impl<C: DetailStore, T, I: ToOptionUsize, const L: u8> Layer for HashNestLayer<C, T, I, { L }> {
|
||||
type KEY = (LodPos);
|
||||
const LEVEL: u8 = { L };
|
||||
}
|
||||
|
||||
impl<C: DetailStore, T, I: ToOptionUsize, const L: u8> ParentLayer
|
||||
for VecNestLayer<C, T, I, { L }>
|
||||
{
|
||||
type CHILD = C;
|
||||
fn child(&self) -> &Self::CHILD {
|
||||
&self.child
|
||||
}
|
||||
}
|
||||
impl<C: DetailStore, T, I: ToOptionUsize, const L: u8> ParentLayer
|
||||
for HashNestLayer<C, T, I, { L }>
|
||||
{
|
||||
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<C, T, I, { L }>
|
||||
{
|
||||
type TRAV = HashIter<'a, HashNestLayer<C, T, I, { L }>>;
|
||||
|
||||
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<C: DetailStore, T, I: ToOptionUsize, const L: u8> IndexStore for VecNestLayer<C, T, I, { L }> {
|
||||
@ -241,80 +131,11 @@ impl<T, const L: u8> DetailStore for HashLayer<T, { L }> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, L: DetailStore<KEY = LodPos> + 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<KEY = usize> + 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<KEY = LodPos>> 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<KEY = usize>> 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 =
|
||||
|
@ -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<T, const L: u8> Layer for VecDelta<T, { L }> {
|
||||
type KEY = (usize);
|
||||
const LEVEL: u8 = { L };
|
||||
}
|
||||
impl<D: Delta, T, const L: u8> Layer for VecNestDelta<D, T, { L }> {
|
||||
type KEY = (usize);
|
||||
const LEVEL: u8 = { L };
|
||||
}
|
||||
|
||||
impl<D: Delta, T, const L: u8> ParentLayer for VecNestDelta<D, T, { L }> {
|
||||
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<D, T, { L }> {
|
||||
type TRAV = VecDataIter<'a, VecNestDelta<D, T, { L }>>;
|
||||
|
||||
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
|
||||
<<C as EntryLayer<'a>>::TRAV as Traversable>::TRAV_CHILD: Traversable,
|
||||
<<D as EntryLayer<'a>>::TRAV as Traversable>::TRAV_CHILD: Traversable,
|
||||
{
|
||||
type TRAV = DataWriterIter<'a, D::TRAV, C::TRAV>;
|
||||
fn trav(&'a self, pos: LodPos) -> DataWriterIter<D::TRAV, C::TRAV> {
|
||||
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<T, const L: u8> Delta for VecDelta<T, { L }> {}
|
||||
impl<C: Delta, T, const L: u8> Delta for VecNestDelta<C, T, { L }> {}
|
||||
|
||||
@ -136,7 +63,6 @@ impl<C: Delta, T, const L: u8> Delta for VecNestDelta<C, T, { L }> {}
|
||||
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;
|
||||
|
||||
|
53
worldsim/src/lodstore/entrylayer.rs
Normal file
53
worldsim/src/lodstore/entrylayer.rs
Normal file
@ -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<C, T, I, { L }>
|
||||
{
|
||||
type TRAV = HashIter<'a, HashNestLayer<C, T, I, { L }>>;
|
||||
|
||||
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<D, T, { L }> {
|
||||
type TRAV = VecDataIter<'a, VecNestDelta<D, T, { L }>>;
|
||||
|
||||
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
|
||||
<<C as EntryLayer<'a>>::TRAV as Traversable>::TRAV_CHILD: Traversable,
|
||||
<<D as EntryLayer<'a>>::TRAV as Traversable>::TRAV_CHILD: Traversable,
|
||||
{
|
||||
type TRAV = DataWriterIter<'a, D::TRAV, C::TRAV>;
|
||||
fn trav(&'a self, pos: LodPos) -> DataWriterIter<D::TRAV, C::TRAV> {
|
||||
DataWriterIter {
|
||||
delta_iter: self.delta.trav(pos),
|
||||
data_iter: self.data.trav(pos),
|
||||
_a: PhantomData::<&'a ()>::default(),
|
||||
}
|
||||
}
|
||||
}
|
76
worldsim/src/lodstore/layer.rs
Normal file
76
worldsim/src/lodstore/layer.rs
Normal file
@ -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<u32> = 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<T, const L: u8> Layer for VecLayer<T, { L }> {
|
||||
type KEY = (usize);
|
||||
const LEVEL: u8 = { L };
|
||||
}
|
||||
impl<T, const L: u8> Layer for HashLayer<T, { L }> {
|
||||
type KEY = (LodPos);
|
||||
const LEVEL: u8 = { L };
|
||||
}
|
||||
impl<C: DetailStore, T, I: ToOptionUsize, const L: u8> Layer for VecNestLayer<C, T, I, { L }> {
|
||||
type KEY = (usize);
|
||||
const LEVEL: u8 = { L };
|
||||
}
|
||||
impl<C: DetailStore, T, I: ToOptionUsize, const L: u8> Layer for HashNestLayer<C, T, I, { L }> {
|
||||
type KEY = (LodPos);
|
||||
const LEVEL: u8 = { L };
|
||||
}
|
||||
|
||||
impl<C: DetailStore, T, I: ToOptionUsize, const L: u8> ParentLayer
|
||||
for VecNestLayer<C, T, I, { L }>
|
||||
{
|
||||
type CHILD = C;
|
||||
fn child(&self) -> &Self::CHILD {
|
||||
&self.child
|
||||
}
|
||||
}
|
||||
impl<C: DetailStore, T, I: ToOptionUsize, const L: u8> ParentLayer
|
||||
for HashNestLayer<C, T, I, { L }>
|
||||
{
|
||||
type CHILD = C;
|
||||
fn child(&self) -> &Self::CHILD {
|
||||
&self.child
|
||||
}
|
||||
}
|
||||
|
||||
///////////////// delta types
|
||||
|
||||
impl<T, const L: u8> Layer for VecDelta<T, { L }> {
|
||||
type KEY = (usize);
|
||||
const LEVEL: u8 = { L };
|
||||
}
|
||||
impl<D: Delta, T, const L: u8> Layer for VecNestDelta<D, T, { L }> {
|
||||
type KEY = (usize);
|
||||
const LEVEL: u8 = { L };
|
||||
}
|
||||
|
||||
impl<D: Delta, T, const L: u8> ParentLayer for VecNestDelta<D, T, { L }> {
|
||||
type CHILD = D;
|
||||
fn child(&self) -> &Self::CHILD {
|
||||
&self.child
|
||||
}
|
||||
}
|
@ -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<u32>,
|
||||
) -> 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]
|
||||
|
36
worldsim/src/lodstore/materializeable.rs
Normal file
36
worldsim/src/lodstore/materializeable.rs
Normal file
@ -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<KEY = LodPos>> 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<KEY = usize>> 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()
|
||||
}
|
||||
}
|
@ -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 <Own Detail Type>[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
|
||||
*/
|
||||
|
95
worldsim/src/lodstore/traversable.rs
Normal file
95
worldsim/src/lodstore/traversable.rs
Normal file
@ -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<KEY = LodPos> + 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<KEY = usize> + 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(),
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user