Debugging conversion from MapTiler rgb-terrain to CustomHeightmapTerrainProvider

Hi folks -

I have access to a server which serves Maptiler RGB-terrain images in webp format, served as OSM-style URLs. Following the example at samples/cloud/elevation-profile/elevationProvider.js at main · maptiler/samples · GitHub, I created the following CustomHeightmapTerrainProvider:

return new Cesium.CustomHeightmapTerrainProvider({
        width: 512,
        height: 512,
        callback: async function (x, y, level) {
          let img = await terrainImageryProvider.requestImage(x, y, level);
          // img appears to be an ImageBitmap. In order to read its
          // data, you have to ask a canvas.
          const canvas = document.createElement('canvas');
          canvas.width = img.width
          canvas.height = img.height
          const context = canvas.getContext('2d')
          context.drawImage(img, 0, 0)
          let data = context.getImageData(0, 0, img.width, img.height).data;
          // data is an array of unsigned 8-bit ints.
          // So, let's create a new array.
          // All zeros, for right now.
          let array = new Float32Array(512 * 512);
          for (let y = 0; y < img.height; y++) {
            for (let x = 0; x < img.width; x++) {
              const imageDataIndex = (y * (img.width * 4)) + (x * 4);
              const red = data[imageDataIndex];
              const green = data[imageDataIndex + 1];
              const blue = data[imageDataIndex + 2];
              array[(y * img.width) + x] = -10000 + ((red * 256 * 256 + green * 256 + blue) * 0.1);
            }
          }
          return array;
        }
      });

I’ve done some spot testing, comparing the results to the results using Cesium.createWorldTerrainAsync(), and I’m pretty sure what I’ve done is wrong, but I’m not sure where to start fixing it. I’m pretty sure the tiles are in OSM rather than TMS layout.

Please don’t suggest that I convert the data into .terrain files and use the CesiumTerrainProvider; I don’t have that option right now.

Thanks in advance.

The answer is that in order to use an imagery provider to retrieve the rgb-terrain data, I need to make sure that I’m making the proper x/y/level requests, which means I need to specify the tilingScheme, because the default tilingScheme for the imagery provider I’m using is Mercator, and the default tilingScheme for this terrain provider class is the geographic tiling scheme. So adding

tilingScheme: new Cesium.WebMercatorTilingScheme(),

as an initialization setting for the terrain provider solves the problem.

Hey slbayer,

I’m in a similar situation and I was wondering what your terrainImageryProvider looked like?

      `let img = await terrainImageryProvider.requestImage(x, y, level);`

Specifically the constructor options you passed. I’m not able to get it to load quite right and I think that might be my issue.

Thanks,

Jarrett

Hi jdretz -

I can’t retrace the invocation right now, but from looking at my code, I’m virtually positive that it would have been

terrainImageryProvider = await Cesium.TileMapServiceImageryProvider.fromUrl(
  url, {
    fileExtension: "webp"
});

Hope this helps.