Skip to content

Commit

Permalink
GlobeControls: Apply a minimum elevation (#509)
Browse files Browse the repository at this point in the history
* Add minimum GlobeControls elevation and ensure `getPositionElevation` can return a negative value.

* Fix comment, tests
  • Loading branch information
gkjohnson authored Mar 20, 2024
1 parent 357c196 commit 12875de
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 12 deletions.
9 changes: 4 additions & 5 deletions src/three/controls/GlobeControls.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const _pointer = new Vector2();
const _prevPointer = new Vector2();
const _deltaPointer = new Vector2();

const MIN_ELEVATION = 10;
const MAX_GLOBE_DISTANCE = 2 * 1e7;
const GLOBE_TRANSITION_THRESHOLD = 0.75 * 1e7;
export class GlobeControls extends EnvironmentControls {
Expand Down Expand Up @@ -164,12 +165,10 @@ export class GlobeControls extends EnvironmentControls {
const invMatrix = _invMatrix.copy( tilesGroup.matrixWorld ).invert();
_pos.copy( camera.position ).applyMatrix4( invMatrix );
ellipsoid.getPositionToCartographic( _pos, _latLon );
const elevation = ellipsoid.getPositionElevation( _pos );

// due to the level of precision of the tiles / sphere
// we can get an elevation that will be higher than the actual elevation.
// when we end up below the surface of the ellipsoid the elevation is returned as positive instead of negative
// resulting in a horizon distance that is too large.
// use a minimum elevation for computing the horizon distance to avoid the far clip
// plane approaching zero as the camera goes to or below sea level.
const elevation = Math.max( ellipsoid.getPositionElevation( _pos ), MIN_ELEVATION );
const horizonDistance = ellipsoid.calculateHorizonDistance( _latLon.lat, elevation );
camera.far = horizonDistance + 0.1;

Expand Down
8 changes: 4 additions & 4 deletions src/three/math/Ellipsoid.js
Original file line number Diff line number Diff line change
Expand Up @@ -227,11 +227,11 @@ export class Ellipsoid {

getPositionElevation( pos ) {

this.getPositionToSurfacePoint( pos, _vec3 );

const elevation = _vec3.distanceTo( pos );
// logic from "getPositionToCartographic"
this.getPositionToSurfacePoint( pos, _vec );

return elevation;
const heightDelta = _vec2.subVectors( pos, _vec );
return Math.sign( heightDelta.dot( pos ) ) * heightDelta.length();

}

Expand Down
6 changes: 3 additions & 3 deletions test/Ellipsoid.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -196,15 +196,15 @@ describe( 'Ellipsoid', () => {

const northPos100 = new Vector3( 0, 0, WGS84_HEIGHT + 100 );
expect( wgsEllipse.getPositionElevation( northPos100 ) ).toBeCloseTo( 100, 1e-6 );
const southPos100 = new Vector3( 0, 0, - WGS84_HEIGHT + 100 );
const southPos100 = new Vector3( 0, 0, - WGS84_HEIGHT - 100 );
expect( wgsEllipse.getPositionElevation( southPos100 ) ).toBeCloseTo( 100, 1e-6 );
const xPos100 = new Vector3( WGS84_RADIUS + 100, 0, 0 );
expect( wgsEllipse.getPositionElevation( xPos100 ) ).toBeCloseTo( 100, 1e-6 );
const mxPos100 = new Vector3( - WGS84_RADIUS + 100, 0, 0 );
const mxPos100 = new Vector3( - WGS84_RADIUS - 100, 0, 0 );
expect( wgsEllipse.getPositionElevation( mxPos100 ) ).toBeCloseTo( 100, 1e-6 );
const zPos100 = new Vector3( 0, WGS84_RADIUS + 100, 0 );
expect( wgsEllipse.getPositionElevation( zPos100 ) ).toBeCloseTo( 100, 1e-6 );
const mzPos100 = new Vector3( 0, - WGS84_RADIUS + 100, 0 );
const mzPos100 = new Vector3( 0, - WGS84_RADIUS - 100, 0 );
expect( wgsEllipse.getPositionElevation( mzPos100 ) ).toBeCloseTo( 100, 1e-6 );

} );
Expand Down

0 comments on commit 12875de

Please sign in to comment.