Seeing rifts and undulations in the ground when using terrain

  1. A concise explanation of the problem you’re experiencing.

We’re seeing gaps / rifts on the map when using our Heightmap terrain data at various places:

nycrift.png

This particular gap seems to be on the edge of a basemap tile.

Additionally, we see some undulations on the map as well using the same terrain data:

nycundulations.png

This is strange to us, because our Heightmap terrain data has a resolution of 7.5 arcseconds, which seems far too coarse to produce such detailed changes in elevation as seen above. Additionally, our terrain only goes to a max zoom level of 10.

Both of the above issues seem to occur all over the map, not necessarily on terrain tile boundaries (the above two images occur right in the middle of a terrain tile).

Does anyone know what could be causing these issues? is it related to the fact that we’re using Heightmap terrain data?

  1. A minimal code example. If you’ve found a bug, this helps us reproduce and repair it.

I can’t supply a Sandcastle example, but from similar posts I’ve seen this is sometimes a loading-related issue (i.e a gap will appear, but will be covered up once the tiles fully load). In our case, it doesn’t seem to be a loading-related issue, as the rifts / undulations seem to persist even after tiles have loaded.

  1. The Cesium version you’re using, your operating system and browser.

We see this behavior in the latest Cesium versions (I’ve tried 1.54 up to 1.56.1).

The Cesium inspector (https://cesiumjs.org/Cesium/Build/Apps/Sandcastle/?src=Cesium%20Inspector.html) might be helpful in debugging this. You can turn it on in your application with the line below.

viewer.extend(Cesium.viewerCesiumInspectorMixin);

``

You can then click on “Terrain” and select “Show tile coordinates”. As you mentioned I would expect to see these rifts between the tile boundaries, but this will help us confirm. If you can share a screenshot of the tile coordinates on these rifts that would be helpful.

Hi Omar,
Thanks for the response.

Here’s the tile coordinates with the rift, it indeed looks like it’s on a tile border:

One strange thing: as I mentioned before, our terrain only goes up to zoom level 10, so it’s strange to see the inspector show tiles with much higher zoom levels. Does cesium do any innate upsampling of terrain to create higher zoom levels? From the above it looks like the rift is on the border of tiles, but these tiles are ones that we don’t actually have.

Also, although I can’t give you our terrain data, we found similar small rifts/undulations with other cesium-based applications.

The above rifts can be found by zooming in on the map using the following cesium-based app: https://kartta.hel.fi/3d/#/ (I’m not associated with this app, but I noticed that it has similar rifts/undulations to what we’re experiencing). The rifts get a little better once everything has loaded in, but it looks like some rifts still persist.

Let me know if you have any advice or info.

Thanks,

Abhi

Now that you mention it, Cesium does indeed upsample tiles, you can see that here:

https://github.com/AnalyticalGraphicsInc/cesium/blob/master/Source/Scene/GlobeSurfaceTile.js#L379

And I do believe the logic for that has changed with the terrain overhaul. This comment is a good summary of what the changes were:

https://github.com/AnalyticalGraphicsInc/cesium/pull/7061#issuecomment-460217748

One thing you can try to do is set the fillHighlightColor to something obvious like red:

https://cesiumjs.org/Cesium/Build/Documentation/Globe.html?classFilter=Globe#fillHighlightColor

And that’ll help visualize if these rifts are coming from these “fill tiles”. The other thing you can try is adding a console.log or attaching a debugger to see if the upsample is being called with these levels, and is where those tiles are coming from.

I know you can’t share your terrain, but if there’s any way you can create some kind of fake test data that is in the same format, that has the same issue, that would be great, and then we can look into it and debug it on our end too. And just to confirm, did you say you’re using one of these terrain providers to load it in Cesium:

https://cesiumjs.org/Cesium/Build/Documentation/TerrainProvider.html?classFilter=TerrainP

Or is it a custom terrain provider?

Thanks again for taking a look.
To answer some of your questions:

  • We’re using a Cesium.TerrainProvider with our own terrain URL.

  • It doesn’t seem like the rifts are coming from “fill” tiles; I didn’t notice these tiles being red after setting the fill highlight color to red.

That github comment you linked was very helpful. One thing I noticed was it mentioned that upsampling can be expensive, and can potentially cause cracks in the terrain.

Is there any way for us to disable upsampling of terrain data? Are there any issues/pitfalls with doing so? I’d like to just test to see if disabling upsampling resolves / reduces the cracks and undulations.

Sincerely,

Abhi

For reference, I think this is the comment that mentions upsampling a very low resolution tile to a high resolution level can cause cracks: https://github.com/AnalyticalGraphicsInc/cesium/pull/7061#issuecomment-460217748

I think the easiest way to make it not upsample is to make the upsample function in GlobeSurfaceTile.js always fail (so make that if check in the beginning always pass). As far as I understand, upsampling is a way to get higher resolution tiles without having to request every level of detail, so if it fixes your problem, I wonder if exposing an option on the terrain provider could be a nice feature to have.

Don’t disable upsampling. The only time it’s used anymore is when you’ve exceeded the terrain’s available resolution. If you disable it, your imagery resolution will be limited to the terrain resolution. Fill tiles are now used to avoid the need to upsample exception in the situation above.

Thanks for the response, you mentioned that fill tiles would resolve the issue above. Does that mean the rifts in our terrain are not caused by upsampling? Do fill tiles avoid the cracks in the terrain? The examples I posted were reproducible in version 1.56.1.

Also, while our terrain only goes to zoom level 10, our imagery goes up to zoom level 18; You mentioned that disabling upsampling would limit our imagery resolution to our terrain resolution, but is there a way to tell Cesium to disable upsampling past our imagery’s max zoom level?

I also would like to be able to set an upsampling limit. Perhaps as a Globe option. This is particularly useful when working with custom Globe material/shaders and tiles UVs.

For now, I work around this limitation by wrapping the QuantizedMeshTerrainData upsample method as such:

// Limit tile mesh upsampling to a specified maximum level
// Maximum level should match imagery maximum zoom level in order to allow for maximum resolution to be loaded.
Cesium.QuantizedMeshTerrainData.prototype.nativeUpsample = Cesium.QuantizedMeshTerrainData.prototype.upsample;
Cesium.QuantizedMeshTerrainData.prototype.upsample = function(e,t,i,zoomLevel,n,a,o){
if (zoomLevel > 18) return;
return this.nativeUpsample(e,t,i,zoomLevel,n,a,o);
};