Skip to content

First valuable feature: real terrain source for 3D Tiles quantized-mesh (#4493)#7953

Draft
clement-igonet wants to merge 3 commits into
maplibre:mainfrom
clement-igonet:feat/3d-tiles-terrain-source-4493
Draft

First valuable feature: real terrain source for 3D Tiles quantized-mesh (#4493)#7953
clement-igonet wants to merge 3 commits into
maplibre:mainfrom
clement-igonet:feat/3d-tiles-terrain-source-4493

Conversation

@clement-igonet

@clement-igonet clement-igonet commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Phase 2 of #4493, following the POC in #7952.

Converts quantized-mesh terrain tiles to terrain-RGB via addProtocol (same pattern as the geotiff plugin, per @HarelM's suggestion below), so the terrain source is a normal raster-dem source — map.setTerrain(), queryTerrainElevation(), draping, hillshade, and color-relief all work with zero core changes.

Bundles a single real Cesium World Terrain tile (Mont Blanc massif, z9) to keep the PR light; dynamic tile-covering resolution maps requested Mercator tiles onto it. The hardening follow-up (#7958) extends this to multi-zoom, live endpoints, and a worker.

Launch Checklist

  • Confirm your changes do not include backports from Mapbox projects
  • Briefly describe the changes in this PR.
  • Link to related issues.
  • Confirm you have read our AI policy here.

Assisted-By: Claude Sonnet 5 (claude-sonnet-5)

Summary by CodeRabbit

  • New Features

    • Added an example demonstrating Cesium quantized-mesh terrain rendered as MapLibre terrain.
    • Added terrain tile processing with elevation queries, hillshade visualization, terrain exaggeration, and summit markers with popups.
    • Added a bundled Mont Blanc terrain tile asset for the example.
  • Chores

    • Terrain files are now treated as binary assets to prevent unintended text modifications.

@HarelM

HarelM commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

The text was too long for me to read, but why not simply use addProtocol and convert the tiles' data into terrainRGB like the geotiff plugin does?

@HarelM

HarelM commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

Please make sure to read our AI policy. This is somewhat violating it and impacts my motivation to review the other PRs you opened...

@codecov

codecov Bot commented Jul 15, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.25%. Comparing base (4435459) to head (89abeef).
⚠️ Report is 5 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #7953   +/-   ##
=======================================
  Coverage   93.25%   93.25%           
=======================================
  Files         290      290           
  Lines       24650    24650           
  Branches     6471     6471           
=======================================
  Hits        22987    22987           
  Misses       1663     1663           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@clement-igonet
clement-igonet force-pushed the feat/3d-tiles-terrain-source-4493 branch 4 times, most recently from 84c073f to f6bd0f6 Compare July 16, 2026 05:08
@clement-igonet

Copy link
Copy Markdown
Contributor Author

Please make sure to read our AI policy. This is somewhat violating it and impacts my motivation to review the other PRs you opened...

OK Guy !

@clement-igonet
clement-igonet marked this pull request as ready for review July 16, 2026 12:21
@clement-igonet
clement-igonet force-pushed the feat/3d-tiles-terrain-source-4493 branch 2 times, most recently from dceb263 to 470265c Compare July 16, 2026 13:52
…maplibre#4493)

Converts quantized-mesh tiles to terrain-RGB on the fly via
addProtocol (same pattern as the geotiff plugin), so the terrain
source is a normal raster-dem source - map.setTerrain(),
queryTerrainElevation(), hillshade, and plain Markers sitting on the
terrain all work with zero core changes.

The decoder (header, delta+zigzag vertices, high-water-mark indices)
is shared with the POC example; new here is barycentric resampling of
the irregular TIN onto the regular grid raster-dem expects, EPSG:4326
to Web Mercator tile-covering resolution, and a distance-based taper
where requested tiles extend past the bundled tile's coverage.

Bundles the same single real Cesium World Terrain tile as the POC
(Mont Blanc massif, zoom 9) to keep the PR light.
@clement-igonet
clement-igonet force-pushed the feat/3d-tiles-terrain-source-4493 branch from 470265c to f4158fc Compare July 16, 2026 21:49
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a bundled Mont Blanc quantized-mesh terrain tile and an example that decodes it, resamples it into Terrarium terrain-RGB tiles, and renders the result through MapLibre’s raster-dem terrain source.

Changes

Terrain source example

Layer / File(s) Summary
Bundle terrain tile asset
.gitattributes, docs/assets/examples/mont-blanc-terrain-tiles/9-531-386.terrain
Marks .terrain files as binary and adds the Mont Blanc terrain tile payload with metadata.
Decode and resample terrain
test/examples/render-3d-tiles-terrain-source.html
Decodes quantized-mesh headers, vertices, and indices; interpolates elevations; handles coverage edges; and generates Terrarium terrain-raster data.
Connect terrain to MapLibre
test/examples/render-3d-tiles-terrain-source.html
Registers the custom tile protocol, configures raster-dem terrain and hillshade, adds summit markers, and displays queried terrain elevation.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant MapLibre
  participant quantizedMeshProtocol
  participant decodeQuantizedMesh
  participant buildTerrainRgbImageData
  participant RasterDemSource
  MapLibre->>quantizedMeshProtocol: request quantized-mesh://z/x/y
  quantizedMeshProtocol->>decodeQuantizedMesh: fetch bundled terrain payload
  decodeQuantizedMesh->>buildTerrainRgbImageData: decoded mesh
  buildTerrainRgbImageData->>RasterDemSource: ImageBitmap terrain-RGB tile
  RasterDemSource->>MapLibre: terrain elevation data
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly reflects the main change: adding a real terrain source for 3D Tiles quantized-mesh data.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/examples/render-3d-tiles-terrain-source.html`:
- Around line 328-335: Update findCoveringQMTiles to collect and return
intersecting tiles from every zoom in descending order instead of returning on
the first non-empty zoom. Preserve each tile’s computed bounds so
multiMeshElevationAt can select the deepest available mesh per point and use
lower-resolution parents for uncovered areas.
- Around line 357-375: The buildTerrainRgbImageData rasterization currently
performs synchronous per-pixel work without cancellation. Thread the protocol
handler’s AbortController signal through the tile fetch and rasterization path,
and make the row/pixel loops stop promptly when the signal is aborted; ensure
aborted work does not continue producing obsolete tile data.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: d79f998f-e5c8-491d-a875-37fb5d598bc5

📥 Commits

Reviewing files that changed from the base of the PR and between e2c1f8d and f4158fc.

⛔ Files ignored due to path filters (1)
  • docs/assets/examples/render-3d-tiles-terrain-source.png is excluded by !**/*.png
📒 Files selected for processing (3)
  • .gitattributes
  • docs/assets/examples/mont-blanc-terrain-tiles/9-531-386.terrain
  • test/examples/render-3d-tiles-terrain-source.html

Comment thread test/examples/render-3d-tiles-terrain-source.html Outdated
Comment thread test/examples/render-3d-tiles-terrain-source.html Outdated
@CommanderStorm
CommanderStorm marked this pull request as draft July 19, 2026 10:33
…andler

Per review: findCoveringQMTiles returns intersecting tiles from every
zoom (deepest first) so lower-resolution parents fill gaps in patchy
child coverage, and the protocol handler threads its AbortController
signal through the tile fetch and rasterization loop.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@clement-igonet
clement-igonet marked this pull request as ready for review July 19, 2026 14:46
@clement-igonet
clement-igonet marked this pull request as draft July 19, 2026 15:00
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.

2 participants