How to show gltf model with geocentric coordinates?

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

I have an datasource with 3D building data from an postgis databse. The data is stored in ETRS89 UTM32N (mainly west germany) reference system. This building data has to be shown on the globe.
I have written a exporter that transform those data (with use of postgis function ST_Transform) to WGS84 (height is stored as height about ground). So each vertex has an lat, lon and alt for x,y, and z.
Because i read somewhere that cesium works with earthcentred coordinates, i than transformed those coordinates to cartesian coordinates. (ECEF). I allready checked the results for some sample points with this online tool: Furthermore the model looks good with all gltf viewers i found (this and some others) and the gltfValidator ( says everything is fine.
So i think the model is almost fine.

I tried to load the model into cesium, but it does not appear. I thought that i have to load the model into earth center so that the model internal values can effect, but that does not changed the non display.
After some searching in this forum i found that models, that are placed under ground are not rendered. I asume that my model does not show up, because its placed in earths core.

Next i tried to convert the model, so that its vertices are all related to the ground center point of the buidling. I think now i have a model that has it's local coordinate system and the building is placed on top the (0,0,0) coordinate. Again validator and viewer say everthing is fine.
When i try to load this model its shown, but not at the expected location. I thought it must now be shown like some of the sample models, but they don't. Model appears kilometers above ground. But scince the values in the vertices are smal (building size max 100m) i can't think of, why.

Additional Question how to use this forum:
I saw questions with appended files, but i can't see any add file button here. What to do to add an file here?

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

// position to place building on ground at lat:0 lon:0
let modelPosCartesian3 = Cesium.Cartesian3.fromDegrees(0, 0, 0);

// Create modelmatrix to move model to place
let modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(modelPosCartesian3);
let modelFromGltf = Cesium.Model.fromGltf({
    url: modelFilePath,
    modelMatrix: modelMatrix,
    scale: 10000,
    debugShowBoundingVolume: true,
    debugWireframe: true
let modelFromGltfReference = SAFE_globe.viewer.scene.primitives.add(modelFromGltf);

3. Context. Why do you need to do this? We might know a better way to accomplish your goal.

4. The Cesium version you're using, your operating system and browser.

Tried with Cesion 1.50 and 1.52

Well, 3D math is not really my forte, but I can give some thoughts until someone else has a chance to look at this. For your first approach, you said your model's coordinates were already converted to ECEF, right? But in your code sample, you appear to be creating a transformation matrix from ENU to ECEF again. For your second approach, you said that the building positions are too high off the ground given the small vertex coordinate values. But your scale value is set to 10000 in the code sample. What happens if you just set it to 1?

Thank you for your reply. I set the scale to 10000 to find my model. If i set the scale to 1 (or a value below 1000) i can't find it.

Youre right with the convertion, i used a differend code for my first approach.

let modelPosIdentityMatrix = Cesium.Matrix4.IDENTITY;
let modelFromGltfIM = Cesium.Model.fromGltf({
                        url: modelFilePath,
                        modelMatrix: modelPosIdentityMatrix,
                        scale: modelScale,
                        debugShowBoundingVolume: true,
                        debugWireframe: true
                    let modelFromGltfIMReference = SAFE_globe.viewer.scene.primitives.add(modelFromGltfIM);

I’m glad that worked for you!

For attaching files, you should be able to see a “attach file” button on top of the post editing window (on top of the toolbar for bold, italic etc)

I think since your model already has the right coordinates relative to the earth center, then that’s why the modelMatrix should be identity, since there’s no transformation needed. I also think:



is technically undefined for positions under the surface of the earth, since it assumes the given position is on the surface.

Hi Omar,

wired google forum. I can't see a toolbar on top of the editing window. Mybe there are some restrictions for my country.



is not undefined for positions below surface. For example following code is just running fine:

let boxPos = Cesium.Cartesian3.fromDegrees(0, 0, -200);
                var box = SAFE_globe.viewer.entities.add({
                    name: 'Yellow box outline',
                    position: boxPos,
                    box: {
                        dimensions: new Cesium.Cartesian3(300000.0, 300000.0, 300000.0),
                        fill: true,
                        outline: true,
                        outlineColor: Cesium.Color.YELLOW

Only if the model is complete under surface it's not rendered. (Makes sense for most applications :smiley: )

In between i checked my calculated coordinates and found that cesium does not use the ECEF calculation i asumed. So i reviewed the cesium code and reimplemented the code behind the Cesium.Cartesian3.fromDegrees() method to my exporter. I tested with some coordinates and now i'am sure that my vertex coordinates are calculated the same, as if i pass them to Cesium.Cartesian3.fromDegrees(). But the model is still not shown.

I still use:

let modelPosIdentityMatrix = Cesium.Matrix4.IDENTITY;
let modelFromGltfIM = Cesium.Model.fromGltf({
                        url: modelFilePath,
                        modelMatrix: modelPosIdentityMatrix, // Not realy needed because IDENTITY matrix is default
                        scale: modelScale,
                        debugShowBoundingVolume: true,
                        debugWireframe: true
                    let modelFromGltfIMReference = SAFE_globe.viewer.scene.primitives.add(modelFromGltfIM);

My used glb is here: and other player shows the file an cesium based player does not display it.

Sorry for the late response. It looks like there’s a couple of issues with how Cesium loads glTF’s that are geo-referenced. There was a change in the default up/forward axes, so it does an automatic conversion when you load it. To disable that, you can load the model with:


url : ‘model.gltf’,

upAxis : Cesium.Axis.Z,

forwardAxis : Cesium.Axis.X



The other way to fix it is by adding a root node with a transform to reverse that, as described here:

Let me know if that helps.