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

fix scene.updateHeight #12134

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open

Conversation

bkuster
Copy link
Contributor

@bkuster bkuster commented Aug 19, 2024

Description

There where some performance issues in Scene.updateHeight which made working with large (mesh surfaces in general) 3D Tiles difficult to very clunky.

Proposed fixes

  • In Cesium3DTileset.js, update height callbacks where wrapped in an object, with an invoked property. This property was always false. In the PR, we set it to true once an update has been added to the frame state and set it back to false on flush.
  • In Scene.updateHeight a callback can be called more then once for the same frame number. We now ensure it is only called once.
  • In Scene.updateHeight a callback which was removed would still be called with a new height. When loading a mesh surface, multiple callbacks are added, one for each initialized frame. For each new one added, the old one is removed, but still called once. We now only call callbacks which where not removed.

Testing plan

Add a mesh surface with enableCollision and watch your performance drop.

Author checklist

  • I have submitted a Contributor License Agreement
  • I have added my name to CONTRIBUTORS.md
  • I have updated CHANGES.md with a short summary of my change
  • I have added or updated unit tests to ensure consistent code coverage
  • I have updated the inline documentation, and included code examples where relevant
  • I have performed a self-review of my code

Copy link

Thank you for the pull request, @bkuster!

✅ We can confirm we have a CLA on file for you.

@bkuster
Copy link
Contributor Author

bkuster commented Aug 19, 2024

this is a possible fix for: #11923

furthermore, related issues could be #11811 & #11787

@ggetz
Copy link
Contributor

ggetz commented Aug 19, 2024

Hi @bkuster, thanks very much for the proposed fix!

which made working with large (mesh surfaces in general) 3D Tiles

Did you have a particular tileset in mind for testing? Google's tileset is certainly the most common use case here, but in my experience is not the worst case in terms of performance.

@jbo023
Copy link
Contributor

jbo023 commented Aug 19, 2024

Hi @ggetz here is a dataset you can use: but the dataset is hosted in Frankfurt, so hopefully fast enough in the US

const viewer = new Cesium.Viewer("cesiumContainer", {});

viewer.scene.globe.depthTestAgainstTerrain = true;

  const tileset = await Cesium.Cesium3DTileset.fromUrl("https://www.virtualcitymap.de/cesium_bugfix/baselayer/mesh_2020/tileset.json", {
    enableCollision: true,
    cacheBytes: 2048 * 1024 * 1024
  });
  viewer.scene.primitives.add(tileset);  
  viewer.scene.debugShowFramesPerSecond = true

  viewer.zoomTo(
    tileset,
    new Cesium.HeadingPitchRange(
      0.0,
      -0.5,
      tileset.boundingSphere.radius / 4.0
    )
  );

@jbo023
Copy link
Contributor

jbo023 commented Aug 22, 2024

@ggetz you can also add the following code to the sandcastle above to see the effect.

const originalGetHeight = viewer.scene.getHeight;
let currentFrame = 0;
let perFramecounter = 0;
let cartos = [];
viewer.scene.getHeight = function(cargo, heightRef) { 
  if (currentFrame !== viewer.scene._frameState.frameNumber) {
    currentFrame = viewer.scene._frameState.frameNumber;
    perFramecounter = 0;
    cartos = [];
  }  
  perFramecounter++;
  cartos.push(cargo)
  if (perFramecounter > 1) {
    console.log('getHeight executed: ', perFramecounter, cartos);    
  }
  originalGetHeight.apply(viewer.scene, arguments);
}

The Console log is called if getHeight is called more than once in a single Frame, in the main branch you can often see getHeight getting executed for the same cartograpic several times, if you move around in the scene.

image

@ggetz
Copy link
Contributor

ggetz commented Aug 22, 2024

Thanks @jbo023 for the test case!

@bkuster While I agree that improvement can be made in this area, I'm not sure this is a noticeable improvement. Using Google's 3D Tileset as well at the test case in this thread, I don't see a difference in FPS when navigating around the scene.

Am I missing anything? @jbo023 do you notice an improvement in FPS?

@jbo023
Copy link
Contributor

jbo023 commented Aug 23, 2024

@ggetz yeah its a bit hard to see, adding clamped points to the scene will point out the issue a bit more.

If you compare loading the following sandcastle you should see it. If i take a performance snapshot during loading, until 60 fps is reached, i see an improvement of aggregated time spend in executing 'Scene.getHeight` from around 10000ms to 5000ms

const viewer = new Cesium.Viewer("cesiumContainer", {});

viewer.scene.globe.depthTestAgainstTerrain = true;
const tileset = await Cesium.Cesium3DTileset.fromUrl("https://www.virtualcitymap.de/cesium_bugfix/baselayer/mesh_2020/tileset.json", {
  enableCollision: true,
  cacheBytes: 2048 * 1024 * 1024
});

viewer.scene.primitives.add(tileset);
viewer.scene.debugShowFramesPerSecond = true

viewer.zoomTo(
  tileset,
  new Cesium.HeadingPitchRange(
    0.0,
    -0.5,
    tileset.boundingSphere.radius / 4.0
  )
);

const longitude = 13.342032117;
const latitude =52.526441;
const delta = 0.001;

function addGeometry(i, j) {
  const west = longitude + delta * i;
  const north = latitude + delta * j + delta;

  viewer.entities.add({
        position: Cesium.Cartesian3.fromDegrees(west, north),
        point: {
          color: Cesium.Color.CORNFLOWERBLUE,
          pixelSize: 18,
          outlineColor: Cesium.Color.DARKSLATEGREY,
          outlineWidth: 3,
          heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
          disableDepthTestDistance: Number.POSITIVE_INFINITY,
        }});
}

function addGeometries() {
  for (let i = 0; i < 12; i++) {
    for (let j = 0; j < 12; j++) {
      addGeometry(i, j);
    }
  }
}
addGeometries();
viewer.zoomTo(viewer.entities);

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.

3 participants