fix(GeoMap): one continuous heightfield so patches never show cliffs or holes - #14860
Conversation
bb749e7 to
b36a834
Compare
…or holes Every rendered patch now samples the same continuous terrain heightfield instead of fetching its own per-patch height grid, so neighboring patches can never disagree about the terrain they share - no more cliffs at patch boundaries and no holes while data loads. - HeightField: best-estimate height everywhere by construction - real data where a tile is stored, ancestor-interpolated estimate where only coarser data exists. Coincident vertices of neighboring patches compute bit-identical heights regardless of which patch meshes them. - ElevationTilePyramid: bounded in-memory working set of decoded elevation tiles (LRU past 128 tiles, ~32MB) serving queries from the tile itself or its nearest stored ancestor with the sub-window to sample. - TerrariumTileFetcher: cache-first fetcher over the AWS Open Data Terrain Tiles (terrarium encoding) - one slippy PNG tile per patch at every zoom, network fallback on cache miss with write-back. Replaces the fixed resolution Copernicus pipeline (TerrainHeightSource removed) and its flat floor / blend band. - Patch skirts scale with the coarsest constraining neighbor LOD delta to hide seams against coarser neighbors. Fixes mavlink#14823
b36a834 to
eb3ebd2
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 50 out of 50 changed files in this pull request and generated no new comments.
Suppressed comments (3)
src/GeoMap/SurfaceModel.cc:171
- During capped refinement, this retains the old ancestor while newly added descendants are already rendered (
Patch.readyis always true andcoveredis always false). On the initially flat field those meshes are coplanar, and with terrain their different tessellations intersect, so multiple event-loop passes can show z-fighting even though there is no coverage hole. Keep one layer hidden until the full replacement coverage is resident, or otherwise remove/split the overlapping portion of the old patch before exposing descendants.
if ((_removalsThisPass >= kMaxPatchRemovalsPerUpdate) || overlapsMissing(it.key())) {
_removalsDeferred = true; // stays resident one more pass; follow-up finishes the cull
.clang-format:63
- This reverses the repository’s documented include order:
CODING_STYLE.md:72-78requires system/STL headers before Qt headers. With this configuration, clang-format will keep producing Qt-first blocks (as seen throughout this PR) and create repo-wide formatting churn. Keep the system category at priority 1 and Qt at priority 2.
- Regex: '^<Q.*>' # Qt headers
Priority: 1
- Regex: '^<[a-z].*>' # System/STL headers
CaseSensitive: true
Priority: 2
src/GeoMap/SurfaceModel.cc:126
- On an empty model this cap adds only two disjoint leaves from the fully refined
desiredset; there is no resident ancestor to cover the remainingmissingRects. The model therefore exposes an incomplete sheet for several queued passes on cold start (and after a non-overlapping camera jump), so visible holes remain independent of height availability. Seed a coarse cover first and refine it incrementally, or allow the initial pass to establish complete coverage before enforcing the delegate-add budget.
if (adds >= kMaxPatchAddsPerUpdate) {
_addsDeferred = true;
continue;
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #14860 +/- ##
==========================================
+ Coverage 25.47% 33.76% +8.29%
==========================================
Files 769 933 +164
Lines 65912 84615 +18703
Branches 30495 39120 +8625
==========================================
+ Hits 16788 28574 +11786
+ Misses 37285 36838 -447
- Partials 11839 19203 +7364
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 616 files with indirect coverage changes Continue to review full report in Codecov by Harness.
🚀 New features to boost your workflow:
|
Build ResultsPlatform Status
All builds passed. Pre-commit
Pre-commit hooks: 2 passed, 75 failed, 7 skipped. Test Resultslinux-coverage-integration: 43 passed, 0 skipped Code Coverage
Artifact Sizes
Updated: 2026-08-13 20:56:08 UTC • Commit: eb3ebd2 • Triggered by: Android |
Fixes #14823
What this does
Every rendered patch now samples the same continuous terrain heightfield instead of fetching its own per-patch height grid, so neighboring patches can never disagree about the terrain they share — no more cliffs at patch boundaries and no holes while data loads.
TerrainHeightSourceremoved) along with its flat floor / blend band.Follow-ups tracked separately: #14858 (tile cache capacity, transient skirt sizing), #14859 (retry of failed elevation fetches for resident patches).
Test coverage (local)
All 16 GeoMap test suites, measured with gcovr on an instrumented (-O0) build:
Module totals: lines 89.5% (2375/2654), functions 90.6% (326/360), branches 52.0%
The SurfacePatchModel gap is the QQuick3D delegate/texture machinery that only executes under a live render loop; the remaining misses elsewhere are defensive branches (e.g. map-engine-unavailable, cache-worker returning a null tile) that can't be arranged deterministically in the test environment.