1use crate::{
2 math::{self, interpolate},
3 noise_fns::{NoiseFn, Seedable},
4 permutationtable::PermutationTable,
5};
6
7#[derive(Clone, Copy, Debug)]
9pub struct Value {
10 seed: u32,
11 perm_table: PermutationTable,
12}
13
14impl Value {
15 pub const DEFAULT_SEED: u32 = 0;
16
17 pub fn new() -> Self {
18 Self {
19 seed: Self::DEFAULT_SEED,
20 perm_table: PermutationTable::new(Self::DEFAULT_SEED),
21 }
22 }
23}
24
25impl Default for Value {
26 fn default() -> Self {
27 Self::new()
28 }
29}
30
31impl Seedable for Value {
32 fn set_seed(self, seed: u32) -> Self {
34 if self.seed == seed {
36 return self;
37 }
38
39 Self {
41 seed,
42 perm_table: PermutationTable::new(seed),
43 }
44 }
45
46 fn seed(&self) -> u32 {
47 self.seed
48 }
49}
50
51impl NoiseFn<[f64; 2]> for Value {
53 fn get(&self, point: [f64; 2]) -> f64 {
54 fn get(perm_table: &PermutationTable, corner: [isize; 2]) -> f64 {
55 perm_table.get2(corner) as f64 / 255.0
56 }
57
58 let floored = math::map2(point, f64::floor);
59 let near_corner = math::to_isize2(floored);
60 let far_corner = math::add2(near_corner, math::one2());
61 let weight = math::map2(math::sub2(point, floored), interpolate::s_curve5);
62
63 let f00 = get(&self.perm_table, [near_corner[0], near_corner[1]]);
64 let f10 = get(&self.perm_table, [far_corner[0], near_corner[1]]);
65 let f01 = get(&self.perm_table, [near_corner[0], far_corner[1]]);
66 let f11 = get(&self.perm_table, [far_corner[0], far_corner[1]]);
67
68 let d0 = interpolate::linear(f00, f10, weight[0]);
69 let d1 = interpolate::linear(f01, f11, weight[0]);
70 let d = interpolate::linear(d0, d1, weight[1]);
71
72 d * 2.0 - 1.0
73 }
74}
75
76impl NoiseFn<[f64; 3]> for Value {
78 fn get(&self, point: [f64; 3]) -> f64 {
79 fn get(perm_table: &PermutationTable, corner: [isize; 3]) -> f64 {
80 perm_table.get3(corner) as f64 / 255.0
81 }
82
83 let floored = math::map3(point, f64::floor);
84 let near_corner = math::to_isize3(floored);
85 let far_corner = math::add3(near_corner, math::one3());
86 let weight = math::map3(math::sub3(point, floored), interpolate::s_curve5);
87
88 let f000 = get(
89 &self.perm_table,
90 [near_corner[0], near_corner[1], near_corner[2]],
91 );
92 let f100 = get(
93 &self.perm_table,
94 [far_corner[0], near_corner[1], near_corner[2]],
95 );
96 let f010 = get(
97 &self.perm_table,
98 [near_corner[0], far_corner[1], near_corner[2]],
99 );
100 let f110 = get(
101 &self.perm_table,
102 [far_corner[0], far_corner[1], near_corner[2]],
103 );
104 let f001 = get(
105 &self.perm_table,
106 [near_corner[0], near_corner[1], far_corner[2]],
107 );
108 let f101 = get(
109 &self.perm_table,
110 [far_corner[0], near_corner[1], far_corner[2]],
111 );
112 let f011 = get(
113 &self.perm_table,
114 [near_corner[0], far_corner[1], far_corner[2]],
115 );
116 let f111 = get(
117 &self.perm_table,
118 [far_corner[0], far_corner[1], far_corner[2]],
119 );
120
121 let d00 = interpolate::linear(f000, f100, weight[0]);
122 let d01 = interpolate::linear(f001, f101, weight[0]);
123 let d10 = interpolate::linear(f010, f110, weight[0]);
124 let d11 = interpolate::linear(f011, f111, weight[0]);
125 let d0 = interpolate::linear(d00, d10, weight[1]);
126 let d1 = interpolate::linear(d01, d11, weight[1]);
127 let d = interpolate::linear(d0, d1, weight[2]);
128
129 d * 2.0 - 1.0
130 }
131}
132
133impl NoiseFn<[f64; 4]> for Value {
135 fn get(&self, point: [f64; 4]) -> f64 {
136 fn get(perm_table: &PermutationTable, corner: [isize; 4]) -> f64 {
137 perm_table.get4(corner) as f64 / 255.0
138 }
139
140 let floored = math::map4(point, f64::floor);
141 let near_corner = math::to_isize4(floored);
142 let far_corner = math::add4(near_corner, math::one4());
143 let weight = math::map4(math::sub4(point, floored), interpolate::s_curve5);
144
145 let f0000 = get(
146 &self.perm_table,
147 [
148 near_corner[0],
149 near_corner[1],
150 near_corner[2],
151 near_corner[3],
152 ],
153 );
154 let f1000 = get(
155 &self.perm_table,
156 [
157 far_corner[0],
158 near_corner[1],
159 near_corner[2],
160 near_corner[3],
161 ],
162 );
163 let f0100 = get(
164 &self.perm_table,
165 [
166 near_corner[0],
167 far_corner[1],
168 near_corner[2],
169 near_corner[3],
170 ],
171 );
172 let f1100 = get(
173 &self.perm_table,
174 [far_corner[0], far_corner[1], near_corner[2], near_corner[3]],
175 );
176 let f0010 = get(
177 &self.perm_table,
178 [
179 near_corner[0],
180 near_corner[1],
181 far_corner[2],
182 near_corner[3],
183 ],
184 );
185 let f1010 = get(
186 &self.perm_table,
187 [far_corner[0], near_corner[1], far_corner[2], near_corner[3]],
188 );
189 let f0110 = get(
190 &self.perm_table,
191 [near_corner[0], far_corner[1], far_corner[2], near_corner[3]],
192 );
193 let f1110 = get(
194 &self.perm_table,
195 [far_corner[0], far_corner[1], far_corner[2], near_corner[3]],
196 );
197 let f0001 = get(
198 &self.perm_table,
199 [
200 near_corner[0],
201 near_corner[1],
202 near_corner[2],
203 far_corner[3],
204 ],
205 );
206 let f1001 = get(
207 &self.perm_table,
208 [far_corner[0], near_corner[1], near_corner[2], far_corner[3]],
209 );
210 let f0101 = get(
211 &self.perm_table,
212 [near_corner[0], far_corner[1], near_corner[2], far_corner[3]],
213 );
214 let f1101 = get(
215 &self.perm_table,
216 [far_corner[0], far_corner[1], near_corner[2], far_corner[3]],
217 );
218 let f0011 = get(
219 &self.perm_table,
220 [near_corner[0], near_corner[1], far_corner[2], far_corner[3]],
221 );
222 let f1011 = get(
223 &self.perm_table,
224 [far_corner[0], near_corner[1], far_corner[2], far_corner[3]],
225 );
226 let f0111 = get(
227 &self.perm_table,
228 [near_corner[0], far_corner[1], far_corner[2], far_corner[3]],
229 );
230 let f1111 = get(
231 &self.perm_table,
232 [far_corner[0], far_corner[1], far_corner[2], far_corner[3]],
233 );
234
235 let d000 = interpolate::linear(f0000, f1000, weight[0]);
236 let d010 = interpolate::linear(f0010, f1010, weight[0]);
237 let d100 = interpolate::linear(f0100, f1100, weight[0]);
238 let d110 = interpolate::linear(f0110, f1110, weight[0]);
239 let d001 = interpolate::linear(f0001, f1001, weight[0]);
240 let d011 = interpolate::linear(f0011, f1011, weight[0]);
241 let d101 = interpolate::linear(f0101, f1101, weight[0]);
242 let d111 = interpolate::linear(f0111, f1111, weight[0]);
243 let d00 = interpolate::linear(d000, d100, weight[1]);
244 let d10 = interpolate::linear(d010, d110, weight[1]);
245 let d01 = interpolate::linear(d001, d101, weight[1]);
246 let d11 = interpolate::linear(d011, d111, weight[1]);
247 let d0 = interpolate::linear(d00, d10, weight[2]);
248 let d1 = interpolate::linear(d01, d11, weight[2]);
249 let d = interpolate::linear(d0, d1, weight[3]);
250
251 d * 2.0 - 1.0
252 }
253}