Two years ago we did an experiment with visualizing custom terrains in Cesium (see

At the time, the used command ‘ctb-tile’ did create the ‘heightmap’ format of terrain tiles.  Now there is an updated tool which also creates the ‘quantized-mesh’ format of terrain tiles. The ‘quantized-mesh’ format is more memory efficient and renders faster (because irregular) so let’s experiment with that.

Here more information about the various terrain tile formats and the updated tool

Note for Docker Windows users: in the Docker commands replace ‘$(pwd)’ with a fully specified directory (like ‘d:/gisdata/nederland/terrain’) and double check Docker Settings -> Shared Drives.

Step 1: Download a GeoTIFF file

As example GeoTIFF file we’ll use again a part of Texel in the Netherlands.

$ wget

Step 2: Data preprocessing

It’s recommended to transform tif file to WGS84, so lets do that with gdalwarp.

$ docker run -v $(pwd):/data geodata/gdal gdalwarp -t_srs EPSG:3857 /data/i09bz1.tif /data/i09bz13857.tif

Step 3: create output directory

$ mkdir tiles

Step 4: Run tiling

In this step we run ‘tumgis/ctb-quantized-mesh’, this image adds the -f Mesh option to ctb-tile.

$ docker run -it -v $(pwd):/data tumgis/ctb-quantized-mesh ctb-tile -f Mesh -C -o /data/tiles /data/i09bz13857.tif

Step 5: Create the layer.json file for Cesium

File layer.json is a TileJSON file for  representing map metadata ( Add the ‘-l’ option to create this file.

$ docker run -it -v $(pwd):/data tumgis/ctb-quantized-mesh ctb-tile -l -f Mesh -C -o /data/tiles /data/i09bz13857.tif 

Step 6] Download Cesium 1.51

$ wget

Step 7] Unzip Cesium

$ unzip -d cesium

Step 8] Edit helloworld

edit ./cesium/Apps/HelloWorld.html in your favorite editor, insert the following script:

Sample code see:

Step 9: run cesium terrain server

$ docker run -p 9000:8000 -v $(pwd):/data/tilesets/terrain --env WEB_DIR=/data/tilesets/terrain/cesium/ geodata/cesium-terrain-server

Test: The following statement should download 1 terrain tile

$ wget http://localhost:9000/tilesets/tiles/0/0/0.terrain

Step 10: Open browser

Open browser with case-sensitive url http://localhost:9000/Apps/HelloWorld.html

Result should be something like:

Screenshot 2018-11-26 at 21.05.14

Voila, with a few Docker commands we’ve tiled a GeoTIFF image to the new quantised-mesh format and served it up to Cesium.


  1. yes good point, I already got it working using: ‘docker run -v $(pwd):/data –rm -it tin-terrain tin-terrain dem2tintiles –input /data/i09bz13857.tif –output-dir /data/dem2tin —-output-format terrain’

  2. Thank you for your useful article. By the way, i noticed that latest cesium-terrain-server build on docker hub does not work properly. Docker users should try with previous versions (i guess v0.5.0 works properly).

      • mmm… it doesn’t seem to work. This time I downloaded Cesium 1.51 (it was 1.58 before), but it still returns error 404 😦
        Is there anything I can do to debug this error? Thank you

      • Hi, thank you for your reply.

        – Yes, using wget I can download the tile;
        – The URL is correct; if I close cesium-terrain-server, Chrome shows another error page;
        – I am on Ubuntu 18.04.

        Where should I download the Cesium zip file?

        About the HelloWorld.html file, the code that I have to replace goes here, right?

        var viewer = new Cesium.Viewer(‘cesiumContainer’); <– here?

        Thank you!

      • I think the cesium viewer is installed in wrong directory. Can you retry the whole process and use the exact statements as given without changing directories (so for download use wget/unzip).

      • Hi, I made some progresses…
        I ran the following commands:

        emanuele@emanuele-HP-ZBook-15-G3:~/data$ pwd
        emanuele@emanuele-HP-ZBook-15-G3:~/data$ ls
        emanuele@emanuele-HP-ZBook-15-G3:~/data$ docker run -v $(pwd):/data geodata/gdal gdalwarp -t_srs EPSG:3857 /data/i09bz1.tif /data/i09bz13857.tif
        Creating output file that is 10095P x 12600L.
        Processing input file /data/i09bz1.tif.
        Using internal nodata values (e.g. -3.40282e+38) for image /data/i09bz1.tif.
        Copying nodata values from source /data/i09bz1.tif to destination /data/i09bz13857.tif.
        0…10…20…30…40…50…60…70…80…90…100 – done.
        emanuele@emanuele-HP-ZBook-15-G3:~/data$ mkdir tiles
        emanuele@emanuele-HP-ZBook-15-G3:~/data$ docker run -it -v $(pwd):/data tumgis/ctb-quantized-mesh ctb-tile -f Mesh -C -o /data/tiles /data/i09bz13857.tif
        0…10…20…30…40…50…60…70…80…90…100 – done.
        emanuele@emanuele-HP-ZBook-15-G3:~/data$ wget
        –2019-06-18 13:22:37–
        Length: 93795302 (89M) [application/octet-stream]
        Saving to: ‘’ 100%[================================================================================================================>] 89,45M 123KB/s in 12m 53s

        2019-06-18 13:35:32 (118 KB/s) – ‘’ saved [93795302/93795302]
        emanuele@emanuele-HP-ZBook-15-G3:~/data$ unzip -d cesium
        emanuele@emanuele-HP-ZBook-15-G3:~/data$ gedit ./cesium/Apps/HelloWorld.html
        emanuele@emanuele-HP-ZBook-15-G3:~/data$ docker run -p 9000:8000 -v $(pwd):/data/tilesets/terrain –env WEB_DIR=/data/tilesets/terrain/cesium/ geodata/cesium-terrain-server
        *** Running /etc/my_init.d/…
        *** Running /etc/my_init.d/…
        *** Running /etc/rc.local…
        *** Booting runit daemon…
        *** Runit started as PID 10

        Then, when I open the page “http://localhost:9000/Apps/HelloWorld.html”, I see the Cesium page but there’s nothing in it: just the black background with the sun and the stars, but there’s no Earth and no terrain. 😦
        I noticed that if I click on the “Data attribution” link, It says “Data provided by: Bing maps”.

      • The “404 page not found” problem that I had at first was caused by the case-sensitive url (as you guessed). I didn’t notice that if you click on the link on step 10, the link that is opened is all lower-cased.
        The latest problem (i.e. no Earth and no terrain) happened because I accidentally forgot to create the layer.json file… and I noticed that only after I posted the reply (sorry 😀 ).

  3. Dear Bertt,
    thanks for you amazing tutorial. I am also working with the cesium-terrain-server and face a problem:

    If I use the default cesium installation served with the terrain-server everything works as expected. My custom terrain is showing up. As sonn as I change the cesium installation using the “WEB_DIR=XXX” command (to use the newest Cesium 1.62) everything works fine until I add my custom terrain: Although the tiles are served (which i ckecked with the network anaylsis tab) no globe is showing up (not even the background glow).

    Do you know what might cause the problem?

    • Hi Sebastian, I don’t know at the moment whats causing this behaviour. If I understand correctly you try to make this tutorial work in Cesium 1.62 instead of 1.51?

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s