Skip to content

feat(core): GlobeView pitch, bearing, and cursor-anchored zoom#10249

Open
charlieforward9 wants to merge 2 commits intomasterfrom
cr/feat/globe-camera
Open

feat(core): GlobeView pitch, bearing, and cursor-anchored zoom#10249
charlieforward9 wants to merge 2 commits intomasterfrom
cr/feat/globe-camera

Conversation

@charlieforward9
Copy link
Copy Markdown
Collaborator

@charlieforward9 charlieforward9 commented Apr 19, 2026

Summary

Brings GlobeView to feature parity with MapView for camera interaction. Three related changes:

  • Pitch and bearing: GlobeView now accepts pitch, bearing, minPitch, maxPitch view-state props. GlobeViewport composes them into a lookAt-based view matrix that keeps the target lng/lat fixed at screen center through tilt and rotation — matching the Google Maps/Earth interaction model. GlobeController wires up dragRotate and touchRotate and enforces the pitch constraints.
  • Cursor-anchored zoom: scroll-wheel zoom now targets the mouse cursor (consistent with MapView) instead of always zooming toward screen center.
  • Pan consistency with MapView: GlobeState inherits pan from MapState, so the grabbed lng/lat stays under the cursor through a drag. The previous delta-pan produced the wrong on-screen speed at zoom > 12 where WebMercatorViewport takes over rendering.

Includes a ray/sphere-miss fallback in unproject so off-globe interactions don't return null.

Why

Pitch + bearing + zoom-toward-cursor are the camera affordances users already expect from MapView. Without them, GlobeView-based apps can't offer the same 3D tilt/orbit UX that MapView has supported for years — which makes it hard to build a projection-toggling app where the camera feels the same on both projections.

Test plan

  • New unit tests in test/modules/core/viewports/globe-viewport.spec.ts for pitch/bearing viewport math
  • New unit tests in test/modules/core/controllers/view-states.spec.ts for pitch/bearing transitions
  • test/apps/globe/app.js updated with sliders to exercise the new view-state props interactively

Companion PRs

This PR is standalone. Two follow-up PRs build on it to bring terrain rendering to GlobeView:

Add camera tilt (pitch) and rotation (bearing) to GlobeView, matching the
Google Maps/Earth interaction model. Uses a lookAt-based view matrix that
composes pitch and bearing rotations while keeping the target lng/lat at
screen center.

Scroll-wheel zoom now targets the mouse cursor position instead of screen
center (matching MapView). Pan reuses MapState's grabbed-lng/lat logic so
the point under the cursor stays under the cursor through the drag —
previously GlobeState's delta-pan produced wrong on-screen speed and
yanked the center at zoom > 12 where WebMercatorViewport takes over
rendering. Unproject for rays that miss the globe surface returns a
plausible fallback rather than null.

Changes:
- GlobeViewport: lookAt view matrix with pitch/bearing, cursor-anchored
  zoom, ray/sphere miss fallback
- GlobeController: dragRotate/touchRotate, pitch/bearing constraints,
  inherits pan from MapState
- GlobeView: pitch/bearing/minPitch/maxPitch view state props
- Tests for pitch/bearing transitions and viewport math
@charlieforward9
Copy link
Copy Markdown
Collaborator Author

The test-node failure is the test/modules/react/deckgl.spec.ts > DeckGL#uncontrolled view state flake introduced in #10240 — master itself fails the same way (run 24594004664). Not caused by this PR. test-python and test-website pass.

Happy to rebase once #10240's follow-up fix lands.

Comment thread modules/core/src/viewports/globe-viewport.ts
Comment thread modules/core/src/viewports/globe-viewport.ts
Comment thread modules/core/src/viewports/globe-viewport.ts
@charlieforward9
Copy link
Copy Markdown
Collaborator Author

charlieforward9 commented Apr 21, 2026

@felixpalmer thank you for the review - I agree with your reinstatement and pan behavior

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.

[Bug] Globe example not displaying as expected Tracker: GlobeView graduation

2 participants