work on a deltas, to store the diff while working on data.

this state does not work, because i tried to iplement delta in a trait type. however this is not necessary, i will revert this.
Just keep this commit for historical reasons - it wont build.
This commit is contained in:
Marcel Märtens 2019-07-24 15:47:15 +02:00
parent 536ef3d6ff
commit d5dca4f6e8
9 changed files with 889 additions and 595 deletions

View File

@ -0,0 +1,22 @@
use super::index::{
LodIndex,
};
/*
A LodArea is the area between 2 LodIndex
*/
#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
pub struct LodArea {
pub lower: LodIndex,
pub upper: LodIndex,
}
impl LodArea {
pub fn new(lower: LodIndex, upper: LodIndex) -> Self {
LodArea {
lower,
upper,
}
}
}

View File

@ -0,0 +1,433 @@
use std::u32;
use std::collections::HashMap;
use vek::*;
use super::index::{
self,
LodIndex,
AbsIndex,
relative_to_1d,
two_pow_u,
};
use super::area::{
LodArea,
};
use super::delta::{
LodDelta,
};
/*
LOD Data contains different Entries in different Vecs, every entry has a "pointer" to it's child start.
This is the structure to store a region and all subscribed information
*/
pub trait LodIntoOptionUsize: Copy {
fn is_some(self) -> bool;
fn into_usize(self) -> usize;
}
pub trait LodConfig {
type L0: Clone; // 2^-4
type L1: Clone;
type L2: Clone;
type L3: Clone;
type L4: Clone; // 2^0
type L5: Clone;
type L6: Clone;
type L7: Clone;
type L8: Clone;
type L9: Clone;
type L10: Clone;
type L11: Clone;
type L12: Clone;
type L13: Clone;
type L14: Clone;
type L15: Clone; // 2^11
type I0: LodIntoOptionUsize;
type I1: LodIntoOptionUsize;
type I2: LodIntoOptionUsize;
type I3: LodIntoOptionUsize;
type I4: LodIntoOptionUsize;
type I5: LodIntoOptionUsize;
type I6: LodIntoOptionUsize;
type I7: LodIntoOptionUsize;
type I8: LodIntoOptionUsize;
type I9: LodIntoOptionUsize;
type I10: LodIntoOptionUsize;
type I11: LodIntoOptionUsize;
type I12: LodIntoOptionUsize;
type I13: LodIntoOptionUsize;
type I14: LodIntoOptionUsize;
type I15: LodIntoOptionUsize;
type Delta: LodDelta;
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, delta: &mut Option<Self::Delta>) where Self: Sized;
fn drill_up(data: &mut LodData::<Self>, parent_abs: AbsIndex, delta: &mut Option<Self::Delta>) where Self: Sized;
}
#[derive(Debug, Clone)]
pub struct LodData<X: LodConfig> {
pub layer0: Vec<X::L0>, // 1/16
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 fn new() -> Self {
Self {
layer0: Vec::new(),
layer1: Vec::new(),
layer2: Vec::new(),
layer3: Vec::new(),
layer4: Vec::new(),
layer5: Vec::new(),
layer6: Vec::new(),
layer7: Vec::new(),
layer8: Vec::new(),
layer9: Vec::new(),
layer10: Vec::new(),
layer11: Vec::new(),
layer12: Vec::new(),
layer13: Vec::new(),
layer14: Vec::new(),
layer15: Vec::new(),
child0: Vec::new(),
child1: Vec::new(),
child2: Vec::new(),
child3: Vec::new(),
child4: Vec::new(),
child5: Vec::new(),
child6: Vec::new(),
child7: Vec::new(),
child8: Vec::new(),
child9: Vec::new(),
child10: Vec::new(),
child11: Vec::new(),
child12: Vec::new(),
child13: Vec::new(),
child14: Vec::new(),
child15: Vec::new(),
anchor: HashMap::new(),
additional: None,
}
}
// dynamically dispatches the get_child_index, this is most prob the bottleneck function.
// evaluate the performacne impact!!!
fn int_get_child_index(&self, abs: AbsIndex) -> usize {
match abs.layer {
0 => self.child0[abs.index].into_usize(),
1 => self.child1[abs.index].into_usize(),
2 => self.child2[abs.index].into_usize(),
3 => self.child3[abs.index].into_usize(),
4 => self.child4[abs.index].into_usize(),
5 => self.child5[abs.index].into_usize(),
6 => self.child6[abs.index].into_usize(),
7 => self.child7[abs.index].into_usize(),
8 => self.child8[abs.index].into_usize(),
9 => self.child9[abs.index].into_usize(),
10 => self.child10[abs.index].into_usize(),
11 => self.child11[abs.index].into_usize(),
12 => self.child12[abs.index].into_usize(),
13 => self.child13[abs.index].into_usize(),
14 => self.child14[abs.index].into_usize(),
15 => self.child15[abs.index].into_usize(),
_ => panic!("wrong abs index"),
}
}
// Returns the childs AbsIndex of Parent AbsIndex
// child_lod must lie within parent
// uses parent_lod as buffer, to not calculate it again
// uses parent_child_index as a buffer, to not calculate it again
fn int_get(parent_abs: AbsIndex, child_lod: LodIndex, parent_lod: LodIndex, parent_child_index: usize) -> AbsIndex {
let child_layer = X::child_layer_id[parent_abs.layer as usize].unwrap();
let child_lod = child_lod.align_to_layer_id(child_layer);
let child_offset = relative_to_1d(child_lod, parent_lod, child_layer, X::layer_volume[child_layer as usize]);
//println!("{} int_get - parent_abs {} child_lod {} parent_lod {} parent_child_index {} child_offset {}", Self::debug_offset(parent_abs.layer), parent_abs, child_lod, parent_lod, parent_child_index, child_offset);
AbsIndex::new(child_layer, parent_child_index + child_offset)
}
// slower variant of int_get which requiere self lookups
fn int_get_lockup(&self, parent_abs: AbsIndex, child_lod: LodIndex) -> AbsIndex {
let parent_lod = child_lod.align_to_layer_id(parent_abs.layer);
let parent_child_index = self.int_get_child_index(parent_abs);
Self::int_get(parent_abs, child_lod, parent_lod, parent_child_index)
}
// target_layer is requiered because same LodIndex can exist for multiple layers, and guessing is stupid here
fn int_recursive_get(&self, parent_abs: AbsIndex, child_lod: LodIndex, target_layer:u8) -> AbsIndex {
let mut parent_abs = parent_abs;
while true {
//println!("{} int_recursive_get {} - {}", Self::debug_offset(parent_abs.layer), parent_abs, target_layer);
parent_abs = self.int_get_lockup(parent_abs, child_lod);
if parent_abs.layer <= target_layer {
return parent_abs;
}
}
unreachable!();
}
pub fn int_get_n(&self, index: LodIndex, layer: u8) -> AbsIndex {
let anchor_lod = index.align_to_layer_id(X::anchor_layer_id);
let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]);
let wanted_abs = self.int_recursive_get(anchor_abs, index, layer);
debug_assert_eq!(wanted_abs.layer, layer);
wanted_abs
}
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 set15(&mut self, index: LodIndex, value: X::L15, delta: Option<X::Delta>) {
let n = self.int_get_n(index,15).index;
delta.map(|d| d.changed15(index, Some(value.clone())));
self.layer15[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: &mut Option<X::Delta>) {
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_layer_id(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);
if parent.layer > target_layer {
// create necessary childs:
X::drill_down(self, parent, delta);
//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_layer_id(child_layer);
let child_upper = area.upper.align_to_layer_id(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 = index::max(area.lower, child_lower);
let inner_upper = index::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: &mut Option<X::Delta>) {
let anchor_layer_id = X::anchor_layer_id;
let anchor_lower = area.lower.align_to_layer_id(anchor_layer_id);
let anchor_upper = area.upper.align_to_layer_id(anchor_layer_id);
let lower_xyz = anchor_lower.get();
let upper_xyz = anchor_upper.get();
let anchor_width = index::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 {
X::drill_down(self, anchor_abs, delta);
let child_lod_upper = Self::get_last_child_lod(anchor_lod, anchor_abs.layer);
let inner_lower = index::max(area.lower, anchor_lod);
let inner_upper = index::min(area.upper, child_lod_upper);
//println!("{}call child with lower, upper {} {} instead of {} {} ", Self::debug_offset(anchor_layer_id), inner_lower, inner_upper, anchor_lod, child_lod_upper);
let inner_area = LodArea::new(inner_lower, inner_upper);
self.int_make_at_least(anchor_abs, inner_area, target_layer, delta);
}
z += anchor_width;
}
y += anchor_width;
}
x += anchor_width;
}
}
fn make_at_most(&mut self, area: LodArea, layer: i8) {
}
fn make_exactly(&mut self, area: LodArea, layer: i8) {
}
}
impl LodIntoOptionUsize for () {
fn is_some(self) -> bool {
false
}
fn into_usize(self) -> usize {
unreachable!("dummyUsize")
}
}
impl LodIntoOptionUsize for u32 {
fn is_some(self) -> bool {
self != u32::MAX
}
fn into_usize(self) -> usize {
self as usize
}
}

View File

@ -0,0 +1,97 @@
use super::{
data::{
LodData,
LodConfig,
},
index::LodIndex,
area::LodArea,
};
/*
A LodDelta applies a change to a Lod
The rules for LodDeltas are strict in order to make them as simple as possible.
A LodDelta created from LodData A can only be applied safely to another LodData equal to A.
However LodDeltas can be combined and reverted
I am not sure about a Vec or Hashmap, the thing is Vec is easier to fill, but might contain duplicate entries:
E.g. change a item multiple time, bloats the Delta, with a Hashmap only the lastest state is kept.
However i belive that most algorithms only change every Value once.
*/
pub trait LodDelta {
type Config: LodConfig;
fn apply(&self, data: &mut LodData::<Self::Config>);
fn filter(&self, area: LodArea) -> Self;
fn changed0(&mut self, index: LodIndex, value: Option<<Self::Config as LodConfig>::L0>);
fn changed15(&mut self, index: LodIndex, value: Option<<Self::Config as LodConfig>::L15>);
}
#[derive(Debug, Clone)]
pub struct DefaultLodDelta<X: LodConfig> {
pub layer0: Vec<(LodIndex, Option<X::L0>)>, // 1/16
pub layer1: Vec<(LodIndex, Option<X::L1>)>, // 1/8
pub layer2: Vec<(LodIndex, Option<X::L2>)>, // 1/4
pub layer3: Vec<(LodIndex, Option<X::L3>)>, // 1/2
pub layer4: Vec<(LodIndex, Option<X::L4>)>, // 1
pub layer5: Vec<(LodIndex, Option<X::L5>)>, // 2
pub layer6: Vec<(LodIndex, Option<X::L6>)>, // 4
pub layer7: Vec<(LodIndex, Option<X::L7>)>, // 8
pub layer8: Vec<(LodIndex, Option<X::L8>)>, // 16
pub layer9: Vec<(LodIndex, Option<X::L9>)>, // 32
pub layer10: Vec<(LodIndex, Option<X::L10>)>, // 64
pub layer11: Vec<(LodIndex, Option<X::L11>)>, // 128
pub layer12: Vec<(LodIndex, Option<X::L12>)>, // 256
pub layer13: Vec<(LodIndex, Option<X::L13>)>, // 512
pub layer14: Vec<(LodIndex, Option<X::L14>)>, // 1024
pub layer15: Vec<(LodIndex, Option<X::L15>)>, // 2048
}
impl<X: LodConfig> DefaultLodDelta<X> {
fn new() -> Self {
Self {
layer0: Vec::new(),
layer1: Vec::new(),
layer2: Vec::new(),
layer3: Vec::new(),
layer4: Vec::new(),
layer5: Vec::new(),
layer6: Vec::new(),
layer7: Vec::new(),
layer8: Vec::new(),
layer9: Vec::new(),
layer10: Vec::new(),
layer11: Vec::new(),
layer12: Vec::new(),
layer13: Vec::new(),
layer14: Vec::new(),
layer15: Vec::new(),
}
}
}
impl<X: LodConfig> LodDelta for DefaultLodDelta<X> {
type Config = X;
//TODO: apply that moves out
fn apply(&self, data: &mut LodData::<Self::Config>) {
for (index, item) in &self.layer15 {
if item.is_some() {
data.set15(*index, item.clone().unwrap(), None);
}
}
}
fn filter(&self, area: LodArea) -> Self {
Self::new()
}
fn changed0(&mut self, index: LodIndex, value: Option<<Self::Config as LodConfig>::L0>) {
self.layer0.push((index, value));
}
fn changed15(&mut self, index: LodIndex, value: Option<<Self::Config as LodConfig>::L15>){
self.layer15.push((index, value));
}
}

View File

@ -5,22 +5,20 @@ use std::cmp;
use std::fmt;
/*
For our LodStructures we need a type that covers the values from 0 - 2047 in steps of 1/32.
which is 11 bits for the digits before the decimal point and 5 bits for the digits after the decimal point.
Because for accessing the decimal point makes no difference we use a u16 to represent this value.
The value needs to be shiftet to get it's "real inworld size",
A region owns the Values from in (0, 2048) in steps of 1/32.
But because regions can also subscribe we add support to the range (0, 2048*3).
which is 13 bits for the digits before the decimal point and 5 bits for the digits after the decimal point.
We use our own LodIndex type to store and compute based on these values, because u16 arithmetic (inside the owned area) is super easy to archive and allows us to optimize a lot.
Edit: now it actually implements a value from 0 - 3*2048 - 1/32, covering over 3 regions for accessing neighbor region values
-- lower neighbor
0 -> 0
1 -> 2047 31/32
65535 -> 2047 31/32
-- owned
65536 -> 2048
131071 -> 4095 31/32
-- upper neighbor
196607 -> 6143 31/32
*/
#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
@ -40,6 +38,7 @@ const BIT_Y_MASK: u64 = 0b0000_0000_0000_0000_0000_0000_0000_1111_1111_1111_1111
const BIT_Z_MASK: u64 = 0b0000_0000_0011_1111_1111_1111_1111_0000_0000_0000_0000_0000_0000_0000_0000_0000;
const BIT_X_MASK32: u32 = 0b0000_0000_0000_0011_1111_1111_1111_1111;
//TODO: Optimize!
impl LodIndex {
pub fn new(data: Vec3<u32>) -> Self {
let mut index = LodIndex {data: 0};
@ -61,9 +60,9 @@ impl LodIndex {
self.data = x + y + z;
}
pub fn align_to_layer_id(&self, level: u8) -> LodIndex {
pub fn align_to_layer_id(&self, layer: u8) -> LodIndex {
let xyz = self.get();
let f = two_pow_u(level) as u32;
let f = two_pow_u(layer) as u32;
LodIndex::new(xyz.map(|i| {
(i / f) * f
}))
@ -105,6 +104,50 @@ impl fmt::Display for AbsIndex {
}
}
impl Sub for LodIndex {
type Output = LodIndex;
fn sub(self, rhs: LodIndex) -> Self::Output {
LodIndex {
data: self.data - rhs.data /*fast but has overflow issues*/
}
}
}
impl Add for LodIndex {
type Output = LodIndex;
fn add(self, rhs: LodIndex) -> Self::Output {
LodIndex {
data: self.data + rhs.data /*fast but has overflow issues*/
}
}
}
pub const fn two_pow_u(n: u8) -> u16 {
1 << n
}
pub fn relative_to_1d(child_lod: LodIndex, parent_lod: LodIndex, child_layer: u8, relative_size: Vec3<u32>) -> usize {
let width = two_pow_u(child_layer) as u32;
let index = (child_lod.get() - parent_lod.get()).map(|e| e / width);
(index[0] * relative_size[2] * relative_size[1] + index[1] * relative_size[2] + index[2]) as usize
}
pub fn min(lhs: LodIndex, rhs: LodIndex) -> LodIndex {
let lhs = lhs.get();
let rhs = rhs.get();
LodIndex::new(lhs.map2(rhs, |a,b| cmp::min(a,b)))
}
pub fn max(lhs: LodIndex, rhs: LodIndex) -> LodIndex {
let lhs = lhs.get();
let rhs = rhs.get();
LodIndex::new(lhs.map2(rhs, |a,b| cmp::max(a,b)))
}
/*************
TESTS
**************/
#[cfg(test)]
mod tests {
use crate::{
@ -213,43 +256,3 @@ mod tests {
}
}
impl Sub for LodIndex {
type Output = LodIndex;
fn sub(self, rhs: LodIndex) -> Self::Output {
LodIndex {
data: self.data - rhs.data /*fast but has overflow issues*/
}
}
}
impl Add for LodIndex {
type Output = LodIndex;
fn add(self, rhs: LodIndex) -> Self::Output {
LodIndex {
data: self.data + rhs.data /*fast but has overflow issues*/
}
}
}
pub const fn two_pow_u(n: u8) -> u16 {
1 << n
}
pub fn relative_to_1d(child_lod: LodIndex, parent_lod: LodIndex, child_layer: u8, relative_size: Vec3<u32>) -> usize {
let width = two_pow_u(child_layer) as u32;
let index = (child_lod.get() - parent_lod.get()).map(|e| e / width);
(index[0] * relative_size[2] * relative_size[1] + index[1] * relative_size[2] + index[2]) as usize
}
pub fn min(lhs: LodIndex, rhs: LodIndex) -> LodIndex {
let lhs = lhs.get();
let rhs = rhs.get();
LodIndex::new(lhs.map2(rhs, |a,b| cmp::min(a,b)))
}
pub fn max(lhs: LodIndex, rhs: LodIndex) -> LodIndex {
let lhs = lhs.get();
let rhs = rhs.get();
LodIndex::new(lhs.map2(rhs, |a,b| cmp::max(a,b)))
}

View File

@ -1,469 +1,6 @@
pub mod index;
use std::u32;
use std::sync::Arc;
use std::collections::HashMap;
use vek::*;
use index::{
LodIndex,
AbsIndex,
relative_to_1d,
};
/*
LOD Data contains different Entries in different vecs, every entry has a "pointer" to it's child start.
This is the structure to store a region and all subscribed information
*/
pub trait LodIntoOptionUsize: Copy {
fn is_some(self) -> bool;
fn into_usize(self) -> usize;
}
pub trait LodConfig {
type L0; // 2^-4
type L1;
type L2;
type L3;
type L4; // 2^0
type L5;
type L6;
type L7;
type L8;
type L9;
type L10;
type L11;
type L12;
type L13;
type L14;
type L15; // 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;
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
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;
}
/*
There is another optimization problem: We have OWNED data and foreign DATA in the struct, but we don't want the foreign data to take a lot of space if unused
But both needs to be accessible transparent without overhead in calculation, difficult.
Imagine a Terrain, which top level is L13, so it would have 64 entries for the owned and 1664 for foreign data if everything is filled.
So we really only fill the boarder giving us 152 border areas.
One could think about multiple entry levels for foreign and owned data, but that means, that foreign data without a parent would exist, which might break algorithms....
So for now we go with a single anchorlevel for now, and hope the designer chooses good levels
*/
#[derive(Debug, Clone)]
pub struct LodData<X: LodConfig> {
pub layer0: Vec<X::L0>, // 1/16
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>,
}
impl<X: LodConfig> LodData<X>
{
pub fn new() -> Self {
Self {
layer0: Vec::new(),
layer1: Vec::new(),
layer2: Vec::new(),
layer3: Vec::new(),
layer4: Vec::new(),
layer5: Vec::new(),
layer6: Vec::new(),
layer7: Vec::new(),
layer8: Vec::new(),
layer9: Vec::new(),
layer10: Vec::new(),
layer11: Vec::new(),
layer12: Vec::new(),
layer13: Vec::new(),
layer14: Vec::new(),
layer15: Vec::new(),
child0: Vec::new(),
child1: Vec::new(),
child2: Vec::new(),
child3: Vec::new(),
child4: Vec::new(),
child5: Vec::new(),
child6: Vec::new(),
child7: Vec::new(),
child8: Vec::new(),
child9: Vec::new(),
child10: Vec::new(),
child11: Vec::new(),
child12: Vec::new(),
child13: Vec::new(),
child14: Vec::new(),
child15: Vec::new(),
anchor: HashMap::new(),
}
}
// dynamically dispatches the get_child_index, this is most prob the bottleneck function.
// evaluate the performacne impact!!!
fn int_get_child_index(&self, abs: AbsIndex) -> usize {
match abs.layer {
0 => self.child0[abs.index].into_usize(),
1 => self.child1[abs.index].into_usize(),
2 => self.child2[abs.index].into_usize(),
3 => self.child3[abs.index].into_usize(),
4 => self.child4[abs.index].into_usize(),
5 => self.child5[abs.index].into_usize(),
6 => self.child6[abs.index].into_usize(),
7 => self.child7[abs.index].into_usize(),
8 => self.child8[abs.index].into_usize(),
9 => self.child9[abs.index].into_usize(),
10 => self.child10[abs.index].into_usize(),
11 => self.child11[abs.index].into_usize(),
12 => self.child12[abs.index].into_usize(),
13 => self.child13[abs.index].into_usize(),
14 => self.child14[abs.index].into_usize(),
15 => self.child15[abs.index].into_usize(),
_ => panic!("wrong abs index"),
}
}
// Returns the childs AbsIndex of Parent AbsIndex
// child_lod must lie within parent
// uses parent_lod as buffer, to not calculate it again
// uses parent_child_index as a buffer, to not calculate it again
fn int_get(parent_abs: AbsIndex, child_lod: LodIndex, parent_lod: LodIndex, parent_child_index: usize) -> AbsIndex {
let child_layer = X::child_layer_id[parent_abs.layer as usize].unwrap();
let child_lod = child_lod.align_to_layer_id(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::ppp(parent_abs.layer), parent_abs, child_lod, parent_lod, parent_child_index, child_offset);
AbsIndex::new(child_layer, parent_child_index + child_offset)
}
// slower variant of int_get which requiere self lookups
fn int_get_lockup(&self, parent_abs: AbsIndex, child_lod: LodIndex) -> AbsIndex {
let parent_lod = child_lod.align_to_layer_id(parent_abs.layer);
let parent_child_index = self.int_get_child_index(parent_abs);
Self::int_get(parent_abs, child_lod, parent_lod, parent_child_index)
}
// target_layer is requiered because same LodIndex can exist for multiple layers, and guessing is stupid here
fn int_recursive_get(&self, parent_abs: AbsIndex, child_lod: LodIndex, target_layer:u8) -> AbsIndex {
let mut parent_abs = parent_abs;
while true {
//println!("{} int_recursive_get {} - {}", Self::ppp(parent_abs.layer), parent_abs, target_layer);
parent_abs = self.int_get_lockup(parent_abs, child_lod);
if parent_abs.layer <= target_layer {
return parent_abs;
}
}
unreachable!();
}
pub fn get15(&self, index: LodIndex) -> &X::L15 {
let anchor_lod = index.align_to_layer_id(X::anchor_layer_id);
let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]);
let wanted_abs = self.int_recursive_get(anchor_abs, index, 15);
debug_assert_eq!(wanted_abs.layer, 15);
&self.layer15[wanted_abs.index]
}
pub fn get14(&self, index: LodIndex) -> &X::L14 {
let anchor_lod = index.align_to_layer_id(X::anchor_layer_id);
let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]);
let wanted_abs = self.int_recursive_get(anchor_abs, index, 14);
debug_assert_eq!(wanted_abs.layer, 14);
&self.layer14[wanted_abs.index]
}
pub fn get13(&self, index: LodIndex) -> &X::L13 {
let anchor_lod = index.align_to_layer_id(X::anchor_layer_id);
let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]);
let wanted_abs = self.int_recursive_get(anchor_abs, index, 13);
debug_assert_eq!(wanted_abs.layer, 13);
&self.layer13[wanted_abs.index]
}
pub fn get12(&self, index: LodIndex) -> &X::L12 {
let anchor_lod = index.align_to_layer_id(X::anchor_layer_id);
let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]);
let wanted_abs = self.int_recursive_get(anchor_abs, index, 12);
debug_assert_eq!(wanted_abs.layer, 12);
&self.layer12[wanted_abs.index]
}
pub fn get11(&self, index: LodIndex) -> &X::L11 {
let anchor_lod = index.align_to_layer_id(X::anchor_layer_id);
let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]);
let wanted_abs = self.int_recursive_get(anchor_abs, index, 11);
debug_assert_eq!(wanted_abs.layer, 11);
&self.layer11[wanted_abs.index]
}
pub fn get10(&self, index: LodIndex) -> &X::L10 {
let anchor_lod = index.align_to_layer_id(X::anchor_layer_id);
let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]);
let wanted_abs = self.int_recursive_get(anchor_abs, index, 10);
debug_assert_eq!(wanted_abs.layer, 10);
&self.layer10[wanted_abs.index]
}
pub fn get9(&self, index: LodIndex) -> &X::L9 {
let anchor_lod = index.align_to_layer_id(X::anchor_layer_id);
let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]);
let wanted_abs = self.int_recursive_get(anchor_abs, index, 9);
debug_assert_eq!(wanted_abs.layer, 9);
&self.layer9[wanted_abs.index]
}
pub fn get8(&self, index: LodIndex) -> &X::L8 {
let anchor_lod = index.align_to_layer_id(X::anchor_layer_id);
let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]);
let wanted_abs = self.int_recursive_get(anchor_abs, index, 8);
debug_assert_eq!(wanted_abs.layer, 8);
&self.layer8[wanted_abs.index]
}
pub fn get7(&self, index: LodIndex) -> &X::L7 {
let anchor_lod = index.align_to_layer_id(X::anchor_layer_id);
let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]);
let wanted_abs = self.int_recursive_get(anchor_abs, index, 7);
debug_assert_eq!(wanted_abs.layer, 7);
&self.layer7[wanted_abs.index]
}
pub fn get6(&self, index: LodIndex) -> &X::L6 {
let anchor_lod = index.align_to_layer_id(X::anchor_layer_id);
let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]);
let wanted_abs = self.int_recursive_get(anchor_abs, index, 6);
debug_assert_eq!(wanted_abs.layer, 6);
&self.layer6[wanted_abs.index]
}
pub fn get5(&self, index: LodIndex) -> &X::L5 {
let anchor_lod = index.align_to_layer_id(X::anchor_layer_id);
let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]);
let wanted_abs = self.int_recursive_get(anchor_abs, index, 5);
debug_assert_eq!(wanted_abs.layer, 5);
&self.layer5[wanted_abs.index]
}
pub fn get4(&self, index: LodIndex) -> &X::L4 {
let anchor_lod = index.align_to_layer_id(X::anchor_layer_id);
let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]);
//println!("4aa4 {:?} - {:?}", anchor_lod, anchor_abs );
let wanted_abs = self.int_recursive_get(anchor_abs, index, 4);
debug_assert_eq!(wanted_abs.layer, 4);
&self.layer4[wanted_abs.index]
}
pub fn get3(&self, index: LodIndex) -> &X::L3 {
let anchor_lod = index.align_to_layer_id(X::anchor_layer_id);
let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]);
let wanted_abs = self.int_recursive_get(anchor_abs, index, 3);
debug_assert_eq!(wanted_abs.layer, 3);
&self.layer3[wanted_abs.index]
}
pub fn get2(&self, index: LodIndex) -> &X::L2 {
let anchor_lod = index.align_to_layer_id(X::anchor_layer_id);
let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]);
let wanted_abs = self.int_recursive_get(anchor_abs, index, 2);
debug_assert_eq!(wanted_abs.layer, 2);
&self.layer2[wanted_abs.index]
}
pub fn get1(&self, index: LodIndex) -> &X::L1 {
let anchor_lod = index.align_to_layer_id(X::anchor_layer_id);
let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]);
let wanted_abs = self.int_recursive_get(anchor_abs, index, 1);
debug_assert_eq!(wanted_abs.layer, 1);
&self.layer1[wanted_abs.index]
}
pub fn get0(&self, index: LodIndex) -> &X::L0 {
let anchor_lod = index.align_to_layer_id(X::anchor_layer_id);
let anchor_abs = AbsIndex::new(X::anchor_layer_id, self.anchor[&anchor_lod]);
let wanted_abs = self.int_recursive_get(anchor_abs, index, 0);
debug_assert_eq!(wanted_abs.layer, 0);
&self.layer0[wanted_abs.index]
}
// returns the last LodIndex, that belongs to a parent AbsIndex
fn get_last_child_lod(parent: LodIndex, parent_level: u8) -> LodIndex {
let child_width = index::two_pow_u(X::child_layer_id[parent_level as usize].unwrap()) as u32;
parent + LodIndex::new(X::layer_volume[X::child_layer_id[parent_level as usize].unwrap() as usize].map(|e| (e-1)*child_width))
}
fn ppp(level: u8) -> &'static str {
match level {
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,*/ lower: LodIndex, upper: LodIndex, target_level: u8) {
let child_layer = X::child_layer_id[parent.layer as usize];
let parent_lod_width = index::two_pow_u(parent.layer) as u32;
let parent_lod = lower.align_to_layer_id(parent.layer);
//assert_eq!(parent_lod, parent_lod2);
//println!("{} lower, upper {} {} {} - {:?}", Self::ppp(parent.layer), lower, upper, parent_lod_width, child_layer);
if parent.layer > target_level {
// create necessary childs:
X::drill_down(self, parent);
//println!("{} DRILLED DOWN", Self::ppp(parent.layer));
if child_layer.is_some() && child_layer.unwrap() > target_level {
let child_layer = child_layer.unwrap();
let child_lod_width = index::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 = lower.align_to_layer_id(child_layer);
let child_upper = upper.align_to_layer_id(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::ppp(parent.layer), lower_xyz);
//println!("{} uxyz {}", Self::ppp(parent.layer), upper_xyz);
//println!("{} child_lod_width {}", Self::ppp(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::ppp(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 = index::max(lower, child_lower);
let inner_upper = index::min(upper, child_upper);
//println!("{} restrict {} {} to {} {}", Self::ppp(parent.layer), lower, upper, inner_lower, inner_upper);
Self::int_make_at_least(self, child_abs, inner_lower, inner_upper, target_level);
}
}
}
}
}
}
/*
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, lower: LodIndex, upper: LodIndex, target_level: u8) {
//ERROR, DOES NOT RECURSIVLY CALL
let anchor_layer_id = X::anchor_layer_id;
let anchor_lower = lower.align_to_layer_id(anchor_layer_id);
let anchor_upper = upper.align_to_layer_id(anchor_layer_id);
let lower_xyz = anchor_lower.get();
let upper_xyz = anchor_upper.get();
let anchor_width = index::two_pow_u(anchor_layer_id) as u32;
let mut x = lower_xyz[0];
//println!("{} xxx lower, upper {} {} {}", Self::ppp(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_level {
X::drill_down(self, anchor_abs);
let child_lod_upper = Self::get_last_child_lod(anchor_lod, anchor_abs.layer);
let inner_lower = index::max(lower, anchor_lod);
let inner_upper = index::min(upper, child_lod_upper);
//println!("{}call child with lower, upper {} {} instead of {} {} ", Self::ppp(anchor_layer_id), inner_lower, inner_upper, anchor_lod, child_lod_upper);
self.int_make_at_least(anchor_abs, inner_lower, inner_upper, target_level);
}
z += anchor_width;
}
y += anchor_width;
}
x += anchor_width;
}
}
fn make_at_most(&mut self, lower: LodIndex, upper: LodIndex, level: i8) {
}
fn make_exactly(&mut self, lower: LodIndex, upper: LodIndex, level: i8) {
}
}
impl LodIntoOptionUsize for () {
fn is_some(self) -> bool {
false
}
fn into_usize(self) -> usize {
unreachable!("dummyUsize")
}
}
impl LodIntoOptionUsize for u32 {
fn is_some(self) -> bool {
self != u32::MAX
}
fn into_usize(self) -> usize {
self as usize
}
}
pub mod area;
pub mod data;
pub mod delta;
pub use data::LodData;
pub use data::LodConfig;

View File

@ -3,6 +3,9 @@ use crate::lodstore::{
LodConfig,
index::LodIndex,
index::AbsIndex,
area::LodArea,
delta::LodDelta,
delta::DefaultLodDelta,
};
use vek::*;
use std::u32;
@ -73,6 +76,9 @@ impl LodConfig for ExampleLodConfig {
type I14 = ();
type I15 = ();
type Delta = DefaultLodDelta<Self>;
type Additional = ();
const anchor_layer_id: u8 = 13;
// this is not for the children, a layer9 has 32x32x32 childs, not 16x16x16
@ -90,7 +96,7 @@ impl LodConfig for ExampleLodConfig {
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: 8, y: 8, z: 8},
Vec3{x: 0, y: 0, z: 0},
Vec3{x: 0, y: 0, z: 0},
];
@ -113,31 +119,11 @@ impl LodConfig for ExampleLodConfig {
None,
];
const layer_len: [usize; 16] = [
(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) {
fn drill_down(data: &mut LodData::<Self>, abs: AbsIndex, delta: &mut Option<DefaultLodDelta<Self>>) {
match abs.layer {
0 => {
panic!("cannot drill down further");
@ -148,6 +134,12 @@ impl LodConfig for ExampleLodConfig {
data.layer0.reserve(Self::layer_len[0]);
data.child4[abs.index] = insert as u32;
//debug!("set0 {:?} = {}", abs, insert);
// in the future use something like a child_index as parameter and a RawVec for allocations
//data.layer0[child_index..child_index+Self::layer_len[0]].iter_mut().map(
// |e| *e = Example_4{
// data: 0,
// }
// );
for i in 0..Self::layer_len[0] {
data.layer0.push(Example_4{
data: 0,
@ -187,7 +179,7 @@ impl LodConfig for ExampleLodConfig {
}
fn drill_up(data: &mut LodData::<Self>, parent_abs: AbsIndex) {
fn drill_up(data: &mut LodData::<Self>, parent_abs: AbsIndex, delta: &mut Option<DefaultLodDelta<Self>>) {
match parent_abs.layer {
0 => {
panic!("SubBlocks_4 does not have children");
@ -215,6 +207,9 @@ impl LodConfig for ExampleLodConfig {
}
}
//DELTA
#[cfg(test)]
mod tests {
use crate::{
@ -272,17 +267,20 @@ mod tests {
while result.layer9.len() < act5 as usize {
let index = randIndex(&mut rng);
let low = index.align_to_layer_id(9);
result.make_at_least(low,low,9);
let area = LodArea::new(low, low);
result.make_at_least(area,9);
}
while result.layer4.len() < act0 as usize {
let index = randIndex(&mut rng);
let low = index.align_to_layer_id(4);
result.make_at_least(low,low,4);
let area = LodArea::new(low, low);
result.make_at_least(area, 4);
}
while result.layer0.len() < act_4 as usize {
let index = randIndex(&mut rng);
let low = index.align_to_layer_id(0);
result.make_at_least(low,low,0);
let area = LodArea::new(low, low);
result.make_at_least(area, 0);
}
println!("creating Region with {} 5er, {} 0er, {} -4er", act5, act0 , act_4);
@ -301,7 +299,8 @@ mod tests {
let mut reg = createRegion(0.0, 0.0, 0.0, 0.1);
let low = LodIndex::new(Vec3::new(8192, 8192, 8192));
let high = LodIndex::new(Vec3::new(16384, 16384, 16384));
reg.make_at_least(low,high,4);
let area = LodArea::new(low, high);
reg.make_at_least(area, 4);
}
#[test]
@ -309,7 +308,8 @@ mod tests {
let mut reg = createRegion(0.0, 0.0, 0.0, 0.1);
let low = LodIndex::new(Vec3::new(0, 0, 0));
let high = LodIndex::new(Vec3::new(4, 4, 4));
reg.make_at_least(low,high,0);
let area = LodArea::new(low, high);
reg.make_at_least(area, 0);
reg.get0(LodIndex::new(Vec3::new(0, 0, 0)));
reg.get0(LodIndex::new(Vec3::new(1, 0, 0)));
reg.get0(LodIndex::new(Vec3::new(0, 1, 0)));
@ -325,7 +325,8 @@ mod tests {
let mut reg = createRegion(0.0, 0.0, 0.0, 0.1);
let low = LodIndex::new(Vec3::new(8704, 8704, 8704));
let high = LodIndex::new(Vec3::new(9216, 9216, 9216));
reg.make_at_least(low,high,0);
let area = LodArea::new(low, high);
reg.make_at_least(area, 0);
reg.get0(LodIndex::new(Vec3::new(8704, 8704, 8704)));
reg.get0(LodIndex::new(Vec3::new(9000, 9000, 9000)));
reg.get0(LodIndex::new(Vec3::new(9000, 9000, 9001)));
@ -342,7 +343,8 @@ mod tests {
let mut reg = createRegion(0.0, 0.0, 0.0, 0.1);
let low = LodIndex::new(Vec3::new(8704, 8704, 8704));
let high = LodIndex::new(Vec3::new(9216, 9216, 9216));
reg.make_at_least(low,high,0);
let area = LodArea::new(low, high);
reg.make_at_least(area, 0);
reg.get0(LodIndex::new(Vec3::new(8704, 8704, 8703)));
}
@ -352,7 +354,8 @@ mod tests {
let mut reg = createRegion(0.0, 0.0, 0.0, 0.1);
let low = LodIndex::new(Vec3::new(8704, 8704, 8704));
let high = LodIndex::new(Vec3::new(9216, 9216, 9216));
reg.make_at_least(low,high,0);
let area = LodArea::new(low, high);
reg.make_at_least(area,0);
reg.get0(LodIndex::new(Vec3::new(10240, 10240, 10240)));
}
@ -361,7 +364,8 @@ mod tests {
let mut reg = createRegion(0.0, 0.0, 0.0, 0.1);
let low = LodIndex::new(Vec3::new(8192, 8192, 8192));
let high = LodIndex::new(Vec3::new(10240, 10240, 10240));
reg.make_at_least(low,high,4);
let area = LodArea::new(low, high);
reg.make_at_least(area, 4);
}
#[test]
@ -370,7 +374,8 @@ mod tests {
let mut reg = createRegion(0.0, 0.0, 0.0, 0.1);
let low = LodIndex::new(Vec3::new(0, 0, 0));
let high = LodIndex::new(Vec3::new(4, 4, 4));
reg.make_at_least(low,high,0);
let area = LodArea::new(low, high);
reg.make_at_least(area, 0);
reg.get0(LodIndex::new(Vec3::new(5, 5, 5))); //this access is not guaranteed but will work
reg.get0(LodIndex::new(Vec3::new(16, 16, 16))); // out of range
}
@ -393,7 +398,8 @@ mod tests {
let high = LodIndex::new(Vec3::new(255, 255, 255));
b.iter(|| {
let mut reg2 = region.clone();
reg2.make_at_least(low,high,0);
let area = LodArea::new(low, high);
reg2.make_at_least(area, 0);
});
}
@ -404,7 +410,8 @@ mod tests {
let high = LodIndex::new(Vec3::new(4, 4, 4));
b.iter(|| {
let mut reg2 = region.clone();
reg2.make_at_least(low,high,0);
let area = LodArea::new(low, high);
reg2.make_at_least(area, 0);
});
}
@ -415,7 +422,8 @@ mod tests {
let high = LodIndex::new(Vec3::new(10240, 10240, 10240));
b.iter(|| {
let mut reg2 = region.clone();
reg2.make_at_least(low,high,4);
let area = LodArea::new(low, high);
reg2.make_at_least(area, 4);
});
}
@ -425,7 +433,8 @@ mod tests {
let access = LodIndex::new(Vec3::new(8561, 8312, 8412));
let low = LodIndex::new(Vec3::new(8192, 8192, 8192));
let high = LodIndex::new(Vec3::new(8800, 8800, 8800));
reg.make_at_least(low,high,0);
let area = LodArea::new(low, high);
reg.make_at_least(area, 0);
b.iter(|| reg.get0(access));
}
@ -434,7 +443,8 @@ mod tests {
let mut reg = createRegion(0.0015, 0.001, 0.001, 0.1);
let low = LodIndex::new(Vec3::new(8192, 8192, 8192));
let high = LodIndex::new(Vec3::new(8800, 8800, 8800));
reg.make_at_least(low,high,0);
let area = LodArea::new(low, high);
reg.make_at_least(area, 0);
b.iter(|| {
reg.get0(LodIndex::new(Vec3::new(8561, 8312, 8412)));
reg.get0(LodIndex::new(Vec3::new(8200, 8599, 8413)));
@ -466,7 +476,8 @@ mod tests {
let z: u16 = rng.gen();
accesslist.push(LodIndex::new(Vec3::new(x,y,z).map(|x| (8192 + x / 66) as u32)));
}
reg.make_at_least(low,high,0);
let area = LodArea::new(low, high);
reg.make_at_least(area, 0);
b.iter(|| {
for i in 0..1000000 {
reg.get0(accesslist[i]);
@ -487,7 +498,8 @@ mod tests {
let z: u16 = rng.gen();
accesslist.push(LodIndex::new(Vec3::new(x,y,z).map(|x| (8192 + x / 66) as u32)));
}
reg.make_at_least(low,high,0);
let area = LodArea::new(low, high);
reg.make_at_least(area, 0);
b.iter(|| {
for i in 0..9990000 {
reg.get0(accesslist[i]);
@ -501,8 +513,11 @@ mod tests {
let access = LodIndex::new(Vec3::new(9561, 9312, 8412));
let low = LodIndex::new(Vec3::new(8192, 8192, 8192));
let high = LodIndex::new(Vec3::new(10240, 10240, 10240));
reg.make_at_least(low,high,4);
let area = LodArea::new(low, high);
reg.make_at_least(area, 4);
b.iter(|| reg.get4(access));
}
// DELTA TESTS
}

View File

@ -0,0 +1,190 @@
use crate::lodstore::{
LodData,
LodConfig,
index::LodIndex,
index::AbsIndex,
delta::LodDelta,
delta::DefaultLodDelta,
};
use vek::*;
use std::u32;
#[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 Delta = DefaultLodDelta<Self>;
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, delta: &mut Option<DefaultLodDelta<Self>>) {
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, delta: &mut Option<DefaultLodDelta<Self>>) {
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

@ -3,8 +3,11 @@ use crate::lodstore::{
LodConfig,
index::LodIndex,
index::AbsIndex,
delta::LodDelta,
delta::DefaultLodDelta,
};
use vek::*;
use std::u32;
#[derive(Debug, Clone)]
pub struct Region9 {
@ -70,6 +73,9 @@ impl LodConfig for TerrainLodConfig {
type I14 = ();
type I15 = ();
type Delta = DefaultLodDelta<Self>;
type Additional = ();
const anchor_layer_id: u8 = 13;
const layer_volume: [Vec3<u32>; 16] = [
@ -86,7 +92,7 @@ impl LodConfig for TerrainLodConfig {
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: 8, y: 8, z: 8},
Vec3{x: 0, y: 0, z: 0},
Vec3{x: 0, y: 0, z: 0},
];
@ -108,72 +114,64 @@ impl LodConfig for TerrainLodConfig {
None,
None,
];
const layer_len: [usize; 16] = [
(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) {
fn drill_down(data: &mut LodData::<Self>, abs: AbsIndex, delta: &mut Option<DefaultLodDelta<Self>>) {
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[i+insert] = SubBlock_4{
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[i+insert] = Block0{
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.child13[abs.index] = insert as u32;
for i in 0..Self::layer_len[9] {
data.layer9[i+insert] = Chunk5{
precent_air: 0.2,
percent_forrest: 0.3,
percent_lava: 0.4,
percent_water: 0.1,
};
//ERROR HERE
unreachable!("finish this like in example");
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) {
fn drill_up(data: &mut LodData::<Self>, parent_abs: AbsIndex, delta: &mut Option<DefaultLodDelta<Self>>) {
unreachable!("finish this like in example");
match parent_abs.layer {
0 => {

View File

@ -7,7 +7,6 @@ use std::sync::{
use std::thread::sleep;
use std::time::Duration;
use std::collections::HashMap;
use vek::*;
use crate::{
job::JobManager,