mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
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:
parent
7039d5a29c
commit
b297f3b479
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
/*
|
||||||
use super::{
|
use super::{
|
||||||
data::{
|
data::{
|
||||||
LodData,
|
LodData,
|
||||||
@ -167,3 +168,4 @@ impl<X: LodConfig> LodDelta<X> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
@ -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,
|
||||||
|
};
|
@ -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());
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,2 +1 @@
|
|||||||
pub mod terrain;
|
pub mod terrain;
|
||||||
mod example;
|
|
@ -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>;
|
|
@ -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>;
|
|
@ -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(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user