1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// This example illustrates the use of different types of writing with generators to build safe trees.
use std::time::Instant;
use fastnoise2::{
generator::{
basic::{Constant, SineWave},
blend::{Add, Fade},
prelude::*,
simplex::Simplex,
FadeInterpolation,
},
SafeNode,
};
use image::{GrayImage, Luma};
const X_SIZE: i32 = 1024;
const Y_SIZE: i32 = 1024;
fn create_node() -> GeneratorWrapper<SafeNode> {
// All these writings produce the same result.
// Please note that using "0.5" (a float) instead of "Constant { value : 0.5 }" (a node) is faster
// because the right-hand member of the "Add" node is a hybrid member (either a node or a float)
// that FastNoise2 handles differently. It is also easier to write "0.5".
let _n = Add {
lhs: Fade {
a: SineWave {
feature_scale: 0.1,
..Default::default()
},
b: SineWave {
feature_scale: -0.2,
..Default::default()
},
fade: Simplex::default(),
fade_min: -1.0,
fade_max: 1.0,
interpolation: FadeInterpolation::Linear,
},
rhs: Constant { value: 0.5 }, // this uses a Constant node as entry to a hybrid member
};
let _n = Add {
lhs: Fade {
a: SineWave {
feature_scale: 0.1,
..Default::default()
},
b: SineWave {
feature_scale: -0.2,
..Default::default()
},
fade: Simplex::default(),
fade_min: -1.0,
fade_max: 1.0,
interpolation: FadeInterpolation::Linear,
},
rhs: 0.5, // and this uses a float directly
};
// You can, and I would recommend this, use functions to instance different types of nodes wrapped in a Generator, necessary for operators such as + - * /
let _n = sinewave(0.1).fade(sinewave(-0.2), simplex()) + constant(0.5); // this uses a Constant node as entry to a hybrid member
let _n = sinewave(0.1).fade(sinewave(-0.2), simplex()) + 0.5; // and this uses a float directly
// You can also mix the two writings. Note the use of the GeneratorWrapper type to enable use of the operator
let _n = GeneratorWrapper(Fade {
a: SineWave {
feature_scale: 0.1,
..Default::default()
},
b: sinewave(-0.2),
fade: Simplex::default(),
fade_min: -1.0,
fade_max: 1.0,
interpolation: FadeInterpolation::Linear,
}) + 0.5;
// Qualifying the "fade" method can also lead to better syntax, although this is subjective.
let _n = GeneratorWrapper::fade(sinewave(0.1), sinewave(-0.2), simplex()) + 0.5;
// simplex() takes two unnecessary parentheses, so you can create the Simplex structure directly, since GeneratorWrapper is not needed here.
let _n = GeneratorWrapper::fade(sinewave(0.1), sinewave(-0.2), Simplex::default()) + 0.5;
// In the end, this is the most idiomatic writing, and it's easier to import functions by using "use fastnoise2::generator::prelude::*;"
let n = sinewave(0.1).fade(sinewave(-0.2), simplex()) + 0.5;
n.build()
}
fn main() {
let node = create_node();
println!("SIMD level: {}", node.get_simd_level());
let mut noise = vec![0.0; (X_SIZE * Y_SIZE) as usize];
let step_size = 0.02;
let start = Instant::now();
let min_max = node.gen_uniform_grid_2d(
&mut noise,
-X_SIZE as f32 / 2.0 * step_size, // x_offset
-Y_SIZE as f32 / 2.0 * step_size, // y_offset
X_SIZE, // x_count
Y_SIZE, // y_count
step_size, // x_step_size
step_size, // y_step_size
1337,
);
let elapsed = start.elapsed();
println!(
"Took {elapsed:?} to generate {} values ({}/s): {min_max:?}",
noise.len(),
noise.len() as f32 / elapsed.as_secs_f32()
);
// Do whatever you want with `noise`! In this case, generate an image with it.
let mut img = GrayImage::new(X_SIZE as u32, Y_SIZE as u32);
for x in 0..X_SIZE {
for y in 0..Y_SIZE {
let index = ((Y_SIZE - 1 - y) * X_SIZE + x) as usize;
let value = noise[index];
let pixel_value = (255.0 * ((value + 1.0) / 2.0)) as u8;
img.put_pixel(x as u32, y as u32, Luma([pixel_value]));
}
}
save(img, "safe.png");
}
fn save(img: GrayImage, filename: &str) {
let output_dir =
std::path::PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap_or_default())
.join("examples_output");
std::fs::create_dir_all(&output_dir).expect("Failed to create directories");
let output_path = output_dir.join(filename);
img.save(&output_path).expect("Failed to save image");
println!("Image successfully saved as {}", output_path.display());
}