1use super::color::*;
4use super::distance::*;
5use super::dna::*;
6use super::ease::*;
7use super::map3::*;
8use super::map3base::*;
9use super::math::*;
10use super::noise::*;
11use super::voronoi::*;
12use super::*;
13extern crate alloc;
14use alloc::boxed::Box;
15
16pub fn gen_metric(dna: &mut Dna, name: &str) -> Distance {
18 dna.choice(
19 name,
20 [
21 (1.0, "1-norm", Distance::Norm1),
22 (4.0, "2-norm", Distance::Norm2),
23 (1.0, "4-norm", Distance::Norm4),
24 (1.0, "8-norm", Distance::Norm8),
25 (1.0, "max norm", Distance::NormMax),
26 ],
27 )
28}
29
30pub fn gen_ease_smooth(dna: &mut Dna, name: &str) -> Ease {
32 dna.choice(
33 name,
34 [
35 (1.0, "smooth3", Ease::Smooth3),
36 (2.0, "smooth5", Ease::Smooth5),
37 (1.0, "smooth7", Ease::Smooth7),
38 (1.0, "smooth9", Ease::Smooth9),
39 (1.0, "squared", Ease::Squared),
40 (1.0, "cubed", Ease::Cubed),
41 (1.0, "up arc", Ease::UpArc),
42 ],
43 )
44}
45
46pub fn gen_ease_voronoi(dna: &mut Dna, name: &str) -> Ease {
48 dna.choice(
49 name,
50 [
51 (1.0, "id", Ease::Id),
52 (1.0, "smooth3", Ease::Smooth3),
53 (1.0, "smooth5", Ease::Smooth5),
54 (1.0, "smooth7", Ease::Smooth7),
55 (1.0, "smooth9", Ease::Smooth9),
56 (1.0, "squared", Ease::Squared),
57 ],
58 )
59}
60
61pub fn gen_ease(dna: &mut Dna, name: &str) -> Ease {
63 dna.choice(
64 name,
65 [
66 (1.0, "id", Ease::Id),
67 (1.0, "smooth3", Ease::Smooth3),
68 (1.0, "smooth5", Ease::Smooth5),
69 (1.0, "smooth7", Ease::Smooth7),
70 (1.0, "smooth9", Ease::Smooth9),
71 (1.0, "sqrt", Ease::Sqrt),
72 (1.0, "squared", Ease::Squared),
73 (1.0, "cubed", Ease::Cubed),
74 (1.0, "down arc", Ease::DownArc),
75 (1.0, "up arc", Ease::UpArc),
76 ],
77 )
78}
79
80pub fn genmap3palette(complexity: f32, tiling: TilingMode, dna: &mut Dna) -> Box<dyn Texture> {
82 match tiling {
83 TilingMode::None => genmap3palette_hasher(complexity, tile_none(), dna),
84 TilingMode::Z => genmap3palette_hasher(complexity, tile_z(), dna),
85 TilingMode::XY => genmap3palette_hasher(complexity, tile_xy(), dna),
86 TilingMode::All => genmap3palette_hasher(complexity, tile_all(), dna),
87 }
88}
89
90pub fn genmap3palette_hasher<H: 'static + Hasher>(
92 complexity: f32,
93 hasher: H,
94 dna: &mut Dna,
95) -> Box<dyn Texture> {
96 let h1 = dna.f32("hue 1");
97 let s1 = dna.f32("saturation 1");
98 let l1 = dna.f32_xform("lightness 1", sqrt);
99 let h2 = dna.f32("hue 2");
100 let s2 = dna.f32("saturation 2");
101 let l2 = dna.f32_xform("lightness 2", sqrt);
102 let h3 = dna.f32("hue 3");
103 let s3 = dna.f32("saturation 3");
104 let l3 = dna.f32_xform("lightness 3", sqrt);
105 let map = genmap3_hasher(complexity, false, hasher, dna);
106
107 palette(h1, s1, l1, h2, s2, l2, h3, s3, l3, map)
108}
109
110pub fn genmap3(complexity: f32, tiling: TilingMode, dna: &mut Dna) -> Box<dyn Texture> {
112 match tiling {
113 TilingMode::None => genmap3_hasher(complexity, false, tile_none(), dna),
114 TilingMode::Z => genmap3_hasher(complexity, false, tile_z(), dna),
115 TilingMode::XY => genmap3_hasher(complexity, false, tile_xy(), dna),
116 TilingMode::All => genmap3_hasher(complexity, false, tile_all(), dna),
117 }
118}
119
120pub fn genmap3_hasher<H: 'static + Hasher>(
122 complexity: f32,
123 is_fractal: bool,
124 hasher: H,
125 dna: &mut Dna,
126) -> Box<dyn Texture> {
127 let basis_weight = if complexity <= 10.0 {
128 1.5
129 } else if complexity <= 40.0 {
130 0.8
131 } else if complexity <= 80.0 {
132 0.4
133 } else {
134 0.2
135 };
136 let unary_weight = if complexity >= 20.0 {
137 1.5
138 } else if complexity >= 5.0 {
139 1.0
140 } else {
141 0.01
142 };
143 let binary_weight = if complexity >= 8.0 { 1.0 } else { 0.01 };
144 let fractal_weight: f32 = if is_fractal {
145 0.0
147 } else if complexity >= 9.0 {
148 0.8
149 } else {
150 0.01
152 };
153
154 let choice = dna.index(
155 "node type",
156 [
157 (basis_weight, "basis"),
158 (unary_weight, "unary"),
159 (binary_weight, "binary"),
160 (fractal_weight, "fractal"),
161 ],
162 );
163
164 if choice == 0 {
165 dna.group();
166 let seed = dna.u32("seed") as u64;
168 let frequency = if is_fractal {
169 2.0
171 } else {
172 dna.f32_xform("frequency", |x| xerp(2.0, 32.0, x))
173 };
174 let texture: Box<dyn Texture> = match dna.index(
175 "basis",
176 [
177 (1.0, "gradient noise"),
178 (1.0, "value noise"),
179 (1.0, "Voronoi"),
180 (0.5, "camo"),
181 ],
182 ) {
183 0 => noise(seed, frequency, hasher.clone()),
184 1 => {
185 dna.group();
186 let ease = gen_ease_smooth(dna, "noise ease");
187 dna.ungroup();
188 vnoise(seed, frequency, ease, hasher.clone())
189 }
190 2 => {
191 dna.group();
192 let pattern_x = dna.u32_in("Voronoi X pattern", 0, 25);
193 let pattern_y = dna.u32_in("Voronoi Y pattern", 0, 25);
194 let pattern_z = dna.u32_in("Voronoi Z pattern", 0, 25);
195 let ease = gen_ease_voronoi(dna, "Voronoi ease");
196 let metric = gen_metric(dna, "distance metric");
197 dna.ungroup();
198 voronoi(
199 seed,
200 frequency,
201 ease,
202 metric,
203 hasher.clone(),
204 pattern_x as usize,
205 pattern_y as usize,
206 pattern_z as usize,
207 )
208 }
209 _ => {
210 dna.group();
211 let border = dna.generate(|dna| {
212 if dna.index("border", [(0.5, "on"), (0.5, "off")]) == 0 {
213 dna.f32_in("border width", 0.01, 0.10)
214 } else {
215 0.0
216 }
217 });
218 let sharpness = dna.f32_in("camo sharpness", 0.0, 1.0);
219 let gradient = dna.f32_in("camo gradient", 0.0, 1.0);
220 let ease = gen_ease_smooth(dna, "camo ease");
221 let metric = gen_metric(dna, "distance metric");
222 dna.ungroup();
223 camo(
224 seed,
225 frequency,
226 ease,
227 metric,
228 hasher.clone(),
229 border,
230 sharpness,
231 gradient,
232 )
233 }
234 };
235 dna.ungroup();
236 texture
237 } else if choice == 1 {
238 dna.group();
240 let child_complexity = complexity * 0.5 - 1.0;
241 let unary_node = match dna.index(
242 "unary node",
243 [
244 (1.0, "saturate"),
245 (1.0, "posterize"),
246 (1.0, "overdrive"),
247 (1.0, "vreflect"),
248 (2.0, "reflect"),
249 (3.0, "shift"),
250 ],
251 ) {
252 0 => {
253 dna.group();
254 let amount = dna.f32_in("amount", 1.0, 5.0);
255 let child = dna.generate(|dna| {
256 genmap3_hasher(child_complexity, is_fractal, hasher.clone(), dna)
257 });
258 dna.ungroup();
259 saturate(amount * amount, child)
260 }
261 1 => {
262 dna.group();
263 let levels = dna.f32_in("levels", 2.0, 10.0);
264 let sharpness: f32 = dna.f32("sharpness");
265 let child = dna.generate(|dna| {
266 genmap3_hasher(child_complexity, is_fractal, hasher.clone(), dna)
267 });
268 dna.ungroup();
269 posterize(levels, sharpness, child)
270 }
271 2 => {
272 dna.group();
273 let amount = dna.f32_in("amount", 1.0, 5.0);
274 let child = dna.generate(|dna| {
275 genmap3_hasher(child_complexity, is_fractal, hasher.clone(), dna)
276 });
277 dna.ungroup();
278 overdrive(amount * amount, child)
279 }
280 3 => {
281 dna.group();
282 let amount = dna.f32_in("amount", 1.0, 10.0);
283 let child = dna.generate(|dna| {
284 genmap3_hasher(child_complexity, is_fractal, hasher.clone(), dna)
285 });
286 dna.ungroup();
287 vreflect(amount, child)
288 }
289 4 => {
290 dna.group();
291 let amount = dna.f32_in("amount", 1.0, 2.0);
292 let x_offset = dna.f32_in("X offset", -1.0, 1.0);
293 let y_offset = dna.f32_in("Y offset", -1.0, 1.0);
294 let z_offset = dna.f32_in("Z offset", -1.0, 1.0);
295 let child = dna.generate(|dna| {
296 genmap3_hasher(child_complexity, is_fractal, hasher.clone(), dna)
297 });
298 dna.ungroup();
299 reflect(amount, vec3(x_offset, y_offset, z_offset), child)
300 }
301 _ => {
302 dna.group();
303 let seed = dna.u32("seed");
304 let child = dna.generate(|dna| {
305 genmap3_hasher(child_complexity, is_fractal, hasher.clone(), dna)
306 });
307 dna.ungroup();
308 shift(seed, child)
309 }
310 };
311 dna.ungroup();
312 unary_node
313 } else if choice == 2 {
314 dna.group();
316 let child_complexity = complexity * 0.5 - 1.0;
317 let binary_node = match dna.index(
318 "binary node",
319 [
320 (1.0, "rotate"),
321 (1.0, "softmix"),
322 (1.0, "layer"),
323 (2.0, "displace"),
324 ],
325 ) {
326 0 => {
327 dna.group();
328 let amount = dna.f32_in("amount", 1.0, 3.0);
329 let child_a = dna.generate(|dna| {
330 genmap3_hasher(child_complexity, is_fractal, hasher.clone(), dna)
331 });
332 let child_b = dna.generate(|dna| {
333 genmap3_hasher(child_complexity, is_fractal, hasher.clone(), dna)
334 });
335 dna.ungroup();
336 rotate(amount, child_a, child_b)
337 }
338 1 => {
339 dna.group();
340 let amount = dna.f32_in("amount", 1.0, 5.0);
341 let displacement = dna.f32_in("displacement", 0.0, 0.5);
342 let child_a = dna.generate(|dna| {
343 genmap3_hasher(child_complexity, is_fractal, hasher.clone(), dna)
344 });
345 let child_b = dna.generate(|dna| {
346 genmap3_hasher(child_complexity, is_fractal, hasher.clone(), dna)
347 });
348 dna.ungroup();
349 softmix3(amount * amount, displacement, child_a, child_b)
350 }
351 2 => {
352 dna.group();
353 let width = dna.f32_in("width", 1.0, 3.0);
354 let ease = gen_ease(dna, "layer ease");
355 let child_a = dna.generate(|dna| {
356 genmap3_hasher(child_complexity, is_fractal, hasher.clone(), dna)
357 });
358 let child_b = dna.generate(|dna| {
359 genmap3_hasher(child_complexity, is_fractal, hasher.clone(), dna)
360 });
361 dna.ungroup();
362 layer(width, ease, child_a, child_b)
363 }
364 _ => {
365 dna.group();
366 let amount = dna.f32_in("amount", 0.0, 0.5);
367 let child_a = dna.generate(|dna| {
368 genmap3_hasher(child_complexity, is_fractal, hasher.clone(), dna)
369 });
370 let child_b = dna.generate(|dna| {
371 genmap3_hasher(child_complexity, is_fractal, hasher.clone(), dna)
372 });
373 dna.ungroup();
374 displace(amount, child_a, child_b)
375 }
376 };
377 dna.ungroup();
378 binary_node
379 } else {
380 dna.group();
382 let child_complexity = min(20.0, complexity * 0.5 - 1.0);
383 let base_f = dna.f32_in("base frequency", 1.5, 9.0);
384 let roughness = dna.f32_xform("roughness", |x| xerp(0.4, 0.9, x));
385 let octaves = dna.u32_in("octaves", 2, 10) as usize;
386 let first_octave = dna.u32_in("first octave", 0, octaves as u32 - 1) as usize;
387 let lacunarity = dna.f32_xform("lacunarity", |x| xerp(1.5, 3.0, x));
388 let displace = dna.generate(|dna| {
389 if dna.index("displace", [(0.333, "on"), (0.666, "off")]) == 0 {
390 dna.f32_in("amount", 0.0, 0.5)
391 } else {
392 0.0
393 }
394 });
395 let layer = dna.generate(|dna| {
396 if dna.index("layer", [(0.333, "on"), (0.666, "off")]) == 0 {
397 dna.f32_in("width", 1.0, 4.0)
398 } else {
399 0.0
400 }
401 });
402 let child_basis =
403 dna.generate(|dna| genmap3_hasher(child_complexity, true, hasher.clone(), dna));
404 dna.ungroup();
405 fractal(
406 base_f,
407 octaves,
408 first_octave,
409 roughness,
410 lacunarity,
411 displace,
412 layer,
413 child_basis,
414 )
415 }
416}