Is anyone using TileMapServiceTerrainProvider or WebMapServiceTerrainProvider?

Hi folks,

These don’t exist in master, only the terrain branch and other related branches. Are you using them? I’m thinking about getting rid of them (at least for now) in preparation for getting terrain into master. I don’t think they’re very useful, because…

WebMapServiceTerrainProvider theoretically lets you serve terrain from a WMS server, which sounds useful. But in practice the only WMS server it works with is GeoServer, and even then only when the BIL plugin is installed. And you may even need some wacky customizations to the BIL plugin to get it to work.

TileMapServiceTerrainProvider expects the server to produce PNGs using the TMS tile layout, which seems standard enough. But the PNGs have to use the unusual format where each height is expressed in millimeters above -1000 meters and stored as a 3 byte integer, where the red channel is the high byte, the blue channel is mid byte, and the green channel is the low byte. Since this isn’t exactly a standard format, it’s unlikely anyone already has terrain data in this format. And if you’re creating a new dataset for use with Cesium, you would be much better served by the CesiumTerrainProvider instead of using this one.

So I’d like to get rid of these. Any objections?



I’m not using any of these, although I did try once to construct heightmaps for TileMapServiceTerrainProvider. Not planning to go back to it though.


No objections here. We use the arcgis terrain provider and slightly modified it for geoserver.

We use a modified version of the existing WebMapServiceTerrainProvider with Geoserver (with the BIL plugin). Seems to work fine, even without wacky customizations to the BIL plugin.

Peter: what are you using now instead of TileMapServiceTerrainProvider?

Jonah: So you basically modified the ArcGIS provider to be a WMS provider instead? Or was it GeoServer specific?

Wayne (sorry if I guessed wrong on your name): Out of curiosity, what modifications did you make?

All: next time you sync up to the terrain branch (if you haven’t already) you’ll need to make some modifications to your custom terrain providers. You should find it vastly simpler than it used to be, but let me know if you need help.




Good guess! :slight_smile:

Basically, I just fixed the errors that existed since the WebMapServiceTerrainProvider was lagging behind. I applied some of the changes from the ArcGISTerrainProvider to fix them.

Here's the relevant bits from the diff (sorry for the formatting):

@@ -84,6 +84,8 @@ define([
         this.tilingScheme = new GeographicTilingScheme();
         this.maxLevel = 18;
+ this.heightmapWidth = 64;
+ this.levelZeroMaximumGeometricError = TerrainProvider.getEstimatedLevelZeroGeometricErrorForAHeightmap(this.tilingScheme.getEllipsoid(), this.heightmapWidth, this.tilingScheme.getNumberOfXTilesAtLevel(0));

@@ -114,6 +116,14 @@ define([
         return maxErrorRadians;

+ WebMapServiceTerrainProvider.prototype.getLevelMaximumGeometricError = TerrainProvider.prototype.getLevelMaximumGeometricError;

@@ -140,7 +150,7 @@ define([
      * @param {Tile} The tile to request geometry for.
     WebMapServiceTerrainProvider.prototype.requestTileGeometry = function(tile) {
- if (requestsInFlight > 1) {
+ if (requestsInFlight > 6) {

@@ -194,14 +204,14 @@ define([
     WebMapServiceTerrainProvider.prototype.transformGeometry = function(context, tile) {
         var tilingScheme = this.tilingScheme;
- var ellipsoid = tilingScheme.ellipsoid;
+ var ellipsoid = tilingScheme.getEllipsoid();
         var extent = tile.extent;

         var width = 64;
         var height = 64;

         var nativeExtent = tilingScheme.tileXYToNativeExtent(tile.x, tile.y, tile.level);
- = ellipsoid.cartographicToCartesian(extent.getCenter());
+ = ellipsoid.cartographicToCartesian(tile.extent.getCenter());

@@ -257,7 +267,7 @@ define([
         tile.maxHeight = buffers.statistics.maxHeight;
         tile.boundingSphere3D = BoundingSphere.fromVertices(buffers.vertices,, 5);

- var ellipsoid = this.tilingScheme.ellipsoid;
+ var ellipsoid = this.tilingScheme.getEllipsoid();

I am using CesiumTerrainProvider and it’s adequate for now.

Hi Kevin,

We just got our VR-TheWorld server to start producing PNGs in the format expected by Cesium (thereby eliminating the need for the proxy). I'm still working in the VR-TheWorld branch, but eventually hope to be able to move to a mainstream branch. So I would say no, please *don't* get rid of TileMapServiceTerrainProvider!



Hi Karen,

Great news that you’ve eliminated the need for the proxy!

I think you’re currently using a customized version of TileMapServiceTerrainProvider. No worries, though, we’ll set you up with a TerrainProvider that will work with VR-TheWorld. It might make sense to make it specific to your server, actually, and call it something like VRTheWorldTerrainProvider.

Did you need to make any changes to the terrain provider when you updated your server to support the PNG format? Or did you just stop using the proxy?


Hi Kevin,

We didn’t have to make any changes to the Cesium code. We did make changes to our terrain server to start serving PNGs in that format. There doesn’t seem to be a concrete convention for the PNG format, so we implemented the scheme that you guys expected (millimeters above -1000 meters). I think in the long term, the -1000 meters might not be sufficient, but it seems to work well enough for now. I do see a problem in the console with error messages streaming by indicating tiles not found because the there are many more levels of detail in the imagery than there is in the elevation data. However, I thought you fixed that a while back, didn’t you?


Hi Karen,

I believe -1000 meters should be sufficient for land terrain. It’s clearly insufficient if we start rendering underwater terrain, though.

I made some changes to reduce the number of errors in the console, but I wasn’t able to eliminate them completely. In order to eliminate those errors completely, we need to know, prior to making the request, which tiles exist and which do not. One way to do that is to pick a max level and then make sure the server has every single tile at that level. This tends to be very inefficient, though, because it requires the entire globe to have the same level of detail. High detail in the oceans is usually not necessary, and even on land it’s natural to have higher-res terrain in some areas than in other areas.

Another approach is to include in each tile a record of which child tiles are present. This is what the CesiumTerrainProvider currently does. The downside to this approach is that it requires us to request tiles in level order. We can’t request a tile at level N until we have already received its parent tile at level N-1.

The best approach is to have the tile table of contents available separately from the tiles themselves. It could be a description file that says “in this rectangular extent, all tiles up to level 12 are present”. It’s possible VRTheWorld already has something like this and we just need to use it. Another way to encode it is with a bitmask like CesiumTerrainProvider uses, only stored separately from the tiles themselves.

Do you guys have some sort of spec or description of your terrain server? We wrote the TerrainProvider you’re currently using mostly by trial-and-error, but with a better understanding of your server I could probably improve it and maybe even fix the tile errors.

If it’s ok with you guys, I’d actually like to include a VRTheWorldTerrainProvider with Cesium out-of-the-box, and even include it as an option/example in the Terrain Sandcastle example.


Hey Kevin,

Our solution for geoserver may be a little bit over-engineered, but we decided not to go with the .bil plugin and not have to include the worldwind.jar. If I remember correctly, that way was requesting huge .bil files from geoserver and the performance wasn’t that great. Instead, we set up a datastore with dted or a very large tiff file and wrote an asynchronous java servlet that forwards the extent request as a post request to the geoserver wcs to retrieve tiff imagery tiles. Then we treat it the same way as the arcgis imagery after that. The performance is not bad after you get the jai and java imageio patches to the jvm just right.

We could not get the geoserver wms to give us 16 bit tiffs, but geoserver has a wcs demo page that we noticed gave us what we wanted.


Hi Wayne,

I am also working on terrain rendering using geoserver.

I need your help in this regards. Could you please share me the webmapserviceterrainprovider file. I am failed to search it.

second i have downloaded the geoserver dds plugin in which i got dds-2.4-Snapshot.jar and worldwind-0.6.jar.

I am using opengeo suite under which geoserver comes with openlayers and other tools.

Currently i have copied them into “geoserver/web-inf/lib”, please help me where i have to copy these files to work with geoserver if the given path is wrong.

If i am looking into layer preview option then it is showing BIL and DDS in WMS format.

Thats what i have done till now. Please help me to show path to go ahead and render my elevation data on cesium globe.



Here’s the WMS Terrain Provider I was using at one point. Your mileage may vary (it’s not as performant as the supported terrain providers, and probably not as accurate), but it should give something to start with. Usage is the same as the other terrain providers. (9.44 KB)

Hey Wayne,

Thanks for sharing this! Any chance I can get you to sign the Contributor’s License Agreement (CLA) so that we can include this terrain provider in Cesium? There’s one for individuals and one for corporations. The CLA essentially says that you (or your company) own the copyright to your contribution and that we’re allowed to use it. You just need to email the completed form to



Thanks Wayne for attaching file.

i am using the release version Cesium-b17. I have just downloaded it and using in visual studio after extracting.

Now where i copy this file and add reference to my hello world page to get it work. Please help.

I have copied the webmapserviceterrainprovider.js on root and given the reference in helloworld.html page.

then i have add the code

var terrainProvider = WebMapServiceTerrainProvider({

url: ‘http://serverurl:portnumber/geoserver/opengeo/wms’,

layers: ‘layername’


centralBody.terrainProvider = terrainProvider;

It is providing error on first line

var terrainProvider = WebMapServiceTerrainProvider({

error is: WebMapServiceTerrainProvider is not defined.

please help.



Hi Manish,

You should follow the Contributor’s Guide to obtain Cesium from GitHub and build it yourself. Add the WMS terrain provider to the Source/Scene directory.

Alternatively, you can wait until this terrain provider is incorporated into a bXX release. I don’t know when that will be, though.


Thanks kevin for your help.

I will check the link follow to Contributor’s Guide.

Thanks Again.


I’ve brought up contributing to Cesium before to my company, and there were some legal issues that needed to be worked through.

This particular terrain provider is 95% the old WMS terrain provider code that I believe you originally wrote, I just modified it slightly to work with the refactored Cesium terrain provider framework (See the diff I had up on my Feb 7 comment). Given this, I don’t think I could claim any sort of copyright anyway. :slight_smile:

Wayne - if you need help getting the CLA OKed with your company, feel free to email me directly.