diamondSquare static method

void diamondSquare(
  1. Float32List g,
  2. TerrainOptions options
)

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);
}