veloren_common/volumes/
vol_grid_3d.rs1use crate::{
2 vol::{BaseVol, RasterableVol, ReadVol, SampleVol, WriteVol},
3 volumes::dyna::DynaError,
4};
5use hashbrown::{HashMap, hash_map};
6use std::{fmt::Debug, sync::Arc};
7use vek::*;
8
9#[derive(Debug)]
10pub enum VolGrid3dError<V: RasterableVol> {
11 NoSuchChunk,
12 ChunkErr(V::Error),
13 DynaError(DynaError),
14 InvalidChunkSize,
15}
16
17#[derive(Clone)]
21pub struct VolGrid3d<V: RasterableVol> {
22 chunks: HashMap<Vec3<i32>, Arc<V>>,
23}
24
25impl<V: RasterableVol> VolGrid3d<V> {
26 #[inline(always)]
27 pub fn chunk_key(pos: Vec3<i32>) -> Vec3<i32> {
28 pos.map2(V::SIZE, |e, sz: u32| e >> (sz - 1).count_ones())
29 }
30
31 #[inline(always)]
32 pub fn chunk_offs(pos: Vec3<i32>) -> Vec3<i32> {
33 pos.map2(V::SIZE, |e, sz| e & (sz - 1) as i32)
34 }
35}
36
37impl<V: RasterableVol + Debug> BaseVol for VolGrid3d<V> {
38 type Error = VolGrid3dError<V>;
39 type Vox = V::Vox;
40}
41
42impl<V: RasterableVol + ReadVol + Debug> ReadVol for VolGrid3d<V> {
43 #[inline(always)]
44 fn get(&self, pos: Vec3<i32>) -> Result<&V::Vox, VolGrid3dError<V>> {
45 let ck = Self::chunk_key(pos);
46 self.chunks
47 .get(&ck)
48 .ok_or(VolGrid3dError::NoSuchChunk)
49 .and_then(|chunk| {
50 let co = Self::chunk_offs(pos);
51 chunk.get(co).map_err(VolGrid3dError::ChunkErr)
52 })
53 }
54}
55
56impl<I: Into<Aabb<i32>>, V: RasterableVol + ReadVol + Debug> SampleVol<I> for VolGrid3d<V> {
59 type Sample = VolGrid3d<V>;
60
61 fn sample(&self, range: I) -> Result<Self::Sample, VolGrid3dError<V>> {
67 let range = range.into();
68 let mut sample = VolGrid3d::new()?;
69 let chunk_min = Self::chunk_key(range.min);
70 let chunk_max = Self::chunk_key(range.max);
71 for x in chunk_min.x..chunk_max.x + 1 {
72 for y in chunk_min.y..chunk_max.y + 1 {
73 for z in chunk_min.z..chunk_max.z + 1 {
74 let chunk_key = Vec3::new(x, y, z);
75
76 let chunk = self.get_key_arc(chunk_key).cloned();
77
78 if let Some(chunk) = chunk {
79 sample.insert(chunk_key, chunk);
80 }
81 }
82 }
83 }
84
85 Ok(sample)
86 }
87}
88
89impl<V: RasterableVol + WriteVol + Clone + Debug> WriteVol for VolGrid3d<V> {
90 #[inline(always)]
91 fn set(&mut self, pos: Vec3<i32>, vox: V::Vox) -> Result<V::Vox, VolGrid3dError<V>> {
92 let ck = Self::chunk_key(pos);
93 self.chunks
94 .get_mut(&ck)
95 .ok_or(VolGrid3dError::NoSuchChunk)
96 .and_then(|chunk| {
97 let co = Self::chunk_offs(pos);
98 Arc::make_mut(chunk)
99 .set(co, vox)
100 .map_err(VolGrid3dError::ChunkErr)
101 })
102 }
103}
104
105impl<V: RasterableVol> VolGrid3d<V> {
106 pub fn new() -> Result<Self, VolGrid3dError<V>> {
107 if Self::chunk_size()
108 .map(|e| e.is_power_of_two() && e > 0)
109 .reduce_and()
110 {
111 Ok(Self {
112 chunks: HashMap::new(),
113 })
114 } else {
115 Err(VolGrid3dError::InvalidChunkSize)
116 }
117 }
118
119 pub fn chunk_size() -> Vec3<u32> { V::SIZE }
120
121 pub fn insert(&mut self, key: Vec3<i32>, chunk: Arc<V>) -> Option<Arc<V>> {
122 self.chunks.insert(key, chunk)
123 }
124
125 pub fn get_key(&self, key: Vec3<i32>) -> Option<&V> {
126 self.chunks.get(&key).map(|arc_chunk| arc_chunk.as_ref())
127 }
128
129 pub fn get_key_arc(&self, key: Vec3<i32>) -> Option<&Arc<V>> { self.chunks.get(&key) }
130
131 pub fn remove(&mut self, key: Vec3<i32>) -> Option<Arc<V>> { self.chunks.remove(&key) }
132
133 pub fn key_pos(&self, key: Vec3<i32>) -> Vec3<i32> { key * V::SIZE.map(|e| e as i32) }
134
135 pub fn pos_key(&self, pos: Vec3<i32>) -> Vec3<i32> { Self::chunk_key(pos) }
136
137 pub fn iter(&self) -> ChunkIter<V> {
138 ChunkIter {
139 iter: self.chunks.iter(),
140 }
141 }
142}
143
144pub struct ChunkIter<'a, V: RasterableVol> {
145 iter: hash_map::Iter<'a, Vec3<i32>, Arc<V>>,
146}
147
148impl<'a, V: RasterableVol> Iterator for ChunkIter<'a, V> {
149 type Item = (Vec3<i32>, &'a Arc<V>);
150
151 fn next(&mut self) -> Option<Self::Item> { self.iter.next().map(|(k, c)| (*k, c)) }
152}