Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove deprecated ways of setting terrain exaggeration and a bugfix #9766

Merged
merged 6 commits into from
Aug 30, 2021

Conversation

IanLilleyT
Copy link
Contributor

@IanLilleyT IanLilleyT commented Aug 29, 2021

Terrain exaggeration was made dynamic in CesiumJS 1.82 with #9603

This PR deprecates some ways to set terrain exaggeration, including:

  • options.terrainExaggeration in Viewer.js
  • options.terrainExaggeration in CesiumWidget.js
  • options.terrainExaggeration in Scene.js
  • terrainExaggeration getter / setter in Scene.js

Globe.terrainExaggeration is the only way to set terrain exaggeration as of this PR

This PR also includes a bugfix caused by using forEachRenderedTile instead of forEachLoadedTile. When the exaggeration changes it updates the exaggeration of all rendered tiles, but after zooming out some fully loaded tiles become renderable again and don't have the updated exaggeration and geodetic surface normals. This is especially noticeable when setting the exaggeration to 1.0, then to 2.0, then zooming out:

Screenshot from 2021-08-29 13-57-36

One fix is to do forEachLoadedTile every frame until all tiles have the updated exaggeration - but as noted in #9603 (comment) this has a performance cost because a partially loaded tile may stay partially loaded forever if you don't move the camera. And so you're wasting cycles on this loop over all loaded tiles.

So this PR is a bit of a compromise. It goes back to forEachLoadedTile instead of forEachRenderedTile, but it only does it for one frame. The main downside is if the exaggeration changes while a tile is being created in a worker it will store an old exaggeration value. In practice this happens way less often than the original problem, but I found it once:

Screenshot from 2021-08-29 14-48-13

This is tricky to fix too, because the only place where you can check if exaggeration changes without doing a whole new loop is somewhere in the quadtree traversal, possibly by calling GlobeSurfaceTile.updateExaggeration inside GlobeSurfaceTileProvider.computeTileVisibility. But it's starting to make things messy, especially since updateExaggeration needs some objects that are not normally passed to computeTileVisibility, like the quadtree itself (in order to update clamp-to-terrain callbacks). So right now this PR replaces a more severe bug with a less severe one.

@cesium-concierge
Copy link

Thanks for the pull request @IanLilleyT!

  • ✔️ Signed CLA found.
  • ❔ Unit tests were not updated.
    • Make sure you've updated tests to reflect your changes, added tests for any new code, and ran the code coverage tool.

Reviewers, don't forget to make sure that:

  • Cesium Viewer works.
  • Works in 2D/CV.
  • Works (or fails gracefully) in IE11.

@IanLilleyT
Copy link
Contributor Author

IanLilleyT commented Aug 29, 2021

Ok ignore the last paragraph in the previous comment. I got it working by calling GlobeSurfaceTile.updateExaggeration in the terrain loading state machine, right after createResources. This makes sense because the exaggeration mismatch should only happen mid-load and can be caught after it finishes loading. This caught the straggler tiles and everything seems to be working correctly now.

The main downside is the QuadtreePrimitive needs to be passed pretty deep into the tile loading code, and only to update the clamp to terrain callbacks (like for the red dot in https://sandcastle.cesium.com/?src=Terrain%20Exaggeration.html). Not sure why _tileToUpdateHeights is part of QuadtreePrimitive instead of GlobeSurfaceTileProvider... 🤔

Comment on lines +455 to +504
GlobeSurfaceTile.prototype.updateExaggeration = function (
tile,
frameState,
quadtree
) {
var surfaceTile = this;
var mesh = surfaceTile.renderedMesh;
if (mesh === undefined) {
return;
}

// Check the tile's terrain encoding to see if it has been exaggerated yet
var exaggeration = frameState.terrainExaggeration;
var exaggerationRelativeHeight = frameState.terrainExaggerationRelativeHeight;
var hasExaggerationScale = exaggeration !== 1.0;

var encoding = mesh.encoding;
var encodingExaggerationScaleChanged = encoding.exaggeration !== exaggeration;
var encodingRelativeHeightChanged =
encoding.exaggerationRelativeHeight !== exaggerationRelativeHeight;

if (encodingExaggerationScaleChanged || encodingRelativeHeightChanged) {
// Turning exaggeration scale on/off requires adding or removing geodetic surface normals
// Relative height only translates, so it has no effect on normals
if (encodingExaggerationScaleChanged) {
if (hasExaggerationScale && !encoding.hasGeodeticSurfaceNormals) {
var ellipsoid = tile.tilingScheme.ellipsoid;
surfaceTile.addGeodeticSurfaceNormals(ellipsoid, frameState);
} else if (!hasExaggerationScale && encoding.hasGeodeticSurfaceNormals) {
surfaceTile.removeGeodeticSurfaceNormals(frameState);
}
}

encoding.exaggeration = exaggeration;
encoding.exaggerationRelativeHeight = exaggerationRelativeHeight;

// Notify the quadtree that this tile's height has changed
if (quadtree !== undefined) {
quadtree._tileToUpdateHeights.push(tile);
var customData = tile.customData;
var customDataLength = customData.length;
for (var i = 0; i < customDataLength; i++) {
// Restart the level so that a height update is triggered
var data = customData[i];
data.level = -1;
}
}
}
};

Copy link
Contributor Author

@IanLilleyT IanLilleyT Aug 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is mostly the same as before. It was moved because it's now called from GlobeSurfaceTile.processStateMachine

@IanLilleyT IanLilleyT requested review from ptrgags and removed request for ptrgags August 29, 2021 20:38
CHANGES.md Outdated
@@ -2,6 +2,10 @@

### 1.85 - 2021-09-01

##### Breaking Changes :mega:

- Removed `Scene.terrainExaggeration` and `options.terrainExaggeration` for `CesiumWidget`, `Viewer`, and `Scene`, which were deprecated in CesiumJS 1.82. Use `Globe.terrainExaggeration` instead.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this was deprecated in 1.83?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch!

@lilleyse
Copy link
Contributor

Thanks @IanLilleyT

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants