Skip to content

Commit

Permalink
Return above-sea-level elevation from queryTerrainElevation + Pass lo…
Browse files Browse the repository at this point in the history
…wered mercator matrix to custom layer (#3854)

* Pass lowered mercator matrix + return sea-level elevation from queryTerrainElevation

* Update comments in threejs with terrain example

* Update queryTerrainElevation test

* Pass non-translated matrices to custom layer on mercator map (this substitutes my initial commit where the matrix was explicitly un-translated)

* Remove unused import

* Add changelog

---------

Co-authored-by: Harel M <[email protected]>
  • Loading branch information
sbachinin and HarelM authored Nov 1, 2024
1 parent e065d91 commit ec8398a
Show file tree
Hide file tree
Showing 5 changed files with 16 additions and 42 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
### ✨ Features and improvements
- Catches network fetching errors such as CORS, DNS or malformed URL as actual `AJAXError` to expose HTTP request details to the `"error"` event (https://github.com/maplibre/maplibre-gl-js/pull/4822)
- Add setVerticalFieldOfView() to public API ([#4717](https://github.com/maplibre/maplibre-gl-js/issues/4717))
- ⚠️ Return actual altitude from queryTerrainElevation + Pass non-translated matrices to custom layer on mercator map ([#3854](https://github.com/maplibre/maplibre-gl-js/pull/3854))
- Disable sky when using globe and blend it in when changing to mercator ([#4853](https://github.com/maplibre/maplibre-gl-js/issues/4853))
- _...Add new stuff here..._

Expand Down
7 changes: 2 additions & 5 deletions src/geo/projection/mercator_transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -840,15 +840,12 @@ export class MercatorTransform implements ITransform {
// both matrices by EXTENT. We also need to rescale Z.

const scale: vec3 = [EXTENT, EXTENT, this.worldSize / this._helper.pixelsPerMeter];
const translate: vec3 = [0, 0, this.elevation];

const fallbackMatrixScaled = createMat4f64();
mat4.translate(fallbackMatrixScaled, tileMatrix, translate);
mat4.scale(fallbackMatrixScaled, fallbackMatrixScaled, scale);
mat4.scale(fallbackMatrixScaled, tileMatrix, scale);

const projectionMatrixScaled = createMat4f64();
mat4.translate(projectionMatrixScaled, tileMatrix, translate);
mat4.scale(projectionMatrixScaled, projectionMatrixScaled, scale);
mat4.scale(projectionMatrixScaled, tileMatrix, scale);

projectionData.fallbackMatrix = fallbackMatrixScaled;
projectionData.mainMatrix = projectionMatrixScaled;
Expand Down
39 changes: 11 additions & 28 deletions src/ui/camera.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {fixedLngLat, fixedNum} from '../../test/unit/lib/fixed';
import {setMatchMedia} from '../util/test/util';
import {mercatorZfromAltitude} from '../geo/mercator_coordinate';
import {Terrain} from '../render/terrain';
import {LngLat, LngLatLike} from '../geo/lng_lat';
import {LngLat} from '../geo/lng_lat';
import {Event} from '../util/evented';
import {LngLatBounds} from '../geo/lng_lat_bounds';
import {MercatorTransform} from '../geo/projection/mercator_transform';
Expand Down Expand Up @@ -2413,34 +2413,17 @@ describe('queryTerrainElevation', () => {
expect(result).toBeNull();
});

test('should return the correct elevation', () => {
// Set up mock transform and terrain objects
const transform = new MercatorTransform(0, 22, 0, 60, true);
transform.setElevation(50);
const terrain = {
getElevationForLngLatZoom: jest.fn().mockReturnValue(200)
} as any as Terrain;

// Set up camera with mock transform and terrain
camera.transform = transform;
camera.terrain = terrain;

// Call queryTerrainElevation with mock lngLat
const lngLatLike: LngLatLike = [1, 2];
const expectedElevation = 150; // 200 - 50 = 150
const result = camera.queryTerrainElevation(lngLatLike);

// Check that transform.getElevation was called with the correct arguments
expect(terrain.getElevationForLngLatZoom).toHaveBeenCalledWith(
expect.objectContaining({
lng: lngLatLike[0],
lat: lngLatLike[1],
}),
transform.tileZoom
);
test('Calls getElevationForLngLatZoom with correct arguments', () => {
const getElevationForLngLatZoom = jest.fn();
camera.terrain = {getElevationForLngLatZoom} as any as Terrain;
camera.transform = new MercatorTransform(0, 22, 0, 60, true);

camera.queryTerrainElevation([1, 2]);

// Check that the correct elevation value was returned
expect(result).toEqual(expectedElevation);
expect(camera.terrain.getElevationForLngLatZoom).toHaveBeenCalledWith(
expect.objectContaining({lng: 1, lat: 2,}),
camera.transform.tileZoom
);
});
});

Expand Down
3 changes: 1 addition & 2 deletions src/ui/camera.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1634,7 +1634,6 @@ export abstract class Camera extends Evented {
if (!this.terrain) {
return null;
}
const elevation = this.terrain.getElevationForLngLatZoom(LngLat.convert(lngLatLike), this.transform.tileZoom);
return elevation - this.transform.elevation;
return this.terrain.getElevationForLngLatZoom(LngLat.convert(lngLatLike), this.transform.tileZoom);
}
}
8 changes: 1 addition & 7 deletions test/examples/add-3d-model-with-terrain.html
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@
const axesHelper = new THREE.AxesHelper(60);
this.scene.add(axesHelper);

// Getting model elevations (in meters) relative to scene origin from maplibre's terrain.
// Getting model elevations in meters above sea level
const sceneElevation = map.queryTerrainElevation(sceneOrigin) || 0;
const model1Elevation = map.queryTerrainElevation(model1Location) || 0;
const model2Elevation = map.queryTerrainElevation(model2Location) || 0;
Expand Down Expand Up @@ -178,12 +178,6 @@
},

render(gl, args) {

// `queryTerrainElevation` gives us the elevation of a point on the terrain
// **relative to the elevation of `center`**,
// where `center` is the point on the terrain that the middle of the camera points at.
// If we didn't account for that offset, and the scene lay on a point on the terrain that is
// below `center`, then the scene would appear to float in the air.
const offsetFromCenterElevation = map.queryTerrainElevation(sceneOrigin) || 0;
const sceneOriginMercator = maplibregl.MercatorCoordinate.fromLngLat(sceneOrigin, offsetFromCenterElevation);

Expand Down

0 comments on commit ec8398a

Please sign in to comment.