veloren_world/util/
structure.rs1use super::{RandomField, Sampler};
2use vek::*;
3
4#[derive(Clone)]
5pub struct StructureGen2d {
6 freq: u32,
7 spread: u32,
8 x_field: RandomField,
9 y_field: RandomField,
10 seed_field: RandomField,
11}
12
13pub type StructureField = (Vec2<i32>, u32);
14
15impl StructureGen2d {
16 pub fn new(seed: u32, freq: u32, spread: u32) -> Self {
17 Self {
18 freq,
19 spread,
20 x_field: RandomField::new(seed + 0),
21 y_field: RandomField::new(seed + 1),
22 seed_field: RandomField::new(seed + 2),
23 }
24 }
25
26 #[inline]
27 fn sample_to_index_internal(freq: i32, pos: Vec2<i32>) -> Vec2<i32> {
28 pos.map(|e| e.div_euclid(freq))
29 }
30
31 #[inline]
32 pub fn sample_to_index(&self, pos: Vec2<i32>) -> Vec2<i32> {
33 Self::sample_to_index_internal(self.freq as i32, pos)
34 }
35
36 #[inline]
37 fn freq_offset(freq: i32) -> i32 { freq / 2 }
38
39 #[inline]
40 fn spread_mul(spread: u32) -> u32 { spread * 2 }
41
42 #[inline]
43 fn index_to_sample_internal(
44 freq: i32,
45 freq_offset: i32,
46 spread: i32,
47 spread_mul: u32,
48 x_field: RandomField,
49 y_field: RandomField,
50 seed_field: RandomField,
51 index: Vec2<i32>,
52 ) -> StructureField {
53 let center = index * freq + freq_offset;
54 let pos = Vec3::from(center);
55 (
56 center
57 + if spread_mul > 0 {
58 Vec2::new(
59 (x_field.get(pos) % spread_mul) as i32 - spread,
60 (y_field.get(pos) % spread_mul) as i32 - spread,
61 )
62 } else {
63 Vec2::zero()
64 },
65 seed_field.get(pos),
66 )
67 }
68
69 pub fn iter(&self, min: Vec2<i32>, max: Vec2<i32>) -> impl Iterator<Item = StructureField> {
72 let freq = self.freq;
73 let spread = self.spread;
74 let spread_mul = Self::spread_mul(spread);
75 assert!(spread * 2 == spread_mul);
76 assert!(spread_mul <= freq);
77 let spread = spread as i32;
78 let freq = freq as i32;
79 let freq_offset = Self::freq_offset(freq);
80 assert!(freq_offset * 2 == freq);
81
82 let min_index = Self::sample_to_index_internal(freq, min) - 1;
83 let max_index = Self::sample_to_index_internal(freq, max) + 1;
84 assert!(min_index.x < max_index.x);
85 let xlen = (max_index.x - min_index.x) as u32;
87 assert!(min_index.y < max_index.y);
88 let ylen = (max_index.y - min_index.y) as u32;
90 let len = ylen as u64 * xlen as u64;
92 let x_field = self.x_field;
98 let y_field = self.y_field;
99 let seed_field = self.seed_field;
100 (0..len).map(move |xy| {
101 let index = min_index + Vec2::new((xy % xlen as u64) as i32, (xy / xlen as u64) as i32);
102 Self::index_to_sample_internal(
103 freq,
104 freq_offset,
105 spread,
106 spread_mul,
107 x_field,
108 y_field,
109 seed_field,
110 index,
111 )
112 })
113 }
114}
115
116impl Sampler<'static> for StructureGen2d {
117 type Index = Vec2<i32>;
118 type Sample = [StructureField; 9];
119
120 fn get(&self, sample_pos: Self::Index) -> Self::Sample {
121 let mut samples = [(Vec2::zero(), 0); 9];
122
123 let freq = self.freq;
124 let spread = self.spread;
125 let spread_mul = Self::spread_mul(spread);
126 let spread = spread as i32;
127 let freq = freq as i32;
128 let freq_offset = Self::freq_offset(freq);
129
130 let sample_closest = Self::sample_to_index_internal(freq, sample_pos);
131
132 for i in 0..3 {
133 for j in 0..3 {
134 let index = sample_closest + Vec2::new(i as i32, j as i32) - 1;
135 let sample = Self::index_to_sample_internal(
136 freq,
137 freq_offset,
138 spread,
139 spread_mul,
140 self.x_field,
141 self.y_field,
142 self.seed_field,
143 index,
144 );
145 samples[i * 3 + j] = sample;
146 }
147 }
148
149 samples
150 }
151}