Skip to content

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

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

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

Conversation

@charlieforward9

@charlieforward9 charlieforward9 commented Jun 6, 2026

Copy link
Copy Markdown
Member

Goals

Fix Web Mercator terrain and bitmap warping in curved projections while keeping projection behavior with the layer that owns the mesh and coordinate contract.

Changes

  • BitmapLayer now rebuilds its mesh and coordinate-conversion uniforms only when the active viewport's mesh resolution changes.
  • Web Mercator imagery continues to opt in through the existing _imageCoordinateSystem: COORDINATE_SYSTEM.CARTESIAN contract. BitmapLayer subclasses inherit the behavior without TileLayer type checks or cloning.
  • TileLayer remains generic: this PR adds no TileLayer prop, projection branch, cache invalidation, or sublayer inspection.
  • TerrainLayer remaps tiled mesh rows from Web Mercator spacing into longitude/latitude for curved projections, while preserving texture coordinates and copying position data rather than mutating loader output.
  • Both paths use the viewport's resolution capability instead of identifying GlobeViewport by class.
  • The terrain loader result now has a local runtime-accurate mesh type, removing the previous any casts around nested attributes and bounding boxes.

Why this design

The two susceptible data contracts are explicit and layer-owned:

  • A bitmap declares that its image coordinates are Web Mercator through _imageCoordinateSystem.
  • Tiled terrain is decoded with Web Mercator row spacing and requires its mesh rows to be remapped before curved rendering.

The viewport's mesh resolution is the shared rendering capability. Flat views use a six-vertex bitmap quad with no coordinate conversion; curved views tessellate that same bitmap and enable Web Mercator conversion. This keeps custom layers and all other TileLayer sublayers untouched.

Validation

  • yarn
  • focused Vitest: 15/15 across BitmapLayer, TerrainLayer, and unchanged TileLayer coverage
  • yarn build
  • yarn lint
  • yarn test-website (passes with the repository's existing Docusaurus/source-map warnings)
  • exact-head browser QA, MapView -> GlobeView -> MapView:
    • MapView: 6 vertices, coordinate conversion 0
    • GlobeView: tessellated mesh, coordinate conversion 1
    • MapView again: 6 vertices, coordinate conversion 0
    • no browser console errors

Visual Validation

projection-warping.mov

@coveralls

coveralls commented Jun 6, 2026

Copy link
Copy Markdown

Coverage Status

coverage: 82.259% (+0.009%) from 82.25% — 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 Outdated
Comment thread modules/geo-layers/src/tile-layer/tile-layer.ts Outdated
Comment thread modules/geo-layers/src/terrain-layer/terrain-layer.ts Outdated
@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

This comment has been minimized.

…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.

@greptile-apps

greptile-apps Bot commented Aug 24, 2026

Copy link
Copy Markdown

Greptile Summary

The PR corrects GlobeView rendering for Web Mercator terrain and explicitly identified bitmap imagery.

  • Remaps tiled terrain mesh rows from Web Mercator spacing to longitude/latitude while preserving source mesh buffers.
  • Makes BitmapLayer meshes and coordinate-conversion uniforms refresh when switching between flat-map and globe projections.
  • Adds focused regression coverage for terrain remapping, source-data integrity, and projection transitions.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
modules/geo-layers/src/terrain-layer/terrain-layer.ts Copies tiled terrain positions and remaps mesh-row latitudes through Web Mercator coordinates only for globe rendering.
modules/layers/src/bitmap-layer/bitmap-layer.ts Rebuilds projection-sensitive bitmap mesh and coordinate state when viewport resolution changes.
test/modules/geo-layers/terrain-layer.spec.ts Adds regression coverage for GlobeView terrain-row remapping and verifies that loader-owned mesh data remains unchanged.
test/modules/layers/bitmap-layer.spec.ts Adds coverage for explicit bitmap coordinate conversion and mesh rebuilding across MapView and GlobeView transitions.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Web Mercator tile data] --> B{Layer type}
  B -->|Terrain| C[Load terrain mesh]
  C --> D[Copy position buffer]
  D --> E[Remap UV row spacing to latitude]
  E --> F[Render GlobeView mesh]
  B -->|Bitmap| G[Read active viewport resolution]
  G --> H[Build projection-appropriate mesh]
  H --> I[Apply explicit image-coordinate conversion]
  I --> J[Render bitmap]
Loading

Reviews (4): Last reviewed commit: "refactor(geo-layers): detect curved proj..." | Re-trigger Greptile

Comment thread modules/geo-layers/src/tile-layer/tile-layer.ts Outdated
Comment thread modules/geo-layers/src/terrain-layer/terrain-layer.ts Outdated
Comment thread modules/geo-layers/src/tile-layer/tile-layer.ts Outdated
@charlieforward9

Copy link
Copy Markdown
Member Author

@chrisgervang I revisited this and moved the bitmap fix out of TileLayer entirely.

The common quality is not "tile sublayer." It is a layer whose mesh sampling depends on the curved viewport's resolution, paired with an explicit source-coordinate contract. BitmapLayer already owns both: callers identify Web Mercator imagery with _imageCoordinateSystem: COORDINATE_SYSTEM.CARTESIAN, and BitmapLayer now rebuilds its mesh and coordinate uniforms when the viewport resolution changes. Subclasses inherit that behavior directly—there is no instanceof check, clone override, new TileLayer prop, or globe-specific cache path.

Terrain keeps its independent Web Mercator row remap in TerrainLayer, and it uses the same viewport capability instead of checking the GlobeViewport class.

I added a CustomBitmapLayer MapView -> GlobeView -> MapView regression. The live exact-head run moves from 6 vertices / conversion 0, to a tessellated mesh / conversion 1, and back to 6 / 0 with no console errors. Focused tests are 15/15; build, lint, and website checks pass on f6f9b2ea83.

@greptile-apps

greptile-apps Bot commented Aug 26, 2026

Copy link
Copy Markdown

Want your agent to iterate on Greptile's feedback? Try greploops.

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