Skip to content

[geo-layers] Fix GlobeView Mercator tile warping#10350

Open
charlieforward9 wants to merge 7 commits into
masterfrom
cr/fix-globe-mercator-tiles
Open

[geo-layers] Fix GlobeView Mercator tile warping#10350
charlieforward9 wants to merge 7 commits into
masterfrom
cr/fix-globe-mercator-tiles

Conversation

@charlieforward9

@charlieforward9 charlieforward9 commented Jun 6, 2026

Copy link
Copy Markdown
Member

Summary

Fixes GlobeView rendering for WebMercator terrain and imagery tiles. Terrain mesh rows and bitmap UVs now respect WebMercator row spacing instead of treating tile latitude as linear from top to bottom.

Why

XYZ/slippy tiles are encoded in WebMercator space. In GlobeView, deck.gl positions tile geometry in lng/lat space, so using linear latitude rows compresses terrain and imagery toward high latitudes. The distortion is easiest to see at far zooms and pitched globe views.

What Changed

  • TerrainLayer: remaps tiled GlobeView mesh row latitude through @math.gl/web-mercator during the private terrain load path.
  • TerrainLayer: keeps the remap scoped to tiled GlobeView and copies the position array so loader/cached mesh data is not mutated.
  • TileLayer: defaults generated BitmapLayer tile imagery to WebMercator image coordinates in GlobeView while preserving explicit _imageCoordinateSystem overrides.
  • Tests cover terrain row remapping, source mesh integrity, default GlobeView bitmap coordinates, and explicit bitmap coordinate preservation.

Validation

  • yarn vitest run --project headless test/modules/geo-layers/terrain-layer.spec.ts
  • yarn vitest run --project headless test/modules/geo-layers/tile-layer/tile-layer.spec.ts
  • Pre-commit hook ran lint/format/node smoke tests during commit; only existing warnings were reported.

Visual Validation

projection-warping.mov

@coveralls

coveralls commented Jun 6, 2026

Copy link
Copy Markdown

Coverage Status

coverage: 83.181% (+0.02%) from 83.166% — cr/fix-globe-mercator-tiles into master

@chrisgervang chrisgervang left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fix looks good. Let's consider how to make this generalized for other layers that may need the same correction

Comment thread modules/geo-layers/src/terrain-layer/terrain-layer.ts Outdated
Comment thread modules/geo-layers/src/tile-layer/tile-layer.ts
private _getGlobeBitmapLayerProps(layer: Layer): Record<string, unknown> | null {
if (
!(this.context.viewport instanceof _GlobeViewport) ||
!(layer instanceof BitmapLayer) ||

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do BitmapLayers and other layers that need this reprojection have in common?

Have you considered the qualities a layer needs be susceptible to warping?

bounds: overlappedBounds,
elevationDecoder,
meshMaxError,
remapToWebMercatorTile: isGlobe,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All tile sublayers rendered on a globe trigger the remap. Is it true that only the built-in bitmap layer gets modified by this, or would other sublayers get remapped too?

@chrisgervang chrisgervang mentioned this pull request Jun 11, 2026
59 tasks
@chrisgervang chrisgervang added this to the v9.4 milestone Jun 11, 2026
@charlieforward9 charlieforward9 self-assigned this Jun 13, 2026
@charlieforward9

Copy link
Copy Markdown
Member Author

@copilot resolver los conflictos de combinación en esta rama.

…or-tiles

# Conflicts:
#	modules/geo-layers/src/terrain-layer/terrain-layer.ts

Copilot AI commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

@copilot resolver los conflictos de combinación en esta rama.

Done — merged origin/master into this branch and resolved the one conflict in terrain-layer.ts. The only changes needed were:

  • Remove the duplicate _GlobeViewport bare import (master renamed it to _GlobeViewport as GlobeViewport)
  • Remove the duplicate COORDINATE_SYSTEM import our branch had added
  • Update import type {Mesh}import type {MeshAttributes} and propagate that rename through all type aliases, state declarations, and function signatures to match master's loaders.gl upgrade

@charlieforward9

Copy link
Copy Markdown
Member Author

@copilot CI hurtin

Copilot AI commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

@copilot CI hurtin

Fixed in the latest commit. The CI failures were TypeScript errors introduced during the merge conflict resolution — I incorrectly replaced Mesh with MeshAttributes without accounting for the difference: MeshAttributes is an index type {[k: string]: MeshAttribute}, so TypeScript resolves mesh.attributes as MeshAttribute (the individual attribute value type, not the nested attributes dict). The terrain loader actually returns {attributes: {POSITION: ..., TEXCOORD_0: ...}, header: {...}} at runtime. Fixed by using (mesh as any).attributes casts in remapTerrainMeshToWebMercatorTile and // @ts-ignore + MeshWithBoundingBox cast in onViewportLoad, following the same pattern master already uses for the header.boundingBox access.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants