3D Tiles. Model moves when camera tilts

Hi all

I’m having some issues with my 3dtiles setup. My b3dm with CESIUM_RTC moves when the camera tilts to the extent that gets hidden below the sea level.

Please see attached tileset & b3dm files.

What am I doing wrong?

Im on the 3d-tile branch and have just pulled the last version of cesium from github.

Thanks in advance


mar.b3dm (95.3 KB)

tileset_mar.json (531 Bytes)

The model is located beneath the globe, which often creates illusions like this.

If you set:

viewer.scene.globe.depthTestAgainstTerrain = true;

the model won’t be visible at all.

So I would recommend either positioning/centering the model better or using a different CESIUM_RTC center value.

Hi Sean

Thank you for your response. There are a couple things I still don’t understand:

  1. So far I’ve been calculating the RTC center coordinates with this code:

Cesium.Cartesian3.fromDegrees(-4.8729014790370195, 36.509302568426179, 0.0)

¿Is that correct?

Screenshot - 01_02_2017 , 16_24_36.png

Screenshot - 01_02_2017 , 15_58_21.png

mar.b3dm (95.2 KB)

mar.gltf (95.2 KB)

tileset_mar.json (531 Bytes)

  1. That looks correct to me.

  2. When depthTestAgainstTerrain is true and the model is partially under terrain, only the part that is under the terrain will be hidden.

  3. The model appears rotated because the RTC extension only handles the translation component of the model, whereas eastNorthUpToFixedFrame generates a matrix that applies the correct translation and rotation depending on the longitude/latitude given. If you were to set the model matrix to Cesium.Matrix4.fromTranslation(Cesium.Cartesian3.fromDegrees(-4.8729014790370195, 36.509302568426179, 100.0)) you would see the same result as the RTC.

Maybe instead of RTC you should use a tile transform (https://github.com/AnalyticalGraphicsInc/3d-tiles#tile-transform). The eastNorthUpToFixedFrame matrix you posted would work fine for that.

Another potential issue is that your model is z-up while our model loader expects models (even those embedded in b3dm) to be y-up. (Yes this is a little confusing since 3D Tiles is defined as z-up, but the glTF spec states that models should be y-up, and that’s how most models we find are). To correct this you could add a root node to your gltf model that applies a z-up to y-up transform - a matrix of [1,0,0,0,0,0,-1,0,0,1,0,0,0,0,0,1] should do it. Or you could edit the model to be y-up from the start. This also means that despite the minimum z being -3, the minimum y may be much lower. If you want the height value of Cartesian3.fromDegrees to be 0.0 you’ll probably want the model’s minimum y to be 0 as well so that it appears right above the surface.

Hi all

The transform matrix worked really well. My model now has the right orientation and is nearby to its ideal position.

I’d risk troubling you with one more question: Since I’ve applied the transformation to the model, what units should be my model in?

At this moment the model coordinates are encoded in WGS86 UTM 30 (meters) relative to the transformation origin but I’m showing a displacement of some meters both in x & y.

I’ve already checked the precision of the center coordinates both in the model and in the transformation matrix and everything looks fine.

Screenshot - 02_02_2017 , 18_02_40.png

My tile BoundingVolume is quite big (a whole town), since it is the toplevel tile in the hierarchy. Thus, the model in question should be offset some 1000 m west of the RTC center. As you can see in the image it doesn’t align properly to the base imagery (default Bing maps).

Centering the model on the origin is not pratical in this situation, since the tile should be quite big and should hold more than one model.

Thanks in advance


tileset_mar.json (989 Bytes)

mar.b3dm (95.2 KB)

Hi all

I’ve checked the model coordinates by manually plotting billboards on some of the model coordinates directly into the globe and they aligned perfectly. Example code

cartesian = new Cesium.Cartesian3.fromDegrees(-4.8979284420470881, 36.490237894893575, 0.1); // model vertex coordinate transformed into WGS84


id: “building-coordinate-max”,

position: cartesian,

box: {

dimensions: new Cesium.Cartesian3(1,1,0),

outline: true,

outlineColor: Cesium.Color.WHITE,

outlineWidth: 2,

material: Cesium.Color.fromAlpha(Cesium.Color.YELLOW, 0.2)


label: {

text: ‘MAX’,

font: ‘14pt monospace’,

style: Cesium.LabelStyle.FILL_AND_OUTLINE,

outlineWidth: 2,

verticalOrigin: Cesium.VerticalOrigin.BOTTOM,

pixelOffset: new Cesium.Cartesian2(0,-9)


But when the same model was loaded by a tileset with the appropriate eastNorthUpToFixedFrame transform, it never algined. I’ve also discovered that the model would be closer to it’s ideal position the closer it was to the RTC center. It also looked like it was a rotation rather than translation issue.

Then I’ve tried to manually rotate the tileset by multiplying a rotation transform to the eastNorthUpToFixedFrame transform and applying it directly to the tileset on runtime. Thus I’ve managed to improve dramatically the alignment of the models in my extent (south Spain) by adding a rotation of 1.117 degrees to the tileset modelMatrix. Even models as far as 1000+ m from the RTC appear to be correctly aligned.

This is the code I’ve used to configure the tileset with the appropriate rotation:

var rotation = Cesium.Matrix3.fromRotationZ(1.117* RADIANS_PER_DEGREE);

var rotMat = Cesium.Matrix4.fromRotationTranslation(rotation);

var rtcCenter = new Cesium.Cartesian3.fromDegrees(-4.8728231291920547, 36.5093837495992);

var posMat = Cesium.Transforms.eastNorthUpToFixedFrame(rtcCenter);

var modelMatrix = new Cesium.Matrix4();

Cesium.Matrix4.multiply(posMat, rotMat, modelMatrix);

//modelMatrix = posMat;

var tileset = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({

url: ‘http://cesium.local/tileset.json’,

modelMatrix: modelMatrix,

debugShowBoundingVolume: true,

debugShowContentBoundingVolume: true


Is there any reason for this behavior?

Thanks in advance


Screenshot - 02_02_2017 , 18_02_40.png

tileset.json (422 Bytes)

I’m not totally sure. I’m starting to think that a tile transform may not be right for this tileset since the default east-north-up orientation is really best for tilesets that aren’t already georeferenced like yours.

Using RTC with a y-up transform should be the best solution. What’s throwing things off is the geometry is relative to center from a position perspective, but not rotation.

This is where the transform helps to rotate everything using the best estimate at the given longitude/latitude. However I think the model positions were created with a slightly different orientation than the default east-north-up, which accounts for the small discrepancy.

Really I think the orientation needs to be baked in to the geometry so that the model is truly georeferenced and can be loaded without a tile transform. Otherwise I can’t think of a good solution for this…