Skip to content

Commit

Permalink
Fix render world copies regression (#5101)
Browse files Browse the repository at this point in the history
* Fix renderWorldCopies regression (#5027)

* set renderWorldCopies in GlobeTransform, and return it when not isGlobeRendering

* fix #5024

---------

Co-authored-by: Harel M <harel.mazor@gmail.com>

* Move tests to a designated file

* Update changelog

* Add test to make sure the behavior is kept

* Fix lint

* Update CHANGELOG.md

---------

Co-authored-by: Nathan Olson <nathanmolson@gmail.com>
  • Loading branch information
HarelM and NathanMOlson authored Nov 27, 2024
1 parent 1ac0a1b commit 662700d
Show file tree
Hide file tree
Showing 9 changed files with 494 additions and 442 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
- _...Add new stuff here..._

### 🐞 Bug fixes

- Fix regression in render world copies ([#5101](https://github.com/maplibre/maplibre-gl-js/pull/5101))
- _...Add new stuff here..._

## 5.0.0-pre.8
Expand Down
455 changes: 455 additions & 0 deletions src/geo/projection/covering_tiles.test.ts

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/geo/projection/covering_tiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ export function coveringTiles(transform: IReadonlyTransform, options: CoveringTi
const stack: Array<CoveringTilesStackEntry> = [];
const result: Array<CoveringTilesResult> = [];

if (transform.renderWorldCopies) {
if (transform.renderWorldCopies && detailsProvider.allowWorldCopies()) {
// Render copy of the globe thrice on both sides
for (let i = 1; i <= 3; i++) {
stack.push(newRootTile(-i));
Expand Down
5 changes: 5 additions & 0 deletions src/geo/projection/covering_tiles_details_provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,9 @@ export interface CoveringTilesDetailsProvider {
* Whether to allow variable zoom, which is used at high pitch angle to avoid loading an excessive amount of tiles.
*/
allowVariableZoom: (transform: IReadonlyTransform, options: CoveringTilesOptions) => boolean;

/**
* Whether to allow world copies to be rendered.
*/
allowWorldCopies: () => boolean;
}
4 changes: 4 additions & 0 deletions src/geo/projection/globe_covering_tiles_details_provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ export class GlobeCoveringTilesDetailsProvider implements CoveringTilesDetailsPr
return coveringZoomLevel(transform, options) > 4;
}

allowWorldCopies(): boolean {
return false;
}

getTileAABB(tileID: { x: number; y: number; z: number }, wrap: number, elevation: number, options: CoveringTilesOptions) {
return this._aabbCache.getTileAABB(tileID, wrap, elevation, options);
}
Expand Down
180 changes: 19 additions & 161 deletions src/geo/projection/globe_transform.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {angularCoordinatesRadiansToVector, mercatorCoordinatesToAngularCoordinat
import {expectToBeCloseToArray, getGlobeProjectionMock, sleep} from '../../util/test/util';
import {MercatorCoordinate} from '../mercator_coordinate';
import {tileCoordinatesToLocation} from './mercator_utils';
import {coveringTiles} from './covering_tiles';
import {MercatorTransform} from './mercator_transform';

function testPlaneAgainstLngLat(lngDegrees: number, latDegrees: number, plane: Array<number>) {
const lat = latDegrees / 180.0 * Math.PI;
Expand Down Expand Up @@ -612,166 +612,6 @@ describe('GlobeTransform', () => {
});
});

describe('coveringTiles', () => {
test('zoomed out', () => {
const transform = new GlobeTransform(globeProjectionMock);
transform.resize(128, 128);
transform.setCenter(new LngLat(0.0, 0.0));
transform.setZoom(-1);

const tiles = coveringTiles(transform, {
tileSize: 512,
});

expect(tiles).toEqual([
new OverscaledTileID(0, 0, 0, 0, 0)
]);
});

test('zoomed in', () => {
const transform = new GlobeTransform(globeProjectionMock);
transform.resize(128, 128);
transform.setCenter(new LngLat(-0.02, 0.01));
transform.setZoom(3);

const tiles = coveringTiles(transform, {
tileSize: 512,
});

expect(tiles).toEqual([
new OverscaledTileID(3, 0, 3, 3, 3),
new OverscaledTileID(3, 0, 3, 3, 4),
new OverscaledTileID(3, 0, 3, 4, 3),
new OverscaledTileID(3, 0, 3, 4, 4),
]);
});

test('zoomed in 512x512', () => {
const transform = new GlobeTransform(globeProjectionMock);
transform.resize(512, 512);
transform.setCenter(new LngLat(-0.02, 0.01));
transform.setZoom(3);

const tiles = coveringTiles(transform, {
tileSize: 512,
});

expect(tiles).toEqual([
new OverscaledTileID(3, 0, 3, 3, 3),
new OverscaledTileID(3, 0, 3, 3, 4),
new OverscaledTileID(3, 0, 3, 4, 3),
new OverscaledTileID(3, 0, 3, 4, 4),
new OverscaledTileID(3, 0, 3, 2, 3),
new OverscaledTileID(3, 0, 3, 2, 4),
new OverscaledTileID(3, 0, 3, 5, 3),
new OverscaledTileID(3, 0, 3, 5, 4),
new OverscaledTileID(3, 0, 3, 2, 2),
new OverscaledTileID(3, 0, 3, 2, 5),
new OverscaledTileID(3, 0, 3, 5, 2),
new OverscaledTileID(3, 0, 3, 5, 5),
]);
});

test('pitched', () => {
const transform = new GlobeTransform(globeProjectionMock);
transform.resize(128, 128);
transform.setCenter(new LngLat(-0.002, 0.001));
transform.setZoom(8);
transform.setMaxPitch(80);
transform.setPitch(80);

const tiles = coveringTiles(transform, {
tileSize: 512,
});

expect(tiles).toEqual([
new OverscaledTileID(6, 0, 6, 32, 31),
new OverscaledTileID(6, 0, 6, 31, 31),
new OverscaledTileID(10, 0, 10, 511, 512),
new OverscaledTileID(10, 0, 10, 512, 512)
]);
});

test('pitched+rotated', () => {
const transform = new GlobeTransform(globeProjectionMock);
transform.resize(128, 128);
transform.setCenter(new LngLat(-0.002, 0.001));
transform.setZoom(8);
transform.setMaxPitch(80);
transform.setPitch(80);
transform.setBearing(45);

const tiles = coveringTiles(transform, {
tileSize: 512,
});

expect(tiles).toEqual([
new OverscaledTileID(7, 0, 7, 64, 64),
new OverscaledTileID(7, 0, 7, 65, 63),
new OverscaledTileID(7, 0, 7, 64, 63),
new OverscaledTileID(7, 0, 7, 63, 63),
new OverscaledTileID(7, 0, 7, 64, 62),
new OverscaledTileID(10, 0, 10, 510, 512),
new OverscaledTileID(10, 0, 10, 511, 512),
new OverscaledTileID(10, 0, 10, 511, 513)
]);
});

test('antimeridian1', () => {
const transform = new GlobeTransform(globeProjectionMock);
transform.resize(128, 128);
transform.setCenter(new LngLat(179.99, -0.001));
transform.setZoom(5);

const tiles = coveringTiles(transform, {
tileSize: 512,
});

expect(tiles).toEqual([
new OverscaledTileID(5, 0, 5, 31, 16),
new OverscaledTileID(5, 0, 5, 31, 15),
new OverscaledTileID(5, 1, 5, 0, 16),
new OverscaledTileID(5, 1, 5, 0, 15),
]);
});

test('antimeridian2', () => {
const transform = new GlobeTransform(globeProjectionMock);
transform.resize(128, 128);
transform.setCenter(new LngLat(-179.99, 0.001));
transform.setZoom(5);

const tiles = coveringTiles(transform, {
tileSize: 512,
});

expect(tiles).toEqual([
new OverscaledTileID(5, 0, 5, 0, 15),
new OverscaledTileID(5, 0, 5, 0, 16),
new OverscaledTileID(5, -1, 5, 31, 15),
new OverscaledTileID(5, -1, 5, 31, 16),
]);
});

test('zoom < 0', () => {
const transform = new GlobeTransform(globeProjectionMock);
transform.resize(128, 128);
transform.setCenter(new LngLat(0.0, 80.0));
transform.setZoom(-0.5);

const tiles = coveringTiles(transform, {
tileSize: 512,
minzoom: 0,
maxzoom: 0,
reparseOverscaled: true
});

expect(tiles).toEqual([
new OverscaledTileID(0, 0, 0, 0, 0)
]);
});
});

test('transform and projection instance are synchronized properly', async () => {
const projectionMock = getGlobeProjectionMock();
const globeTransform = createGlobeTransform(projectionMock);
Expand All @@ -793,4 +633,22 @@ describe('GlobeTransform', () => {
expect(projectionMock.useGlobeRendering).toBe(true);
expect(globeTransform.isGlobeRendering).toBe(projectionMock.useGlobeRendering);
});

describe('render world copies', () => {
test('change projection and make sure render world copies is kept', () => {
const globeTransform = createGlobeTransform(globeProjectionMock);
globeTransform.setRenderWorldCopies(true);

expect(globeTransform.renderWorldCopies).toBeTruthy();
});

test('change transform and make sure render world copies is kept', () => {
const globeTransform = createGlobeTransform(globeProjectionMock);
globeTransform.setRenderWorldCopies(true);
const mercator = new MercatorTransform(0, 1, 2, 3, false);
mercator.apply(globeTransform);

expect(mercator.renderWorldCopies).toBeTruthy();
});
});
});
5 changes: 3 additions & 2 deletions src/geo/projection/globe_transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ export class GlobeTransform implements ITransform {
setMaxPitch(pitch: number): void {
this._helper.setMaxPitch(pitch);
}
setRenderWorldCopies(_renderWorldCopies: boolean): void {
setRenderWorldCopies(renderWorldCopies: boolean): void {
this._helper.setRenderWorldCopies(renderWorldCopies);
}
setBearing(bearing: number): void {
this._helper.setBearing(bearing);
Expand Down Expand Up @@ -212,7 +213,7 @@ export class GlobeTransform implements ITransform {
return this._helper.unmodified;
}
get renderWorldCopies(): boolean {
return false;
return this._helper.renderWorldCopies;
}

//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,8 @@ export class MercatorCoveringTilesDetailsProvider implements CoveringTilesDetail
const maxConstantZoomPitch = clamp(78.5 - zfov / 2, 0.0, 60.0);
return (!!options.terrain || transform.pitch > maxConstantZoomPitch || transform.padding.top >= 0.1)
}

allowWorldCopies(): boolean {
return true;
}
}
Loading

0 comments on commit 662700d

Please sign in to comment.