3D Tiles. Model moves when camera tilts

727 views
Skip to first unread message

Alvaro Martin

unread,
Jan 31, 2017, 8:39:21 AM1/31/17
to cesiu...@googlegroups.com
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. 


Inline image 1

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

Alvaro
mar.b3dm
tileset_mar.json

Sean Lilley

unread,
Jan 31, 2017, 8:56:43 PM1/31/17
to cesium-dev, avo.m...@gmail.com
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.

Alvaro Martin

unread,
Feb 1, 2017, 10:41:11 AM2/1/17
to cesiu...@googlegroups.com
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?

------
------

2. The model has a min Z coordinate of -3 (¿meters?) but if I turn on the 
`viewer.scene.globe.depthTestAgainstTerrain = true` option I need to change the RTC Center to `Cesium.Cartesian3.fromDegrees(-4.8729014790370195, 36.509302568426179, 100.0)` to make it be visible. ¿If a model is partially under the ellipsoid will it still be shown when `depthTestAgainstTerran = true?. I've already checked I'm using the default EllipsoidTerrainProvider. 

------
------

3. Also, my model, which represents a building encoded as a Z-UP mesh appears tilted in cesium when encoded as b3dm on 3dtiles but is not tilted if I add manually the corresponding gltf to a specific LLA coordinate with: 

```javascript
    // Exton, PA
    var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(
        Cesium.Cartesian3.fromDegrees(-75.62898254394531, 40.02804946899414, 0.0));
    var url = 'mar.gltf';

    var model = scene.primitives.add(Cesium.Model.fromGltf({
        url: url,
        modelMatrix: modelMatrix,
        scale: 1.0
    }));
```

This is the b3dm in a tileset with RTC = Cesium.Cartesian3.fromDegrees(-4.8729014790370195, 36.509302568426179, 100.0): 

Inline image 1

The same model, turned into a gltf and loaded to a static location. As you can see it is not rotated.

Inline image 3


I cannot find any transformation matrix in the b3dm or tileset that explains the rotation of the model. ¿Why is it rotated? ¿Am I missing anything?

Thanks in advance!

Álvaro

Please see attached files:

* mar.b3dm → b3dm model file
* tileset_mar.gltf → tileset
* mar.gltf → equivalent gltf file. In fact it is the same b3dm file minus the b3dm header and where the RTC extension data has been substituted with spaces using a hex editor.

 
Álvaro Martín
Inuvik Studio: Framebags a medida para cicloturismo ultraligero
Rodadas.net Una comunidad de viajeros en bicicleta
t. +34 696 07 04 70
e. alv...@rodadas.net
mar.b3dm
mar.gltf
tileset_mar.json

Sean Lilley

unread,
Feb 1, 2017, 7:42:53 PM2/1/17
to cesium-dev, alv...@rodadas.net
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.

Alvaro Martin

unread,
Feb 6, 2017, 3:44:12 AM2/6/17
to cesium-dev
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. 

Inline image 1

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

Álvaro

 
Álvaro Martín
Inuvik Studio: Framebags a medida para cicloturismo ultraligero
Rodadas.net Una comunidad de viajeros en bicicleta
tileset_mar.json
mar.b3dm

Alvaro Martin

unread,
Feb 8, 2017, 7:07:20 AM2/8/17
to cesium-dev
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
    viewer.entities.add({
        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.

Inline image 1

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({
        modelMatrix: modelMatrix,
        debugShowBoundingVolume: true,
        debugShowContentBoundingVolume: true
    }));

Is there any reason for this behavior?

Thanks in advance

Álvaro


On Mon, Feb 6, 2017 at 9:43 AM, Alvaro Martin <alv...@rodadas.net> wrote:
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. 

Inline image 1

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

Álvaro
tileset.json

Sean Lilley

unread,
Feb 8, 2017, 9:07:31 PM2/8/17
to cesium-dev, alv...@rodadas.net
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...
Reply all
Reply to author
Forward
0 new messages