diamondSquare static method
Generate random terrain using the Diamond-Square method.
Based on https://github.com/srchea/Terrain-Generation/blob/master/js/classes/TerrainGeneration.js
Float32List g
The geometry's z-positions to modify with heightmap data.
TerrainOptions options
A map of settings that control how the terrain is constructed and
displayed. Valid values are the same as those for the options parameter
of {@link THREE.Terrain}().
Implementation
static void diamondSquare(Float32List g, TerrainOptions options) {
// Set the segment length to the smallest power of 2 that is greater than
// the number of vertices in either dimension of the plane
int segments = MathUtils.ceilPowerOfTwo<int>(math.max(options.xSegments, options.ySegments) + 1).toInt();
// Initialize heightmap
final List<Float64Array> heightmap = [];
double smoothing = (options.maxHeight! - options.minHeight!);
int i,
size = segments + 1,
j,
xl = options.xSegments + 1,
yl = options.ySegments + 1;
for (i = 0; i <= segments; i++) {
heightmap.add(new Float64Array(segments+1));
}
// Generate heightmap
for (int l = segments; l >= 2; l ~/= 2) {
int half = (l*0.5).round(),
whole = l.round(),
x,
y;
double avg,
d;
smoothing /= 2;
// square
for (x = 0; x < segments; x += whole) {
for (y = 0; y < segments; y += whole) {
d = math.Random().nextDouble() * smoothing * 2 - smoothing;
avg = heightmap[x][y] + // top left
heightmap[x+whole][y] + // top right
heightmap[x][y+whole] + // bottom left
heightmap[x+whole][y+whole]; // bottom right
avg *= 0.25;
heightmap[x+half][y+half] = avg + d;
}
}
// diamond
for (x = 0; x < segments; x += half) {
for (y = (x+half) % l; y < segments; y += l) {
d = math.Random().nextDouble() * smoothing * 2 - smoothing;
avg = heightmap[(x-half+size)%size][y] + // middle left
heightmap[(x+half)%size][y] + // middle right
heightmap[x][(y+half)%size] + // middle top
heightmap[x][(y-half+size)%size]; // middle bottom
avg *= 0.25;
avg += d;
heightmap[x][y] = avg;
// top and right edges
if (x == 0) heightmap[segments][y] = avg;
if (y == 0) heightmap[x][segments] = avg;
}
}
}
// Apply heightmap
for (i = 0; i < xl; i++) {
for (j = 0; j < yl; j++) {
g[j * xl + i] += heightmap[i][j];
}
}
// static SmoothConservative(g, options);
}