forked from TheAlgorithms/Java
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSimplexNoise.java
137 lines (104 loc) · 3.8 KB
/
SimplexNoise.java
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
package com.generation;
import java.util.Random;
/**
* Implementation of the simplex noise algorithm.
*/
public class SimplexNoise {
private SimplexNoiseOctave[] octaves;
private double[] frequencys;
private double[] amplitudes;
private int largestFeature;
private double persistance;
private long seed;
/**
* @param largestFeature the diameter of the largest possible "cloud".
* @param persistence the persistence. a low persistence causes smoother transition between the features while a high one makes the transition hard. (range = {@code 0.0F} - {@code 1.0F})
* @param seed the seed this algorithm will use to generate pseudo random numbers. The generation will always look the same if the seed and the other parameters have the same value as in a previous generation
*/
public SimplexNoise(int largestFeature, double persistence, long seed) {
this.largestFeature = largestFeature;
this.persistance = persistence;
this.seed = seed;
int octaveCount = (int) Math.ceil(Math.log10(largestFeature) / Math.log10(2.0D));
this.octaves = new SimplexNoiseOctave[octaveCount];
this.frequencys = new double[octaveCount];
this.amplitudes = new double[octaveCount];
Random random = new Random(seed);
for (int index = 0; index < octaveCount; index++) {
this.octaves[index] = new SimplexNoiseOctave(random.nextInt());
this.frequencys[index] = Math.pow(2, index);
this.amplitudes[index] = Math.pow(persistence, (double) octaveCount - index);
}
}
/**
* Generates a height map.
*
* @param x X coordinate
* @param y Y coordinate
* @param width width
* @param height height
* @return the generated height map
*/
public float[][] generateHeightMap(int x, int y, int width, int height) {
int xEnd = x + width;
int yEnd = y + height;
float[][] result = new float[width][height];
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
int posX = x + i * ((xEnd - x) / width);
int posY = y + j * ((yEnd - y) / height);
result[i][j] = Math.min(1.0F, Math.max(0.0F, (float) (0.5D * (1 + this.getNoise(posX, posY)))));
}
}
return result;
}
/**
* Generates a two dimensional noise.
*
* @param x X coordinate
* @param y Y coordinate
* @return the generated noise
*/
public double getNoise(int x, int y) {
double result = 0;
for (int index = 0; index < this.octaves.length; index++) {
result += this.octaves[index].noise(x / this.frequencys[index], y / this.frequencys[index]) * this.amplitudes[index];
}
return result;
}
/**
* Generates a three dimensional noise.
*
* @param x X coordinate
* @param y Y coordinate
* @param z Z coordinate
* @return the generated noise
*/
public double getNoise(int x, int y, int z) {
double result = 0;
for (int index = 0; index < this.octaves.length; index++) {
double frequency = Math.pow(2, index);
double amplitude = Math.pow(this.persistance, (double) this.octaves.length - index);
result += this.octaves[index].noise(x / frequency, y / frequency, z / frequency) * amplitude;
}
return result;
}
/**
* @return the largest possible feature
*/
public int getLargestFeature() {
return this.largestFeature;
}
/**
* @return the persistence
*/
public double getPersistance() {
return this.persistance;
}
/**
* @return the seed
*/
public long getSeed() {
return this.seed;
}
}