Impressed by the terrain rendering in @CesiumJS - with a 10m elevation model for Norway! Farewell Google Earth. pic.twitter.com/RQKvfu2hBb
— Bjørn Sandvik (@thematicmapping) October 4, 2014
Compared to the dying Google Earth plugin, it's quite complicated to get started with Cesium. The source code is well documented and the live coding Sandcastle is great, but there is a lack of tutorials and my development slows down when I have to deal with a lot of math.
That said, I was able to create an app streaming my own terrain and imagery with a few lines of code. There is also WebGL Earth, a wrapper around Cesium giving you an API similar to well-known Leaflet. I expect to see more functions or wrappers to make stuff like camera positioning easier in the future.
How can you add your own terrain data to Cesium?
I was looking for an open source solution, and found out that Cesium supports two terrain formats:
tiled heightmap format is similar to the one I used for three.js. Each tile contains 65 x 65 height values, which overlap their neighbors at their edges to create a seamless terrain. Cesium translates the heightmap tiles into a uniform triangle mesh, as I did in three.js. The downside of this format is the uniform grid, you use the same amount of data to represent both flat and hilly terrain.
|The regular terrain mesh made from heightmap tiles.|
The quantized-mesh format follows the same tile structure as heightmap tiles, but each tile is better optimised for large-scale terrain rendering. Instead of creating a dense, uniform triangle mesh in the browser, an irregular triangle mesh is pre-rendered for each tile. It's a better representation of the landscape, having less detail in flat areas while increasing the density in steep terrain. The mesh terrain is also more memory efficient and renders faster.
|The irregular terrain mesh from quantized-mesh tiles. Larger triangles have less height variation.|
Unfortunately, I haven't found any open source tools to create tiles in the quantized-mesh format - please notify me if you know how to do it!
You can generate heightmap tiles with Cesium Terrain Builder, a great command-line utility by Homme Zwaagstra at the GeoData Institute, University of Southampton.
I'm using the same elevation data as I did for my three.js maps, but this time in full 10 meter resolution. I'm just clipping the data to my focus area (Jotunheimen) using EPSG:4326, the World Geodetic System (WGS 84).
gdalwarp -t_srs EPSG:4326 -te 7.2 60.9 9.0 61.7 -co compress=lzw -r bilinear jotunheimen.vrt jotunheimen.tif
I went for the easy option, and installed Cesium Terrain Builder using the Docker image. First I installed Docker via Homebrew. I was not able to mount my hard drive with this method, so I downloaded the elevation data from my public Dropbox folder:
I used the ctb-tile command to generate the tileset:
ctb-tile --output-dir ./tiles jotunheimen.tif
The command returned 65 000 tiles down to zoom level 15. I compressed the tiles into one file:
tar cvzf tiles.tar.gz tiles
and used the Dropbox uploader to get the tiles back to my hard drive:
./dropbox_uploader.sh upload tiles.tar.gz tiles.tar.gz
So I got 65 000 terrain tiles on my server, how can I see the beauty in Cesium? It required some extra work:
- First I had to add a missing top level tile that Cesium was expecting.
- Cesium was also looking for a layer.json file which I had to create:
- Lastly, I added a .htaccess file to support CORS and gzipped terrain tiles:
|Beautiful terrain rendered with 10 m elevation data from the Norwegian Mapping Authority. Those who know Jotunheimen, will notice Skogadalsbøen by the river and Stølsnostind and Falketind surrounded by glaciers in the background.|
|The terrain is a bit blocky (see the mount Falketind to the left), but I'm not sure if this is happening in Cesium Terrain Builder or Cesium itself. The quantized-mesh tiles from AGI gives a better result.|
I'm not able so show an interactive version, as I'm using detailed aerial imagery from "Norge i bilder", which are not publicly available.