Skip to content

Commit

Permalink
Fix zoom on side globes with terrain 3D (#3425)
Browse files Browse the repository at this point in the history
* Fix zoom on side globes with terrain 3D

* Add changelog entry
  • Loading branch information
sbachinin authored Nov 29, 2023
1 parent b7b86c1 commit 8b16a2a
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 40 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
- _...Add new stuff here..._

### 🐞 Bug fixes
- Fix zooming outside the central globe when terrain 3D is enabled ([#3425](https://github.com/maplibre/maplibre-gl-js/pull/3425))
- _...Add new stuff here..._

## 4.0.0-pre.1
Expand Down
45 changes: 22 additions & 23 deletions src/render/terrain.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,22 +52,27 @@ describe('Terrain', () => {
expect(coordinate).not.toBeNull();
});

const setupMercatorOverflow = (centerLng: number) => {
const setupMercatorOverflow = () => {
const WORLD_WIDTH = 4;
const painter = {
context: new Context(gl(WORLD_WIDTH, 1) as any),
width: WORLD_WIDTH,
height: 1,
transform: {center: {lng: centerLng}}
} as any as Painter;
const sourceCache = {} as SourceCache;
const terrain = new Terrain(painter, sourceCache, {} as any as TerrainSpecification);
const mockTile = {tileID: {canonical: {x: 0, y: 0, z: 0}}};
terrain.sourceCache.getTileByID = () => mockTile as any as Tile;
const tileIdsToWraps = {a: -1, b: 0, c: 1, d: 2};
terrain.sourceCache.getTileByID = (id) => {
return {
tileID: {
canonical: {x: 0, y: 0, z: 0},
wrap: tileIdsToWraps[id]
}
} as any as Tile;
};
terrain.getElevation = () => 0;
terrain.coordsIndex = ['abcd'];
terrain._coordsTextureSize = WORLD_WIDTH;
const pixels = new Uint8Array([2, 0, 0, 255, 3, 0, 0, 255, 0, 0, 0, 255, 1, 0, 0, 255]);
terrain.coordsIndex = Object.keys(tileIdsToWraps);
const pixels = new Uint8Array([0, 0, 0, 255, 0, 0, 0, 254, 0, 0, 0, 253, 0, 0, 0, 252]);
const image = new RGBAImage({width: WORLD_WIDTH, height: 1}, pixels);
const imageTexture = new Texture(painter.context, image, painter.context.gl.RGBA);
terrain.getFramebuffer('coords'); // allow init of frame buffers
Expand All @@ -77,32 +82,26 @@ describe('Terrain', () => {

test(
`pointCoordiate should return negative mercator x
if center.lng is to the right of 180 meridian
and a given point is to the left of 180`,
if the point is on the LEFT outside the central globe`,
() => {
expect.assertions(2);
const centerLng = -170;
const pointX = 1; // x in the left half of the 4-px world
const terrain = setupMercatorOverflow(centerLng);
expect.assertions(1);
const pointX = 0;
const terrain = setupMercatorOverflow();
const coordinate = terrain.pointCoordinate(new Point(pointX, 0));

expect(coordinate.x).toBeLessThan(0);
expect(coordinate.x).toBeGreaterThan(-1);
expect(coordinate.x).toBe(-1);
});

test(
`pointCoordiate should return mercator x greater than 1
if center.lng is to the left of 180 meridian
and a given point is to the right of 180`,
if the point is on the RIGHT outside the central globe`,
() => {
expect.assertions(2);
const centerLng = 170;
const pointX = 3; // x in the right half of the 4-px world
const terrain = setupMercatorOverflow(centerLng);
expect.assertions(1);
const pointX = 3;
const terrain = setupMercatorOverflow();
const coordinate = terrain.pointCoordinate(new Point(pointX, 0));

expect(coordinate.x).toBeGreaterThan(1);
expect(coordinate.x).toBeLessThan(2);
expect(coordinate.x).toBe(2);
});

test('Calculate tile minimum and maximum elevation', () => {
Expand Down
19 changes: 2 additions & 17 deletions src/render/terrain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {Painter} from './painter';
import {Texture} from '../render/texture';
import type {Framebuffer} from '../gl/framebuffer';
import Point from '@mapbox/point-geometry';
import {MercatorCoordinate, lngFromMercatorX, mercatorXfromLng} from '../geo/mercator_coordinate';
import {MercatorCoordinate} from '../geo/mercator_coordinate';
import {TerrainSourceCache} from '../source/terrain_source_cache';
import {SourceCache} from '../source/source_cache';
import {EXTENT} from '../data/extent';
Expand Down Expand Up @@ -341,9 +341,8 @@ export class Terrain {
if (!tile) return null;
const coordsSize = this._coordsTextureSize;
const worldSize = (1 << tile.tileID.canonical.z) * coordsSize;
const mercatorX = (tile.tileID.canonical.x * coordsSize + x) / worldSize;
return new MercatorCoordinate(
this._allowMercatorOverflow(p, mercatorX),
(tile.tileID.canonical.x * coordsSize + x) / worldSize + tile.tileID.wrap,
(tile.tileID.canonical.y * coordsSize + y) / worldSize,
this.getElevation(tile.tileID, x, y, coordsSize)
);
Expand Down Expand Up @@ -442,18 +441,4 @@ export class Terrain {
mercatorY
};
}

_allowMercatorOverflow(p: Point, mercatorX: number): number {
const inLeftHalf = p.x < (this.painter.width / 2);
let lng = lngFromMercatorX(mercatorX);
const centerLng = this.painter.transform.center.lng;
if (
(inLeftHalf && Math.sign(lng) > 0 && Math.sign(centerLng) < 0) ||
(!inLeftHalf && Math.sign(lng) < 0 && Math.sign(centerLng) > 0)
) {
lng = 360 * Math.sign(centerLng) + lng;
return mercatorXfromLng(lng);
}
return mercatorX;
}
}

0 comments on commit 8b16a2a

Please sign in to comment.