veloren_common/volumes/
scaled.rs1use crate::vol::{BaseVol, FilledVox, ReadVol, SizedVol};
2use vek::*;
3
4pub struct Scaled<V> {
5 pub inner: V,
6 pub scale: Vec3<f32>,
7}
8
9impl<V: BaseVol> BaseVol for Scaled<V> {
10 type Error = V::Error;
11 type Vox = V::Vox;
12}
13
14impl<V: ReadVol> ReadVol for Scaled<V>
15where
16 V::Vox: FilledVox,
17{
18 #[inline(always)]
19 fn get(&self, pos: Vec3<i32>) -> Result<&Self::Vox, Self::Error> {
20 let min_pos = pos.map2(self.scale, |e, scale| ((e as f32) / scale).floor() as i32);
23 let max_pos = pos.map2(self.scale, |e, scale| {
24 ((e as f32 + 1.0) / scale).ceil() as i32
25 });
26 let pos = pos.map2(self.scale, |e, scale| {
27 (((e as f32 + 0.5) / scale) - 0.5).round() as i32
28 });
29
30 let range_iter = |i: usize| {
32 std::iter::successors(Some(0), |p| Some(if *p < 0 { -*p } else { -(*p + 1) }))
33 .take_while(move |p| {
34 (min_pos[i]..max_pos[i])
35 .contains(&(pos[i] + *p))
38 })
39 };
40 range_iter(0)
41 .flat_map(|i| {
42 range_iter(1).map(move |j| range_iter(2).map(move |k| Vec3::new(i, j, k)))
43 })
44 .flatten()
45 .map(|offs| self.inner.get(pos + offs))
46 .find(|vox| vox.as_ref().is_ok_and(|v| v.is_filled()))
47 .unwrap_or_else(|| self.inner.get(pos))
48 }
49}
50
51impl<V: SizedVol> SizedVol for Scaled<V> {
52 #[inline(always)]
53 fn lower_bound(&self) -> Vec3<i32> {
54 self.inner
55 .lower_bound()
56 .map2(self.scale, |e, scale| (e as f32 * scale).floor() as i32)
57 }
58
59 #[inline(always)]
60 fn upper_bound(&self) -> Vec3<i32> {
61 self.inner
62 .upper_bound()
63 .map2(self.scale, |e, scale| (e as f32 * scale).ceil() as i32)
64 }
65}