diff --git a/CHANGELOG.md b/CHANGELOG.md index 90b0e5b697..c552929906 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/src/render/terrain.test.ts b/src/render/terrain.test.ts index 39b384a9fc..7f6ae85ae7 100644 --- a/src/render/terrain.test.ts +++ b/src/render/terrain.test.ts @@ -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 @@ -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', () => { diff --git a/src/render/terrain.ts b/src/render/terrain.ts index 47afdd0c5a..248f82f712 100644 --- a/src/render/terrain.ts +++ b/src/render/terrain.ts @@ -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'; @@ -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) ); @@ -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; - } }