Skip to content

GeoMap: continuous drape terrain design - one heightfield, patches as views, no holes or cliffs ever #14823

Description

@DonLakeFlyer

Problem

The GeoMap 3D terrain surface can currently show holes and cliffs that appear and later fill in: flat-zero patches rendered beside real-height neighbors (cliff at the shared edge), pending patches suppressed or covered by retiring predecessors (holes when that hiding has a gap), and failed fetches degrading to flat ground next to lifted terrain. This is wrong as a product experience — partial data should never look broken.

The root cause is architectural: heights are per-patch independent facts. Each patch renders whatever it personally received (or flat zero), and continuity between neighbors is nobody's responsibility. The covered/retiring/degraded machinery exists to hide the discontinuities that model inevitably produces, and every gap in the hiding is visible as a cliff or hole.

Design principle

The map is always a continuous drape, regardless of what data is or isn't available.

  • The surface starts fully draped at zero height.
  • As terrain data becomes available, the carpet lifts up in that region.
  • Where data is missing (not yet fetched, fetch failed, coarser LOD), the surface renders the best available estimate, and edges always match the surrounding heights — never a cliff, never a hole.

Architecture: one heightfield, patches are views

Invert the data model: there is one continuous heightfield; patch meshes are views into it, never owners of private height data.

HeightField (new)

  • Owns the current best estimate of terrain height everywhere: real data where delivered, ancestor-interpolated estimates where only coarser data exists, zero where nothing is known.
  • Continuous by construction — there is no "missing" region, only coarser-estimate regions.
  • Backed by the slippy elevation pyramid (GeoMap: client-side slippy elevation tile pyramid - zoom-level terrain queries with derived-tile cache #14820): pyramid tiles are the storage, ancestor seeding is the estimate mechanism. These are one system — the pyramid is the data layer, the field is its rendering contract.

Patch meshing

  • Patches sample the field at their vertex world positions. Two patches sharing an edge sample identical positions → identical heights → edges match structurally, not via suppression logic.
  • Cross-LOD edges use the standard stitching rule: fine-edge vertices adjacent to a coarser neighbor are constrained to the coarse edge's interpolation (eliminates T-junction cracks).

Data arrival

  • A delivery updates a region of the field → affected patches (plus edge-adjacent neighbors) re-sample and re-mesh.
  • The field eases toward new data (~300 ms) so the carpet visibly lifts; because the animation lives in the field, adjacent patches lift coherently — no transient edge mismatch.

Failure handling

  • "Degraded" ceases to exist as a state: a failed fetch simply means the region keeps its current estimate (ancestor data or zero). A later retry improves it. No flat-zero cliff is possible.

What this eliminates

  • The covered/z-fight suppression for pending patches (they render the field estimate, which matches any cover)
  • Most retiring-cover height semantics (imagery fallback remains a separate, existing mechanism)
  • The degraded-patch special case and its retry-ladder visual consequences
  • The entire bug class "hole/cliff that fills in later"

Replaced by one invariant, testable in one line: adjacent rendered edge vertices are always equal.

Relationship to existing work

Suggested phases

  1. Design doc: field data structure (pyramid-tile sampling + interpolation rules), cross-LOD edge stitching rule, dirty-region → re-mesh flow, easing model, migration path from the current per-patch delivery.
  2. Field + re-sampling: introduce HeightField over the existing height sources; patches sample it; delete covered/degraded height logic. Invariant test: edge-vertex equality across all resident patch pairs, under churn and failure injection.
  3. Easing: temporal blend on field updates ("carpet lift").
  4. Pyramid integration (GeoMap: client-side slippy elevation tile pyramid - zoom-level terrain queries with derived-tile cache #14820): persistent estimates across sessions.

Acceptance criteria

  • From cold start over any terrain, the surface is never anything but a continuous sheet: starts flat, lifts as data arrives.
  • Kill the network mid-load: surface remains continuous (partially lifted), no cliffs at data boundaries.
  • LOD churn (zoom in/out, high-tilt orbit) never opens a hole or crack.
  • Automated: edge-vertex equality invariant holds in unit tests under slow-heights churn and injected fetch failures.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions