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
use crate::grid_2d::Grid2d;
use noise::{NoiseFn, OpenSimplex, Seedable};
use std::ops::Range;
#[derive(Clone)]
pub struct NoiseMapGenerator {
seed: u32,
chunk_size: usize,
zoom: f64,
generator: OpenSimplex,
}
impl NoiseMapGenerator {
pub fn new(seed: u32, chunk_size: usize, zoom: f64) -> Self {
Self {
seed,
chunk_size: chunk_size.max(1),
zoom,
generator: OpenSimplex::new().set_seed(seed),
}
}
pub fn seed(&self) -> u32 {
self.seed
}
pub fn chunk_size(&self) -> usize {
self.chunk_size
}
pub fn zoom(&self) -> f64 {
self.zoom
}
pub fn sample_raw(&self, x: f64, y: f64, z: f64) -> f64 {
self.generator.get([x, y, z]) + 1.0 * 0.5
}
pub fn sample(
&self,
coord: (isize, isize),
(col, row): (usize, usize),
margin: usize,
depth: f64,
) -> f64 {
let col = col % (self.chunk_size + margin * 2);
let row = row % (self.chunk_size + margin * 2);
let x = self.zoom * (coord.0 as f64 * self.chunk_size as f64 + col as f64 - margin as f64)
/ self.chunk_size as f64;
let y = self.zoom * (coord.1 as f64 * self.chunk_size as f64 + row as f64 - margin as f64)
/ self.chunk_size as f64;
self.sample_raw(x, y, depth)
}
#[inline]
pub fn build_chunk(&self, coord: (isize, isize), margin: usize) -> Grid2d<f64> {
self.build_chunk_with_depth(coord, margin, 0.0)
}
pub fn build_chunk_with_depth(
&self,
coord: (isize, isize),
margin: usize,
depth: f64,
) -> Grid2d<f64> {
let mut cells = Vec::with_capacity(self.chunk_size * self.chunk_size);
let mcs = self.chunk_size + margin * 2;
for row in 0..mcs {
for col in 0..mcs {
cells.push(self.sample(coord, (col, row), margin, depth));
}
}
Grid2d::with_cells(mcs, cells)
}
#[inline]
pub fn build_chunks(&self, coord: Range<(isize, isize)>) -> Grid2d<f64> {
self.build_chunks_with_depth(coord, 0.0)
}
pub fn build_chunks_with_depth(&self, coord: Range<(isize, isize)>, depth: f64) -> Grid2d<f64> {
let xs = (coord.end.0 - coord.start.0) as usize;
let ys = (coord.end.1 - coord.start.1) as usize;
let mut cells = Vec::with_capacity(self.chunk_size * self.chunk_size * xs * ys);
for row in 0..(self.chunk_size * ys) {
for col in 0..(self.chunk_size * xs) {
let xc = coord.start.0 + (col / self.chunk_size) as isize;
let yc = coord.start.1 + (row / self.chunk_size) as isize;
cells.push(self.sample(
(xc, yc),
(col % self.chunk_size, row % self.chunk_size),
0,
depth,
));
}
}
Grid2d::with_cells(self.chunk_size * xs, cells)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_print_ascii() {
let gen = NoiseMapGenerator::new(0, 8, 4.0);
fn print_chunk(chunk: Grid2d<f64>) {
for row in 0..chunk.rows() {
let cells = chunk
.get_row_cells(row)
.unwrap()
.into_iter()
.map(|f| if f >= 0.5 { '#' } else { ' ' })
.collect::<String>();
println!("|{}|", cells);
}
}
let chunk = gen.build_chunk((0, 0), 1);
print_chunk(chunk.clone());
println!();
print_chunk(chunk.get_part((1, 1)..(9, 9)));
}
}