-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Description
When heightmap terrain is upsampled past its available data, it appears to "sink" into the ground and decrease in height with each upsampling.
Here is a gif of the issue:

(I am unable to provide a sandcastle link as I am not able to share the terrain data, apologies).
I have a heightmap terrain dataset on a server and we use CesiumTerrainProvider with a url to our heightmap server. The dataset only goes up to zoom level 10, but I have basemap imagery that goes much higher (i.e satellite imagery that goes to zoom level 20).
If I restrict the terrain tiles to only go up to level 10 (shown in the above gif via the Cesium inspector), then a milk truck placed exactly at the terrain height appears to be perfectly on top of the terrain (note the back wheel is just barely clipping into the terrain, which proves it is perfectly on top of the terrain).
If I then enable LOD update (which allows Cesium to upsample our heightmap terrain past its limits to higher zoom levels), I see the terrain sink downwards below where the actual data is, and it worsens with each additional upsampling. This makes the truck look like it's floating.
I'm aware that other artifacts, like the cracks/rifts and undulations are a result of upsampling heightmap data, but the sinking of the terrain is very difficult to deal with, as it makes all ground vehicle heights look incorrect (even if they are placed correctly according to the underlying data).
The issue does not occur when I try it with a different dataset that uses quantized mesh instead of heightmap, but I am currently unable to switch to quantized mesh for our main dataset, and would like to see if there is a workaround for this issue using heightmap data.
Things I have tried:
- Manually shifting the terrain upwards by just adding a fixed offset value. I do this by increasing the terrain provider's heightmapStructure offset, or by overriding the terrainprovider.upsample function and adding a flat value to the terrain data being shown. This workaround doesn't work for us as the terrain 'sink' amount doesn't seem to be the same everywhere, so one flat offset wouldn't handle all cases.
- Restricting upsampling such that it does not go past our terrain zoom level. This workaround gives us the desired outcome with respect to the terrain data, but has the side effect of restricting our basemap's zoom level too, making high resolution basemap imagery clamped to only level 10, which is not desireable for us.
- Writing a custom terrain provider class that has its own requestTileGeometry function that tries to change the way the data is given after zoom level 10. This required that I configure the provider to believe it has more than level 10 data (otherwise requestTileGeometry doesn't get called past our max level of 10), but after this, I realized I would have to manually upsample our own data which looks like what the built-in upsample function already does.
Is there any workaround or solution for this issue that doesn't involve switching our large dataset from heightmap to quantized mesh? (i.e Is there a way to restrict Cesium from upsampling our terrain data while still allowing it to display higher resolution basemap imagery on top of it? Or a way to prevent it from sinking when upsampling?)
Reproduction steps
- I have a heightmap data set on a server. The data only goes to zoom level 10
- I add this data using CesiumTerrainProvider with a URL.
- I use a basemap imagery data set that goes up to zoom level 20
- When I zoom in, cesium upsamples my terrain data (presumably to match the imagery) and the terrain sinks lower and lower into the ground, below where the actual data is.
Sandcastle example
I am unable to provide a sandcastle link as I cannot share our heightmap terrain data.
Environment
Browser: Chrome
CesiumJS Version:
Operating System: Windows