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(
72 &self,
73 min: Vec2<i32>,
74 max: Vec2<i32>,
75 ) -> impl Iterator<Item = StructureField> + use<> {
76 let freq = self.freq;
77 let spread = self.spread;
78 let spread_mul = Self::spread_mul(spread);
79 assert!(spread * 2 == spread_mul);
80 assert!(spread_mul <= freq);
81 let spread = spread as i32;
82 let freq = freq as i32;
83 let freq_offset = Self::freq_offset(freq);
84 assert!(freq_offset * 2 == freq);
85
86 let min_index = Self::sample_to_index_internal(freq, min) - 1;
87 let max_index = Self::sample_to_index_internal(freq, max) + 1;
88 assert!(min_index.x < max_index.x);
89 let xlen = (max_index.x - min_index.x) as u32;
91 assert!(min_index.y < max_index.y);
92 let ylen = (max_index.y - min_index.y) as u32;
94 let len = ylen as u64 * xlen as u64;
96 let x_field = self.x_field;
102 let y_field = self.y_field;
103 let seed_field = self.seed_field;
104 (0..len).map(move |xy| {
105 let index = min_index + Vec2::new((xy % xlen as u64) as i32, (xy / xlen as u64) as i32);
106 Self::index_to_sample_internal(
107 freq,
108 freq_offset,
109 spread,
110 spread_mul,
111 x_field,
112 y_field,
113 seed_field,
114 index,
115 )
116 })
117 }
118}
119
120impl Sampler<'static> for StructureGen2d {
121 type Index = Vec2<i32>;
122 type Sample = [StructureField; 9];
123
124 fn get(&self, sample_pos: Self::Index) -> Self::Sample {
125 let mut samples = [(Vec2::zero(), 0); 9];
126
127 let freq = self.freq;
128 let spread = self.spread;
129 let spread_mul = Self::spread_mul(spread);
130 let spread = spread as i32;
131 let freq = freq as i32;
132 let freq_offset = Self::freq_offset(freq);
133
134 let sample_closest = Self::sample_to_index_internal(freq, sample_pos);
135
136 for i in 0..3 {
137 for j in 0..3 {
138 let index = sample_closest + Vec2::new(i as i32, j as i32) - 1;
139 let sample = Self::index_to_sample_internal(
140 freq,
141 freq_offset,
142 spread,
143 spread_mul,
144 self.x_field,
145 self.y_field,
146 self.seed_field,
147 index,
148 );
149 samples[i * 3 + j] = sample;
150 }
151 }
152
153 samples
154 }
155}