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
This commit is contained in:
Marcel Märtens 2019-10-16 11:08:23 +02:00
parent 7039d5a29c
commit b297f3b479
8 changed files with 371 additions and 1301 deletions

View File

@ -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::collections::HashMap;
use std::{u16, u32};
use vek::*; 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. Terminology:
This is the structure to store a region and all subscribed information - 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 <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 LodIntoOptionUsize: Copy { pub trait Layer {
fn is_some(self) -> bool; type KEY;
fn into_usize(self) -> usize; const LEVEL: u8;
} }
pub trait LodConfig { pub trait ParentLayer: Layer {
type L0: Clone; // 2^-4 type CHILD: Layer;
type L1: Clone; fn child(&self) -> &Self::CHILD;
type L2: Clone; fn CHILDS_PER_OWN_TOTAL() -> usize {
type L3: Clone; two_pow_u32(Self::LOG2_OF_CHILDS_PER_OWN_TOTAL()) as usize
type L4: Clone; // 2^0 }
type L5: Clone; fn LOG2_OF_CHILDS_PER_OWN_TOTAL() -> u8 {
type L6: Clone; 3 * ({ Self::LEVEL } - Self::CHILD::LEVEL)
type L7: Clone; }
type L8: Clone; fn CHILDS_PER_OWN() -> Vec3<u32> {
type L9: Clone; Vec3 {
type L10: Clone; x: two_pow_u32(Self::LEVEL - Self::CHILD::LEVEL) as u32,
type L11: Clone; y: two_pow_u32(Self::LEVEL - Self::CHILD::LEVEL) as u32,
type L12: Clone; z: two_pow_u32(Self::LEVEL - Self::CHILD::LEVEL) as u32,
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<u32>; 16]; // number of elements on this layer as Vec3 (not on child layer!)
const child_layer_id: [Option<u8>; 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::<Self>, abs: AbsIndex) where Self: Sized;
fn drill_up(data: &mut LodData::<Self>, 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,
} }
} }
} }
#[derive(Debug, Clone)] pub trait IndexStore: ParentLayer {
pub struct LodData<X: LodConfig> { type INDEX: ToOptionUsize;
pub layer0: Vec<X::L0>, // 1/16 fn load(&self, key: Self::KEY) -> Self::INDEX;
pub layer1: Vec<X::L1>, // 1/8
pub layer2: Vec<X::L2>, // 1/4
pub layer3: Vec<X::L3>, // 1/2
pub layer4: Vec<X::L4>, // 1
pub layer5: Vec<X::L5>, // 2
pub layer6: Vec<X::L6>, // 4
pub layer7: Vec<X::L7>, // 8
pub layer8: Vec<X::L8>, // 16
pub layer9: Vec<X::L9>, // 32
pub layer10: Vec<X::L10>, // 64
pub layer11: Vec<X::L11>, // 128
pub layer12: Vec<X::L12>, // 256
pub layer13: Vec<X::L13>, // 512
pub layer14: Vec<X::L14>, // 1024
pub layer15: Vec<X::L15>, // 2048
pub child0: Vec<X::I0>,
pub child1: Vec<X::I1>,
pub child2: Vec<X::I2>,
pub child3: Vec<X::I3>,
pub child4: Vec<X::I4>,
pub child5: Vec<X::I5>,
pub child6: Vec<X::I6>,
pub child7: Vec<X::I7>,
pub child8: Vec<X::I8>,
pub child9: Vec<X::I9>,
pub child10: Vec<X::I10>,
pub child11: Vec<X::I11>,
pub child12: Vec<X::I12>,
pub child13: Vec<X::I13>,
pub child14: Vec<X::I14>,
pub child15: Vec<X::I15>,
pub anchor: HashMap<LodIndex, usize>,
pub additional: Option<X::Additional>,
} }
impl<X: LodConfig> LodData<X> pub trait DetailStore: Layer {
{ type DETAIL;
pub fn new() -> Self { fn load(&self, key: Self::KEY) -> &Self::DETAIL;
Self { }
layer0: Vec::new(),
layer1: Vec::new(),
layer2: Vec::new(),
layer3: Vec::new(),
layer4: Vec::new(),
layer5: Vec::new(),
layer6: Vec::new(),
layer7: Vec::new(),
layer8: Vec::new(),
layer9: Vec::new(),
layer10: Vec::new(),
layer11: Vec::new(),
layer12: Vec::new(),
layer13: Vec::new(),
layer14: Vec::new(),
layer15: Vec::new(),
child0: Vec::new(),
child1: Vec::new(),
child2: Vec::new(),
child3: Vec::new(),
child4: Vec::new(),
child5: Vec::new(),
child6: Vec::new(),
child7: Vec::new(),
child8: Vec::new(),
child9: Vec::new(),
child10: Vec::new(),
child11: Vec::new(),
child12: Vec::new(),
child13: Vec::new(),
child14: Vec::new(),
child15: Vec::new(),
anchor: HashMap::new(),
additional: None,
}
}
// dynamically dispatches the get_child_index, this is most prob the bottleneck function. pub trait Traversable<C> {
// evaluate the performacne impact!!! fn get(self) -> C;
fn int_get_child_index(&self, abs: AbsIndex) -> usize { }
match abs.layer { pub trait Materializeable<T> {
0 => self.child0[abs.index].into_usize(), fn mat(self) -> T;
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 #[derive(Default, Clone, Debug)]
fn int_get_lockup(&self, parent_abs: AbsIndex, child_lod: LodIndex) -> AbsIndex { pub struct VecLayer<T, const L: u8> {
let parent_lod = child_lod.align_to_level(parent_abs.layer); pub detail: Vec<T>,
let parent_child_index = self.int_get_child_index(parent_abs); }
Self::int_get(parent_abs, child_lod, parent_lod, parent_child_index) #[derive(Default, Clone, Debug)]
} pub struct HashLayer<T, const L: u8> {
pub detail: FxHashMap<LodPos, T>,
}
#[derive(Default, Clone, Debug)]
pub struct VecNestLayer<C: DetailStore, T, I: ToOptionUsize, const L: u8> {
pub detail: Vec<T>,
pub index: Vec<I>,
pub child: C,
}
#[derive(Default, Clone, Debug)]
pub struct HashNestLayer<C: DetailStore, T, I: ToOptionUsize, const L: u8> {
pub detail_index: FxHashMap<LodPos, (T, I)>,
pub child: C,
}
// target_layer is requiered because same LodIndex can exist for multiple layers, and guessing is stupid here pub struct HashIter<'a, C: DetailStore> {
fn int_recursive_get(&self, parent_abs: AbsIndex, child_lod: LodIndex, target_layer:u8) -> AbsIndex { layer: &'a C,
let mut parent_abs = parent_abs; wanted: LodPos,
while true { layer_lod: LodPos, //LodPos aligned to layer::LEVEL
//println!("{} int_recursive_get {} - {}", Self::debug_offset(parent_abs.layer), parent_abs, target_layer); }
parent_abs = self.int_get_lockup(parent_abs, child_lod); pub struct VecIter<'a, C: DetailStore> {
if parent_abs.layer <= target_layer { layer: &'a C,
return parent_abs; wanted: LodPos,
} layer_lod: LodPos, //LodPos aligned to layer::LEVEL
} layer_key: usize,
unreachable!(); }
}
pub fn int_get_n(&self, index: LodIndex, layer: u8) -> AbsIndex { #[rustfmt::skip]
let anchor_lod = index.align_to_level(X::anchor_layer_id); impl<T, const L: u8> Layer for VecLayer<T, { L }> {
let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]); type KEY = ( usize ); const LEVEL: u8 = { L };
let wanted_abs = self.int_recursive_get(anchor_abs, index, layer); }
debug_assert_eq!(wanted_abs.layer, layer); #[rustfmt::skip]
wanted_abs impl<T, const L: u8> Layer for HashLayer<T, { L }> {
} type KEY = ( LodPos ); const LEVEL: u8 = { L };
}
#[rustfmt::skip]
impl<C: DetailStore, T, I: ToOptionUsize, const L: u8> Layer for VecNestLayer<C, T, I, { L }> {
type KEY = ( usize ); const LEVEL: u8 = { L };
}
#[rustfmt::skip]
impl<C: DetailStore, T, I: ToOptionUsize, const L: u8> Layer for HashNestLayer<C, T, I, { L }> {
type KEY = ( LodPos ); const LEVEL: u8 = { L };
}
// target_layer is requiered because same LodIndex can exist for multiple layers, and guessing is stupid here #[rustfmt::skip]
fn int_recursive_get_cached(&self, cache: &mut CacheLine, parent_abs: AbsIndex, child_lod: LodIndex, target_layer:u8) -> AbsIndex { impl<C: DetailStore, T, I: ToOptionUsize, const L: u8> ParentLayer for VecNestLayer<C, T, I, { L }> {
let mut parent_abs = parent_abs; type CHILD = C;
let mut old_parent_abs = parent_abs; fn child(&self) -> &Self::CHILD { &self.child }
while true { }
//println!("{} int_recursive_get {} - {}", Self::debug_offset(parent_abs.layer), parent_abs, target_layer); #[rustfmt::skip]
old_parent_abs = parent_abs; impl<C: DetailStore, T, I: ToOptionUsize, const L: u8> ParentLayer for HashNestLayer<C, T, I, { L }> {
parent_abs = self.int_get_lockup(parent_abs, child_lod); type CHILD = C;
if parent_abs.layer <= target_layer { fn child(&self) -> &Self::CHILD { &self.child }
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 { impl<C: DetailStore, T, I: ToOptionUsize, const L: u8> HashNestLayer<C, T, I, { L }> {
let wanted_abs = if cache.last_parent_area.is_inside(index) { fn trav(&self, pos: LodPos) -> HashIter<Self> {
//println!("yay"); HashIter {
Self::int_get(cache.last_parent_abs, index, cache.last_parent_lod, cache.last_parent_child_index) layer: &self,
} else { wanted: pos,
//println!("nay"); layer_lod: pos.align_to_level({ L }),
//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<X>>) {
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<X>>) {
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<X>>) {
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<X>>) {
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<X>>) {
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<X>>) {
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<X>>) {
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<X>>) {
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<X>>) {
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<X>>) {
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<X>>) {
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<X>>) {
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<X>>) {
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<X>>) {
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<X>>) {
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<X>>) {
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<X>>) {
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<X>>) {
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 () { #[rustfmt::skip]
fn is_some(self) -> bool { impl<C: DetailStore, T, I: ToOptionUsize, const L: u8> IndexStore for VecNestLayer<C, T, I, { L }> {
false type INDEX = I;
} fn load(&self, key: Self::KEY) -> Self::INDEX { self.index[key] }
fn into_usize(self) -> usize { }
unreachable!("dummyUsize") #[rustfmt::skip]
impl<C: DetailStore, T, I: ToOptionUsize, const L: u8> IndexStore for HashNestLayer<C, T, I, { L }> {
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 { #[rustfmt::skip]
fn is_some(self) -> bool { impl<C: DetailStore, I: ToOptionUsize, T, const L: u8> DetailStore for VecNestLayer<C, T, I, { L }> {
self != u32::MAX type DETAIL = T;
} fn load(&self, key: Self::KEY) -> &Self::DETAIL {
fn into_usize(self) -> usize { &self.detail[key]
self as usize }
}
#[rustfmt::skip]
impl<C: DetailStore, I: ToOptionUsize, T, const L: u8> DetailStore for HashNestLayer<C, T, I, { L }> {
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<T, const L: u8> DetailStore for VecLayer<T, { L }> {
type DETAIL = T;
fn load(&self, key: usize) -> &Self::DETAIL {
&self.detail[key]
}
}
#[rustfmt::skip]
impl<T, const L: u8> DetailStore for HashLayer<T, { L }> {
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<KEY = LodPos> + IndexStore> Traversable<VecIter<'a, L::CHILD>>
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<KEY = usize> + IndexStore> Traversable<VecIter<'a, L::CHILD>>
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<KEY=LodPos>> 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<KEY=usize>> 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());
} }
} }

View File

@ -1,3 +1,4 @@
/*
use super::{ use super::{
data::{ data::{
LodData, LodData,
@ -167,3 +168,4 @@ impl<X: LodConfig> LodDelta<X> {
} }
} }
} }
*/

View File

@ -1,8 +1,11 @@
pub mod lodpos; pub mod lodpos;
pub mod area; pub mod area;
pub mod index; pub mod index;
pub mod newdata;
pub mod data; pub mod data;
pub mod delta; pub mod delta;
pub use data::LodData; pub use data::{
pub use data::LodConfig; HashNestLayer,
VecNestLayer,
HashLayer,
VecLayer,
};

View File

@ -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 <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;
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<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;
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<C> {
fn get(self) -> C;
}
pub trait Materializeable<T> {
fn mat(self) -> T;
}
//#######################################################
#[derive(Default)]
pub struct VecLayer<T, const L: u8> {
pub detail: Vec<T>,
}
#[derive(Default)]
pub struct HashLayer<T, const L: u8> {
pub detail: FxHashMap<LodPos, T>,
}
#[derive(Default)]
pub struct VecNestLayer<C: DetailStore, T, I: ToOptionUsize, const L: u8> {
pub detail: Vec<T>,
pub index: Vec<I>,
pub child: C,
}
#[derive(Default)]
pub struct HashNestLayer<C: DetailStore, T, I: ToOptionUsize, const L: u8> {
pub detail_index: FxHashMap<LodPos, (T, I)>,
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<T, const L: u8> Layer for VecLayer<T, { L }> {
type KEY = ( usize ); const LEVEL: u8 = { L };
}
#[rustfmt::skip]
impl<T, const L: u8> Layer for HashLayer<T, { L }> {
type KEY = ( LodPos ); const LEVEL: u8 = { L };
}
#[rustfmt::skip]
impl<C: DetailStore, T, I: ToOptionUsize, const L: u8> Layer for VecNestLayer<C, T, I, { L }> {
type KEY = ( usize ); const LEVEL: u8 = { L };
}
#[rustfmt::skip]
impl<C: DetailStore, T, I: ToOptionUsize, const L: u8> Layer for HashNestLayer<C, T, I, { L }> {
type KEY = ( LodPos ); const LEVEL: u8 = { L };
}
#[rustfmt::skip]
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 }
}
#[rustfmt::skip]
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<C: DetailStore, T, I: ToOptionUsize, const L: u8> HashNestLayer<C, T, I, { L }> {
fn trav(&self, pos: LodPos) -> HashIter<Self> {
HashIter {
layer: &self,
wanted: pos,
layer_lod: pos.align_to_level({ L }),
}
}
}
#[rustfmt::skip]
impl<C: DetailStore, T, I: ToOptionUsize, const L: u8> IndexStore for VecNestLayer<C, T, I, { L }> {
type INDEX = I;
fn load(&self, key: Self::KEY) -> Self::INDEX { self.index[key] }
}
#[rustfmt::skip]
impl<C: DetailStore, T, I: ToOptionUsize, const L: u8> IndexStore for HashNestLayer<C, T, I, { L }> {
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<C: DetailStore, I: ToOptionUsize, T, const L: u8> DetailStore for VecNestLayer<C, T, I, { L }> {
type DETAIL = T;
fn load(&self, key: Self::KEY) -> &Self::DETAIL {
&self.detail[key]
}
}
#[rustfmt::skip]
impl<C: DetailStore, I: ToOptionUsize, T, const L: u8> DetailStore for HashNestLayer<C, T, I, { L }> {
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<T, const L: u8> DetailStore for VecLayer<T, { L }> {
type DETAIL = T;
fn load(&self, key: usize) -> &Self::DETAIL {
&self.detail[key]
}
}
#[rustfmt::skip]
impl<T, const L: u8> DetailStore for HashLayer<T, { L }> {
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<KEY = LodPos> + IndexStore> Traversable<VecIter<'a, L::CHILD>>
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<KEY = usize> + IndexStore> Traversable<VecIter<'a, L::CHILD>>
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<KEY=LodPos>> 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<KEY=usize>> 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());
}
}

View File

@ -1,2 +1 @@
pub mod terrain; pub mod terrain;
mod example;

View File

@ -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<u32>; 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<u8>; 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::<Self>, 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::<Self>, 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<TerrainLodConfig>;

View File

@ -1,199 +1,50 @@
use crate::lodstore::{ use crate::lodstore::{
LodData, HashNestLayer,
LodConfig, VecNestLayer,
HashLayer,
VecLayer,
lodpos::LodPos, lodpos::LodPos,
lodpos::AbsIndex, lodpos::AbsIndex,
delta::LodDelta,
}; };
use vek::*; use vek::*;
use std::u32; use std::u32;
pub type LodIndex = LodPos; pub type LodIndex = LodPos;
#[derive(Debug, Clone)] #[derive(Debug, Clone, Default)]
pub struct Region9 { pub struct Region {
precent_air: f32, precent_air: f32,
percent_forrest: f32, percent_forrest: f32,
percent_lava: f32, percent_lava: f32,
percent_water: f32, percent_water: f32,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone, Default)]
pub struct Chunk5 { pub struct Chunk {
precent_air: f32, precent_air: f32,
percent_forrest: f32, percent_forrest: f32,
percent_lava: f32, percent_lava: f32,
percent_water: f32, percent_water: f32,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone, Default)]
pub struct Block0 { pub struct Block {
material: u32, material: u32,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone, Default)]
pub struct SubBlock_4 { pub struct SubBlock {
material: u32, material: u32,
} }
#[derive(Debug, Clone)]
pub struct TerrainLodConfig {}
impl LodConfig for TerrainLodConfig { #[rustfmt::skip]
type L0 = SubBlock_4; pub type TerrainLod =
type L1 = (); HashNestLayer<
type L2 = (); VecNestLayer<
type L3 = (); VecNestLayer<
type L4 = Block0; VecLayer<
type L5 = (); SubBlock, 0
type L6 = (); > ,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
type L7 = (); > ,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
type L8 = (); > ,Region ,u16, 13
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<u32>; 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<u8>; 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::<Self>, 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::<Self>, 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<TerrainLodConfig>;

View File

@ -6,18 +6,18 @@ use crate::{
regionmanager::meta::RegionId, regionmanager::meta::RegionId,
job::JobManager, job::JobManager,
}; };
use lod::terrain::Terrain; use lod::terrain::TerrainLod;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Region { pub struct Region {
id: RegionId, id: RegionId,
jobmanager: Arc<JobManager>, jobmanager: Arc<JobManager>,
pub block: Terrain, pub block: TerrainLod,
temp: Terrain, temp: TerrainLod,
light: Terrain, light: TerrainLod,
evil: Terrain, evil: TerrainLod,
civ: Terrain, civ: TerrainLod,
} }
impl Region { impl Region {
@ -25,11 +25,11 @@ impl Region {
Self { Self {
id, id,
jobmanager, jobmanager,
block: Terrain::new(), block: TerrainLod::default(),
temp: Terrain::new(), temp: TerrainLod::default(),
light: Terrain::new(), light: TerrainLod::default(),
evil: Terrain::new(), evil: TerrainLod::default(),
civ: Terrain::new(), civ: TerrainLod::default(),
} }
} }
} }