3D Tiles Exaggeration

Hi all, I’m looking for a solution for vertical exaggeration for 3D tiles point clouds. I can’t recall if the following snippet was suggested somewhere, but if the tileset transform is used, the results get more incorrect the further you move from the tileset origin.

tileset.root.transform = Cesium.Matrix4.setScale(
    tileset.root.transform,
    new Cesium.Cartesian3(1, 1, exaggerationFactor),
    tileset.root.transform
);

I’ve got a sandcastle example here if you’d like to take a look.

The synthetic example is as follows:

  • Blue points are the entire grid, from 0m to 28m elevation
  • Yellow points are half the grid to the west
  • Red points are the remaining half to the east

The observed behaviour is that points at the limits of the dataset drift. i.e. the red and yellow points should be coincidental with the blue points (which they are when no transforms are applied). But I think what’s happening is, the transformation of the points at the limits aren’t affected based on the curvature of the earth at their location, but rather the surface normal at the location of the tileset origin.

Is there a more correct way (that gives the correct results) for exaggeration?

Hey Stuart,

There was a recent Sandcastle example here that demonstrated how to scale a 3D Tileset vertically while accounting for when the origin is far from what’s being scaled: How to change the scale for box defined tilesets?.

But I’m not sure if that solution readily applies in your use case. Perhaps this could be something built-in to CesiumJS to make this transformation easier. Can you tell me more about your use case? Are you mainly interested in vertically scaling point clouds? Or is this tileset just created for debug purposes? How are your 3D Tiles generated? Is the goal to be able to see changes in elevation more easily?

Thanks Omar. Yeah that example has the same issues I’m describing here. If you switch to ellipsoid terrain, scale to 0.1, then the center of the tileset scales as expected (near Brooklyn Navy Yard: 40.706673,-73.977723), but the extremities are floating in the sky (e.g. Orchard Beach: 40.8662867,-73.7943881). If the Orchard Beach Promenade were in it’s own tileset, I’d imagine it would scale correctly.

Another more subtle effect is that scaling causes translation across the earths surface at the extremities. If you swap over to orthographic view and look at Orchard Beach, and switch between scale 1 and 10, you’ll see the promenade shifting its location, which doesn’t happen at the Brooklyn Navy Yard.

What I assume is happening is a uniform scale like classic 3D transformations. Hopefully the following animation explains what I think is happening. The scale is applied along the surface normal at the tileset origin, thus causing the extremities to scale along an axis that doesn’t follow their surface normal. Plus since the extremities are scaled along an axis that don’t follow the surface normal, they shift horizontally too (hopefully shown by the line from the earth’s centre).

Compare that to this second animation which scales every point along it’s own surface normal (using a deformation cage).

Obviously these examples are exaggerated as we’d be talking about a tileset that covers a quarter of the earth, but when trying to line up multiple tilesets over hundreds of metres or kilometres, they don’t line up when a scaling factor is applied.

To answer your other questions, yes it’s just point clouds exaggerated to highlight subtle differences in elevation.

I love the gifs @Stuart_Attenborrow. The sandcastle Omar posted is the quick and dirty way to exaggerate a tileset relative to the tileset’s center point, but as you’ve shown it breaks down the larger the tileset is.

To do this properly the scale would need to be applied in the vertex shader, and unfortunately there’s no way to do this out of the box at the moment.

1 Like

I opened a GitHub issue here to log this feature request: https://github.com/CesiumGS/cesium/issues/8809.