-
-
Notifications
You must be signed in to change notification settings - Fork 113
/
Copy pathperlin_noise.cpp
66 lines (63 loc) · 2.24 KB
/
perlin_noise.cpp
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
#include "util.h"
#include "perlin_noise.h"
void addAvg(int x, int y, const Table<double>& wys, double& avg, int& num) {
Vec2 pos(x, y);
if (pos.inRectangle(wys.getBounds())) {
avg += wys[pos];
++num;
}
}
Table<double> genNoiseMap(RandomGen& random, Rectangle area, NoiseInit init, double varianceMult) {
int width = 1;
while (width < area.width() - 1 || width < area.height() - 1)
width *= 2;
width /= 2;
++width;
Table<double> wys(width, width);
wys[0][0] = init.topLeft;
wys[width - 1][0] = init.topRight;
wys[width - 1][width - 1] = init.bottomRight;
wys[0][width - 1] = init.bottomLeft;
wys[(width - 1) / 2][(width - 1) / 2] = init.middle;
double variance = 0.5;
double heightDiff = 0.1;
for (int a = width - 1; a >= 2; a /= 2) {
if (a < width - 1)
for (Vec2 pos1 : Rectangle((width - 1) / a, (width - 1) / a)) {
Vec2 pos = pos1 * a;
double avg = (wys[pos] + wys[pos.x + a][pos.y] + wys[pos.x][pos.y + a] + wys[pos.x + a][pos.y + a]) / 4;
wys[pos.x + a / 2][pos.y + a / 2] =
avg + variance * (random.getDouble() * 2 - 1);
}
for (Vec2 pos1 : Rectangle((width - 1) / a, (width - 1) / a + 1)) {
Vec2 pos = pos1 * a;
double avg = 0;
int num = 0;
addAvg(pos.x + a / 2, pos.y - a / 2, wys, avg, num);
addAvg(pos.x, pos.y, wys, avg, num);
addAvg(pos.x + a, pos.y, wys, avg, num);
addAvg(pos.x + a / 2, pos.y + a / 2, wys, avg, num);
wys[pos.x + a / 2][pos.y] =
avg / num + variance * (random.getDouble() * 2 - 1);
}
for (Vec2 pos1 : Rectangle((width - 1) / a + 1, (width - 1) / a)) {
Vec2 pos = pos1 * a;
double avg = 0;
int num = 0;
addAvg(pos.x - a / 2, pos.y + a / 2, wys, avg, num);
addAvg(pos.x, pos.y, wys, avg, num);
addAvg(pos.x, pos.y + a , wys, avg, num);
addAvg(pos.x + a / 2, pos.y + a / 2, wys, avg, num);
wys[pos.x][pos.y + a / 2] =
avg / num + variance * (random.getDouble() * 2 - 1);
}
variance *= varianceMult;
}
Table<double> ret(area);
Vec2 offset(area.left(), area.top());
for (Vec2 v : area) {
Vec2 lv((v.x - offset.x) * width / area.width(), (v.y - offset.y) * width / area.height());
ret[v] = wys[lv];
}
return ret;
}