Skip to content

WIP: experiment with Google Maps 3D overlay support#10401

Draft
charlieforward9 wants to merge 23 commits into
visgl:masterfrom
NEW-HEAT:codex/google-maps-3d-overlay-prototype
Draft

WIP: experiment with Google Maps 3D overlay support#10401
charlieforward9 wants to merge 23 commits into
visgl:masterfrom
NEW-HEAT:codex/google-maps-3d-overlay-prototype

Conversation

@charlieforward9

Copy link
Copy Markdown
Member

Summary

  • extend GoogleMapsOverlay#setMap to recognize gmp-map-3d / Map3DElement alongside google.maps.Map
  • add an experimental Map3D adapter that derives Deck view state from center, range, heading, tilt, and fov
  • install a passive Map3D WebGL context capture hook; if Google internals cannot be captured, warn and fall back to a non-interleaved Deck overlay instead of touching GL
  • forward basic DOM pointer/click events and listen to Map3D camera-change events for redraws
  • add a Map3D mock and focused overlay/camera tests

Notes

  • This is intentionally draft/prototype scope.
  • No Google API keys or exploratory React example are included.
  • The interleaved path only uses already-captured Map3D contexts; it does not call getContext() on an internal Google canvas just to probe, because that can create/corrupt a context.
  • This creates the deck.gl surface needed before landing polished editable-layers / manual connect UX on Google Map3D.

Test Plan

  • yarn vitest run --project headless test/modules/google-maps/google-maps-overlay.spec.ts
  • ./node_modules/.bin/eslint modules/google-maps/src/index.ts modules/google-maps/src/google-maps-overlay.ts modules/google-maps/src/utils.ts
  • commit hook: module/test/example lint+prettier and node smoke tests passed; existing repo lint warnings remain warnings

@charlieforward9

Copy link
Copy Markdown
Member Author

Prototype follow-up from the local Map3D route demo:

  • The non-interleaved DOM Deck fallback is visibly camera-approximate on Map3DElement; route paths can drift while panning/tilting because we do not have Google's Map3D terrain/projection surface.
  • The standalone demo now treats native Polyline3DElement with CLAMP_TO_GROUND as the route source of truth. Deck layers are off by default and exposed only as an explicit debug overlay.
  • The overlay warning now names this: fallback rendering is approximate and should not be used for terrain-locked Map3D geometry.
  • Added camera altitude handling/tests using cameraPosition where Map3D exposes it, but that still does not replace a shared GL/projection/depth path for polished editable paths/polygons.

@charlieforward9

Copy link
Copy Markdown
Member Author

Second follow-up: added a native Map3D editing demo shell on top of the drift finding.

What the demo now does:

  • Keeps authoritative geometry in native Map3D elements, not the approximate Deck DOM fallback.
  • Supports local point/path/polygon editing state.
  • Uses Map3D gmp-click positions to append points and insert path/polygon vertices.
  • Uses native 3D markers as selectable vertex handles.
  • Exports the current editor state as GeoJSON.
  • Leaves Deck as an explicit debug overlay only.

Current limitation: Google Maps 3D exposes click positions and native 3D geometry, but no documented draggable vertex/path editing API. So this is the first supportable adapter direction, not yet the polished editable-layers replacement.

@charlieforward9

Copy link
Copy Markdown
Member Author

Third follow-up: split the native editor shell into a supportable adapter boundary.

New shape:

  • map3d-editor-state.js owns pure edit operations: mode, append, nearest-segment insert, select, delete, undo, reset, move selected, coordinate normalization, GeoJSON export.
  • map3d-native-editor.js now just adapts Map3D events/elements to that operation layer and renders native Map3D geometry/handles.
  • Added focused tests for the operation layer under test/modules/google-maps/map3d-editor-state.spec.ts.
  • Added a supportable vertex move path: select a handle, click Move Selected, then the next native Map3D click repositions that vertex. This avoids claiming draggable handles before Google exposes a documented drag/edit API.

Verification: focused Map3D/editor tests are 18/18, example/test lint is clean for the touched surfaces, and the standalone demo builds with Vite.

@charlieforward9

Copy link
Copy Markdown
Member Author

Update after 7406654:

  • Promoted the Map3D editor operations out of the standalone demo and into @deck.gl/google-maps as typed experimental utilities. The demo now consumes the package export and the unit tests target the module source.
  • Stabilized the Map3D Deck diagnostic overlay so it no longer participates in Google Map3D depth:
    • Map3D shared-GL draw uses depthTest: false and depthMask: false.
    • getViewPropsFromMap3D keeps Deck viewport position at [0, 0, 0] instead of inheriting Map3D center altitude, avoiding visible vertical bob/drift while panning.
    • Demo Deck debug layers also opt out of depth and are labeled as screen-composited debug rather than authoritative terrain geometry.
  • Kept native Map3D editor geometry as the locked surface: path/polygon/handles use Map3D elements with CLAMP_TO_GROUND, with occluded segments enabled where supported.
  • Fixed a live demo runtime crash: current Polygon3DInteractiveElement rejects outerColor/outerWidth, so those unsupported polygon style keys were removed.

Live browser finding: in the in-app browser the real Map3D renderer did not expose a reachable canvas under gmp-map-3d; DOM inspection only found the Deck fallback canvas. The demo therefore reports DOM overlay fallback there, loads the native editor successfully, and keeps Deck debug explicitly non-authoritative.

Verification:

  • yarn vitest run --project headless test/modules/google-maps/google-maps-overlay.spec.ts test/modules/google-maps/map3d-editor-state.spec.ts
  • ./node_modules/.bin/eslint modules/google-maps/src/map-3d-editor-state.ts modules/google-maps/src/index.ts modules/google-maps/src/google-maps-overlay.ts modules/google-maps/src/utils.ts examples/website/google-map-3d-overlay-prototype/app.js examples/website/google-map-3d-overlay-prototype/map3d-native-editor.js test/modules/google-maps/google-maps-overlay.spec.ts test/modules/google-maps/map3d-editor-state.spec.ts --quiet
  • ./node_modules/.bin/tsc -b modules/core/tsconfig.json modules/google-maps/tsconfig.json --pretty false
  • ../../../node_modules/.bin/vite build --config ../../vite.config.local.mjs in examples/website/google-map-3d-overlay-prototype
  • Browser smoke at http://127.0.0.1:5173/: native Map3D editor loads, Deck debug toggles, no current polygon runtime error.

@coveralls

coveralls commented Jun 29, 2026

Copy link
Copy Markdown

Coverage Status

coverage: 82.76% (-0.4%) from 83.113% — NEW-HEAT:codex/google-maps-3d-overlay-prototype into visgl:master

@charlieforward9

Copy link
Copy Markdown
Member Author

Update after f45ee0d:

Added an explicit experimental Map3D Deck depth mode:

  • New GoogleMapsOverlay prop/type: map3DDepthMode?: "screen" | "mesh" exported from @deck.gl/google-maps.
  • Default remains screen: Deck draws as a compositor overlay and does not read/write Google Map3D depth.
  • mesh mode enables depth testing against the Map3D depth buffer when a captured shared WebGL context is available. It uses depthTest: true, depthFunc: LEQUAL, and depthMask: false, so Deck can be occluded by the Google mesh without writing into Google depth.
  • If mesh mode is requested but Map3D shared GL cannot be captured, the warning now says that mesh depth requires a captured shared Map3D WebGL context.

Demo update:

  • Added a Deck: Screen / Deck: Mesh Depth toggle next to Show Deck Debug.
  • Deck debug is now visually distinct from native Map3D geometry: screen mode is bright green, mesh-depth mode is yellow.
  • The status panel distinguishes:
    • native editor + screen-composited deck debug
    • native editor + deck mesh-depth debug
    • native editor + deck mesh-depth requested (shared WebGL unavailable)

Answer to the latest browser screenshot: that view was native Google Map3D geometry, not Deck. The button still said Show Deck Debug, and DOM inspection showed gmp-polyline-3d-interactive / gmp-polygon-3d-interactive / markers with altitude-mode="clamp-to-ground". Deck debug is only visible after toggling it on; in this browser it still runs through the DOM fallback canvas because the Google Map3D canvas is not exposed/captured.

Verification:

  • yarn vitest run --project headless test/modules/google-maps/google-maps-overlay.spec.ts test/modules/google-maps/map3d-editor-state.spec.ts
  • ./node_modules/.bin/eslint modules/google-maps/src/google-maps-overlay.ts modules/google-maps/src/index.ts examples/website/google-map-3d-overlay-prototype/app.js test/modules/google-maps/google-maps-overlay.spec.ts --quiet
  • ./node_modules/.bin/prettier --check modules/google-maps/src/google-maps-overlay.ts modules/google-maps/src/index.ts examples/website/google-map-3d-overlay-prototype/app.js test/modules/google-maps/google-maps-overlay.spec.ts
  • ./node_modules/.bin/tsc -b modules/core/tsconfig.json modules/google-maps/tsconfig.json --pretty false
  • ../../../node_modules/.bin/vite build --config ../../vite.config.local.mjs in examples/website/google-map-3d-overlay-prototype
  • Browser smoke at http://127.0.0.1:5173/: reload, toggle Deck debug, toggle mesh depth. Status reports DOM overlay fallback and deck mesh-depth requested (shared WebGL unavailable); clean post-reload console filter showed no current warn/error entries.

@charlieforward9

Copy link
Copy Markdown
Member Author

Alignment update pushed in bc2aa71e75d0b0fee4898e2c86d10d563b9cf1ff:

  • Fixed the Map3D cameraPosition zoom derivation for pitched cameras by applying the pitch cosine, matching the terrain-camera correction pattern used in the Mapbox terrain adapter. The previous branch used vertical camera height directly, which over-zoomed steep Map3D views and made Deck geometry drift off the native Map3D path.
  • Switched range fallback zoom math to the same 512-world scale used by Deck/WebMercator and the cameraPosition branch.
  • Added gmp-steadychange to the Map3D camera redraw listeners to avoid stale fallback draws after Map3D settles.
  • Removed unsupported 3D path outline style from the demo to avoid Google Maps constructor errors.

Verification: focused Map3D tests pass, targeted eslint/typecheck/prettier pass, and the local 3D demo now shows the Deck debug path aligned with the native Map3D route in both screen and mesh-depth fallback modes. The example production build is still blocked in this worktree because node_modules/@deck.gl/google-maps resolves to the sibling main checkout instead of this worktree and that target has no package dist.

@charlieforward9

Copy link
Copy Markdown
Member Author

Local demo visibility fix pushed in 420053187b82404c053eac559af5df939f853d3c:

  • The Map3D overlay prototype now defaults showDeckDebug to true, so a fresh reload immediately shows the Deck debug route instead of only native Map3D geometry.
  • The example Vite config now aliases @deck.gl/core, @deck.gl/google-maps, and @deck.gl/layers to this worktree's source modules. This avoids the local cross-worktree node_modules symlink resolving to the sibling main checkout without dist, which was why the dev server appeared to serve but the page had no Deck layer.

Local server is running at http://127.0.0.1:5173/ with the NEWHEAT Google Maps key mapped into GoogleMapsAPIKey. Focused eslint/prettier passed for the changed demo files; commit hook also passed with existing repo warnings only.

@charlieforward9

Copy link
Copy Markdown
Member Author

Map3D movement follow-up pushed in 980bd66c634bcfcd9faf519a7e0e89069523cb3b:

  • Restored the demo default to the native Map3D clamp-to-ground editor surface. That is the terrain-draped path/polygon/point view and should not show the Deck fallback z drift on first load.
  • Kept Deck debug as an explicit opt-in for adapter comparison.
  • Updated the Map3D camera listener so gmp-steadychange with isSteady: false starts a requestAnimationFrame redraw loop, then cancels it on isSteady: true. This reduces fallback Deck lag while Google Map3D is actively moving the camera.
  • Added focused test coverage for the continuous redraw loop.

Local verification: focused Map3D tests pass (20 tests), targeted eslint/prettier/typecheck pass, and the local dev server is still running at http://127.0.0.1:5173/.

@charlieforward9

Copy link
Copy Markdown
Member Author

Demo visibility toggle follow-up pushed in 7f6e663fd633ceb5649a060eae9521e2acd38037:

  • showDeckDebug is back to true by default, so a fresh reload immediately shows the Deck debug route and the button reads Hide Deck Debug.
  • Native Map3D clamp-to-ground geometry still renders underneath for terrain comparison.

Local server is running at http://127.0.0.1:5173/; focused lint/format passed for the changed file and the commit hook passed with existing repo warnings only.

@charlieforward9

Copy link
Copy Markdown
Member Author

Tightened the draped-surface fallback in 14d363c29.\n\nWhat changed:\n- Map3D WebGL canvas capture now walks nested shadow-host chains, covering renderer canvases that are not direct children of gmp-map-3d.\n- Added a focused regression test for nested Map3D renderer canvas capture.\n- The prototype defaults back to the native Map3D clamp-to-ground editor surface and hides the screen-composited Deck fallback by default. If shared GL is unavailable, the panel now calls that out instead of letting the floating Deck canvas look like the draped route.\n\nLocal verification:\n- vitest run --project headless test/modules/google-maps/google-maps-overlay.spec.ts test/modules/google-maps/map3d-editor-state.spec.ts\n- targeted eslint/prettier\n- tsc -b modules/core/tsconfig.json modules/google-maps/tsconfig.json --pretty false\n- dev server is live again at http://127.0.0.1:5173/

@charlieforward9

Copy link
Copy Markdown
Member Author

Added f27784fd8 to stop showing the unstable Deck fallback during Map3D camera motion.\n\nThe live repro is still reporting DOM overlay fallback, so neither screen nor mesh can be trusted as a terrain-draped Deck layer there. The demo now keeps the native Map3D clamp-to-ground route/editor visible while the camera moves, pauses the Deck diagnostic during fallback camera motion, and restores it after gmp-steadychange or a short camera-event debounce. This avoids the visible z-jiggle without pretending the fallback is a true terrain-locked Deck overlay.\n\nLocal checks:\n- targeted example eslint/prettier\n- Vite HMR picked up app.js\n- dev server is still live at http://127.0.0.1:5173/

@charlieforward9

Copy link
Copy Markdown
Member Author

Added 5f676680a after live testing feedback.\n\nI backed out the hide-on-pan behavior. The Deck diagnostic now stays visible while panning/zooming even when Map3D shared GL is unavailable. The status copy now calls that path aligned deck canvas fallback instead of implying draping/interleaving. Mesh-depth still reports that it is requested but using the aligned canvas fallback when shared GL is not captured.\n\nLocal checks:\n- targeted example eslint/prettier\n- Vite HMR reloaded app.js\n- dev server is live at http://127.0.0.1:5173/

@charlieforward9

Copy link
Copy Markdown
Member Author

Added 9cbf8e978 to address the fallback pan jiggle without hiding the Deck canvas.\n\nWhat changed:\n- addMap3DCameraChangeListener now accepts redrawWhileMoving.\n- Shared Map3D GL keeps continuous redraws.\n- DOM fallback holds Deck redraws while Map3D reports non-steady camera movement, skips intermediate camera-change events, and redraws once when the camera steadies.\n- The example copy now calls this steady aligned deck canvas fallback.\n\nThis keeps the Deck diagnostic visible during pan, but stops it from chasing unsynchronized intermediate Map3D camera poses.\n\nLocal verification:\n- focused Map3D vitest suite: 22 passing\n- targeted eslint/prettier\n- tsc -b modules/core/tsconfig.json modules/google-maps/tsconfig.json --pretty false\n- dev server remains live at http://127.0.0.1:5173/

@charlieforward9

Copy link
Copy Markdown
Member Author

Added 4bccd5385 as the next pan-jiggle fix.\n\nInstead of freezing fallback redraws, DOM fallback now uses Map3D range as the zoom source while captured shared-GL mode can still use cameraPosition. The previous fallback was inheriting camera-position altitude changes during pan, which is a plausible source of the z-scale wobble. With this change, fallback redraws continuously again so the canvas follows pan, but the zoom is range-stabilized rather than terrain/camera-altitude driven.\n\nLocal verification:\n- focused Map3D/editor vitest suite: 23 passing\n- targeted eslint/prettier\n- tsc -b modules/core/tsconfig.json modules/google-maps/tsconfig.json --pretty false\n- Vite hot-reloaded the overlay/app source and the dev server remains live at http://127.0.0.1:5173/

@charlieforward9

Copy link
Copy Markdown
Member Author

Added 9b9b81e1d as the hard-stable fallback after the live repro still showed z movement.\n\nThis adds map3DFallbackMode: 'geospatial' | 'screen'. The existing geospatial fallback remains available for experimenting with approximate Map3D camera math, but the prototype now defaults to screen fallback: Deck uses an OrthographicView and cartesian pixel-space layers when shared Map3D GL is unavailable. That means no pseudo-3D projection and no z-scale jump during pan; native Map3D polyline/polygon/markers remain the authoritative geospatial locked surface.\n\nLocal verification:\n- focused Map3D/editor vitest suite: 24 passing\n- targeted eslint/prettier\n- tsc -b modules/core/tsconfig.json modules/google-maps/tsconfig.json --pretty false\n- PR head is 9b9b81e1d; dev server is live at http://127.0.0.1:5173/

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