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

Solve the issue of #11877 #11907

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

Solve the issue of #11877 #11907

wants to merge 4 commits into from

Conversation

HapDragon
Copy link
Contributor

@HapDragon HapDragon commented Mar 28, 2024

solve the issue #11877

###11877

Testing plan

when camera lookAt something, using transform, which will lead to recompute camera position, add a restrict in the terrain adjustment process by comparing the magnitude of the transform's origin to a height level, to filter the position which is far away from the globe surface.

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 update 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, @HapDragon! Welcome to the Cesium community!

In order for us to review your PR, please complete the following steps:

Review Pull Request Guidelines to make sure your PR gets accepted quickly.

@ggetz
Copy link
Contributor

ggetz commented Apr 1, 2024

Thanks @HapDragon! We'll review this shortly!

@HapDragon
Copy link
Contributor Author

Hi, @ggetz , like the graph below:
image

Origin P will turn to P1 after terrain adjustment, actually I am not sure whether there should add some property to specify the threshold. Or use some angle threshold to determine whether to ignore the height change, I mean if the difference between origin P centric angle and new P1 centric angle bigger than some threshold, we will ignore the height change.

Thank you for reviewing.

Matrix4.getTranslation(transform, transformOrigin);
transformOriginLen = Cartesian3.magnitude(transformOrigin);
}
if (transformOriginLen > controller._minimumCollisionTerrainHeight) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure about the use of controller._minimumCollisionTerrainHeight here. That value was design to be the height above the ellipsoid surface, not the absolute value.

Additionally, that put us in this strange "middle ground" where the camera still re-orients strangely, like in this example below:

const viewer = new Cesium.Viewer("cesiumContainer", {
  //globe: false
});

const url = "../../SampleData/models/CesiumAir/Cesium_Air.glb";
const position = new Cesium.Cartesian3(0.0, 100000.0, 0.0);
const orientation = new Cesium.Quaternion(0.0, 0.0, 0.0, 1.0);

const entity = viewer.entities.add({
  name: url,
  position: position,
  orientation: orientation,
  model: {
    uri: url,
  },
});

viewer.camera.lookAt(
  new Cesium.Cartesian3(0.0, 100000.0, 1), 
  new Cesium.Cartesian3(0, 50, 0));

How would you feel about instead using a percentage of the ellipsoid radius? That will ensure we scale to other ellipsoids if needed without having to manually set a value.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hello ,
At line 2897, the comparision: controller._minimumCollisionTerrainHeight, it seemed should not be such a value. What I thought is to put a threshold to specify the maximum centric length of cartesian3, then let any point in a centric ball with the threshold radius will not do the height adjustment (if there is a transform upon the camera).

Thanks for your advice, I am a little confused about using a percentage of the ellipsoid radius. Does it mean using percentage of ellipsoid radius as the height threshold test?

I modify the adjustHeightForTerrain function again: it will avoid the problem in your example above and issue of #11877 as well:

function adjustHeightForTerrain(controller, cameraChanged) {
  controller._adjustedHeightForTerrain = true;

  const scene = controller._scene;
  const mode = scene.mode;
  const globe = scene.globe;

  if (mode === SceneMode.SCENE2D || mode === SceneMode.MORPHING) {
    return;
  }

  const camera = scene.camera;
  const ellipsoid = defaultValue(globe?.ellipsoid, Ellipsoid.WGS84);
  const projection = scene.mapProjection;


  let transform;
  let mag;
  if (!Matrix4.equals(camera.transform, Matrix4.IDENTITY)) {
    transform = Matrix4.clone(camera.transform, scratchAdjustHeightTransform);
    mag = Cartesian3.magnitude(camera.position);
    camera._setTransform(Matrix4.IDENTITY);
  }

  const cartographic = scratchAdjustHeightCartographic;
  if (mode === SceneMode.SCENE3D) {
    ellipsoid.cartesianToCartographic(camera.position, cartographic);
  } else {
    projection.unproject(camera.position, cartographic);
  }

  let heightUpdated = false; 
  if (cartographic.height < controller._minimumCollisionTerrainHeight) {  
    if((defined(transform)&&cartographic.height>-ellipsoid.maximumRadius*0.3)||!defined(transform)){
      const globeHeight = controller._scene.globeHeight;
      if (defined(globeHeight)) {
        const height = globeHeight + controller.minimumZoomDistance;
        const difference = globeHeight - controller._lastGlobeHeight;
        const percentDifference = difference / controller._lastGlobeHeight;
  
        // Unless the camera has been moved by user input, to avoid big jumps during tile loads
        // only make height updates when the globe height has been fairly stable across several frames
        if (
          cartographic.height < height &&
          (cameraChanged || Math.abs(percentDifference) <= 0.1)
        ) {
          cartographic.height = height;
          if (mode === SceneMode.SCENE3D) {
            ellipsoid.cartographicToCartesian(cartographic, camera.position);
          } else {
            projection.project(cartographic, camera.position);
          }
          heightUpdated = true;
        }
  
        if (cameraChanged || Math.abs(percentDifference) <= 0.1) {
          controller._lastGlobeHeight = globeHeight;
        } else {
          controller._lastGlobeHeight += difference * 0.1;
        }
      }
   }  
  }

  if (defined(transform)) {
    camera._setTransform(transform);
    if (heightUpdated) {
      Cartesian3.normalize(camera.position, camera.position);
      Cartesian3.negate(camera.position, camera.direction);
      Cartesian3.multiplyByScalar(
        camera.position,
        Math.max(mag, controller.minimumZoomDistance),
        camera.position
      );
      Cartesian3.normalize(camera.direction, camera.direction);
      Cartesian3.cross(camera.direction, camera.up, camera.right);
      Cartesian3.cross(camera.right, camera.direction, camera.up);
    }
  }
}

It use this code to filter point in deep underground areas:
(defined(transform)&&cartographic.height>-ellipsoid.maximumRadius*0.3)

@ggetz
Copy link
Contributor

ggetz commented Apr 22, 2024

Thanks for the suggestion @HapDragon! I have one comment before we proceed.

@HapDragon
Copy link
Contributor Author

Thanks for the suggestion@ggetz , I have commented on the code several months ago, it seemed could not been seen. that is to use: if((defined(transform)&&cartographic.height>-ellipsoid.maximumRadius*0.3)||!defined(transform)) to filter point in deep underground areas.

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.

2 participants