3D mesh created from Context capture is floating above and below the cesium world terrain


I have 6 production.Json files of 3D mesh created in context capture and I am trying to add them individually in cesium JS (1.88) in Cesium World Terrain provided by cesium, however the 3d data is floating either above or below the terrain. It is interesting to know that the projection (WGS84) and the other settings for all the 3D meshes are same, however they are giving different height value for all data, some are seen below the ground and some are above it.

It would be helpful if you can provide me some explanation to this scenario as well as a workaround. Please feel free to reach in case of any further clarifications.

Hi @Asiya_Z,

Each tileset that you are fusing with Cesium World Terrain has a geolocation associated with it. This location may be above or below the terrain. Are you looking to add your 3D data on top of Cesium World Terrain? If so, I recommend editing the geolocation of your datasets to match the terrain elevation of Cesium World Terrain more closely. Alternatively, if you would like your 3D datasets to replace sections of Cesium World Terrain, you can use the ClippingPlanes part of our API. This sandcastle demo showcases how you can achieve that functionality.


My goal is to add the 3D mesh on top of cesium terrain, touching the ground level. Can you please elaborate on changing geolocation and changing it to what?

When you create those models, are they georeferenced to some degree of precision, or just created from for example some photogrammetry process? If the coordinates of the photos are relying on normal GPS accuracy only, I suspect context capture tries to make a best guess to where the model is referenced. However, accuracy of photo GPS is +/- 3m, so that’s your initial error margin, I suspect.

Using PPK (post-processing of coordinate data) you can process the photo GPS accuracy to a higher degree, depending on the accuracy of the timestamp to the saving of the image (a normal camera’s time precission is a bit dodgy). Some boxes added to your camera (for drones, planes, cars, etc.) have their own high-grade timer (micro-second precission) and GPS accuracy devices (like IMU’s, etc.) that you can use to post-process those images to a much higher accuracy (triangulation and adjustment based on accurate time you took the picture, and the GPS satellite data, coupled with CORS station data closest to that location), going from +/- 3m down to roughly 1-3cm lat/long, and 2-5cm height. Once you use those accurate coordinates instead of the internal photo ones when you create your mesh model, it will also be better georeferenced and placed in a more correct place.

Next is to look at the terrain models. I don’t know the accuracy of the Cesium World Terrain model, to be honest, so take this with a grain of salt. Some terrain models are more accurate than others, some also are quantizised, meaning they’re based off a grid that is calculated, to some degree of complexity and precission. If a terrain model is accurate to 30m grid, it can still be accurate in heights (say +/- 1m, normative), but it means that anything between the grid points are calculated, which is a problem if your terrain is especially bumpy (high in contrast) where your model is situated. Some quantisation methods are good at high resolution in complex areas and low resolution in flats, and anything inbetween, it’s a minefield in itself. World terrain models are usually good for generic stuff, but if you want high precission you often have to provide your own (and if your model is georeferenced properly, the same process can create both DTMs, models, point-clouds, etc.)

Anyway, take a screenshot of what you’re seeing, and we can try to help you a bit further? But I’d definitly start by looking at getting the georeferencing right (especially if this is a dynamic application that updates the data from time to time), or (much cheaper) look into height adjustments for 3D tilesets, and adjust them statically until you’re happy (and apply that adjustment every time you load your scene). More on that here;




Hello @sam.rothstein Thank you for your response.

ClippingPlanes seems to be a nice option, however all the 3D datasets are located on different locations and clipping multiple areas of the terrain seems to be a lot of manual work.

Can you share more optimized solution that can be used for for large number of dataset.


I understand your concern. Unfortunately, I am unaware of a simple solution that will allow you to algorithmically generate clipping planes.


Hi @sam.rothstein I would like to connect to Cesium Tech Support in order to discuss my script with more details. Could you let me know how exactly we can do that?

@Alexander_Johannesen I kept the projection of the data/output same as cesium terrain ECEF and still giving me the same issue. Would it be possible for us to connect with cesium tech support and explain the whole scenario?

What do you mean you kept them “same as” the Cesium terrain? Again, if the precission of the models is off (and individual), that doesn’t matter. Georeferencing between WGS84 and any other (local, projected or imprecise) coordinates are really, really hard. I guess more info on how you georeference each model is the key to this puzzle.

As to talking with Cesium, sure give them a spin, especially if you’re an Ion customer.



As per my understanding the default projection of Cesium World Terrain is ECEF. I have created the model from 2D lidar photos and the projection of all the photos and 3D mesh has been checked with WG84 and ECEF projection one by one and the tower position remains above the cesium Terrain.

Well, you said you had 6 models, right? I still suspect the problem is accuracy of photo positions. And I think your solution is (apart from fixing the accuracy) the Height adjustment. You can probably even sample the middle coordinate of the model and adjust its height to the sampled point (or matrix, if you’re brave).




Thank you for all the help!
I have a query, would it be possible for us to set a range of height, let say -100 to 100 in this model matrix script:
tileset.readyPromise.then(function(tileset) {
var height = 50.00; // Set this to anything
var cartographic = Cesium.Cartographic.fromCartesian(tileset.boundingSphere.center);
var surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0);
var offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, height);
var translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3());
tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation);

Like how the range has been given in this Height adjustment widget Cesium Sandcastle