private void preloadTiles(MeshTile[] tiles) {
    double minValue = Double.MAX_VALUE;
    double minScale = 1d;

    BufferWrapperRaster[] rasters = new BufferWrapperRaster[tiles.length];
    for (int i = 0; i < tiles.length; i++) {
      rasters[i] = this.readTileRaster(tiles[i]);

      double[] minAndMax = ElevationMesh.getMinAndMaxValues(rasters[i]);
      if (minAndMax[0] < minValue) minValue = minAndMax[0];

      double scale =
          ElevationMesh.suggestVerticalScale(tiles[i].getSector(), tiles[i].getMeshCoords());
      if (scale < minScale) minScale = scale;
    }

    if (minValue == Double.MAX_VALUE) minValue = 0d;
    this.verticalOffset = -minValue;
    this.verticalScale = minScale;

    for (int i = 0; i < tiles.length; i++) {
      ElevationMesh mesh =
          this.createMesh(tiles[i], rasters[i], this.verticalOffset, this.verticalScale);
      this.cache.add(tiles[i].getTileKey(), mesh);
    }
  }
  private void drawTile(GL gl, Camera camera, MeshTile tile) {
    TileKey key = tile.getTileKey();

    ElevationMesh mesh = (ElevationMesh) this.cache.getObject(key);
    if (mesh == null && !this.cache.contains(key)) {
      BufferWrapperRaster raster = this.readTileRaster(tile);
      mesh = this.createMesh(tile, raster, this.verticalOffset, this.verticalScale);
      long size = (mesh != null) ? mesh.getSizeInBytes() : 1L;
      this.cache.add(key, mesh, size);
    }

    if (mesh != null) mesh.render(gl, camera);
  }