Visitar URL original
fix(core): rotate GlobeView like a ball through poles by charlieforward9 · Pull Request #10598 · visgl/deck.gl · GitHub
Skip to content

fix(core): rotate GlobeView like a ball through poles - #10598

Merged
charlieforward9 merged 29 commits into
masterfrom
codex/globe-pole-zoom-stability
Aug 31, 2026
Merged

charlieforward9 merged 29 commits into
masterfrom
codex/globe-pole-zoom-stability

Conversation

@charlieforward9

@charlieforward9 charlieforward9 commented Aug 26, 2026 •

Copy link
Copy Markdown
Member
Screen.Recording.2026-08-26.at.2.40.00.PM.mov

Goals

  • make GlobeView interaction behave like rotating a physical ball, including when the initial bearing is 0
  • keep pointer-anchored zoom smooth and consistent at the equator and near either pole
  • preserve shared controller configuration instead of adding globe-only interaction paths to the base controller

Changes

  • rotate camera position and up together as one rigid frame, then derive longitude, latitude, and bearing from the result
  • let normal drag cross either pole; bearing evolves naturally instead of implicitly locking north up at bearing 0
  • spin inertia around one fixed sphere axis so position and orientation remain coherent through poles and across the antimeridian
  • make pointer correction depend on screen-space distance from the globe limb, with a smooth release for edge and off-globe anchors
  • keep continuous wheel and pinch gestures on one coherent pointer-anchor contract
  • keep zoomAround: 'center' scale-only, without camera steering
  • use the existing shared maxBounds option for explicit latitude limits; no globe-specific maxLatitude API is added
  • make the globe test app Reset cancel active inertia and restore longitude, latitude, zoom, bearing, and pitch
  • document the physical-ball behavior and add drag, wheel, smooth-wheel, pinch, free-bearing, equivalent-bearing, and polar-maxBounds regressions

Validation

Current pushed head: 78d360d272

  • feat(core): support pointer-anchored zoom in GlobeView #10385 landed on master as 8126bb90f1
  • retargeted this PR to master and merged the landed base with a normal merge commit
  • resolved the squash-history conflicts semantically; the resolved tree matches the previously tested fix(core): rotate GlobeView like a ball through poles #10598 head exactly
  • git diff --check upstream/master...HEAD
  • yarn lint
  • focused Vitest, headless project: 102/102 on the refreshed head
  • the previous identical tree passed yarn build, yarn test-website, focused headless/browser suites, and mobile/browser stress
  • all review threads are resolved; fresh GitHub checks are running on the refreshed head

Stack

Replace the `log.warn('around not supported in GlobeView')` no-op
with real spherical anchoring, mirroring the existing planar branch:
- `initializeProps`: when the start viewport is a GlobeViewport and the
  screen anchor falls on the globe (`isPointOnGlobe`), unproject it to
  lng/lat and stash it as `aroundLngLat`.
- `interpolateProps`: each frame, call `panByGlobeAnchor(aroundLngLat,
  lerp(start.around, end.around, t))` so the geographic point stays
  pinned under the anchor screen point during the transition.

This makes the `_onDoubleClick` zoom transition (`_getTransitionProps
({around: pos})`) actually anchor on GlobeView. Previously the warn
fired and the LERP ran without anchor maintenance, which read as a
center-anchored zoom-in regardless of where the user tapped.

Tests cover the on-globe anchored path and the off-globe fall-through.
- Consolidate stray imports at the top of the file.
- Document the two GLOBE_ZOOM_ANCHOR_* constants so the empirical
  damping behavior (start damping at 0.75 of the limb, never below
  35% strength) is self-explanatory.
- Add a JSDoc to _getRayToGlobe explaining it as the shared ray/sphere
  math helper for unproject + isPointOnGlobe + panByGlobeAnchor.
…pout)

Per #10307 review: zoomAround is a config option that always needs a value,
unlike the transient gesture anchors guarded the same way. The !== undefined
guard let a partial-props / HMR reconstruction drop the key, so
_shouldZoomAroundPointer() saw undefined and silently reverted to center zoom.
…ared-zoom

# Conflicts:
#	docs/api-reference/core/globe-controller.md
#	modules/core/src/controllers/controller.ts
#	test/modules/core/controllers/controllers.spec.ts
# Conflicts:
#	test/modules/core/controllers/controllers.spec.ts
@greptile-apps

greptile-apps Bot commented Aug 26, 2026 •

Copy link
Copy Markdown

Greptile Summary

The PR changes GlobeView interaction to rotate camera position and orientation as a rigid frame, allowing physical-ball movement through the poles while preserving pointer-anchored zoom behavior.

  • Reworks drag and inertia around spherical rotation axes.
  • Adds smoothly damped pointer anchoring near and beyond the globe limb.
  • Applies shared maxBounds constraints and expands interaction regression coverage.
  • Updates GlobeView documentation and the globe test application.

Confidence Score: 5/5

The PR appears safe to merge because no blocking failure remains in the eligible follow-up review scope.

No blocking failure remains.

Important Files Changed

Filename Overview
modules/core/src/controllers/globe-controller.ts Replaces north-up pan special cases with rigid-frame drag, anchored zoom correction, fixed-axis inertia, and shared bounds enforcement.
modules/core/src/viewports/globe-utils.ts Adds camera-frame matching rotation and supports coherent position, up-vector, bearing, and inertia interpolation through poles.
modules/core/src/viewports/globe-viewport.ts Smoothly attenuates pointer-anchor strength near the globe limb and refines north-up zoom correction behavior.
test/apps/globe/app.js Makes reset restore the complete initial camera state and cancel active transitions.
test/modules/core/controllers/controllers.spec.ts Expands controller coverage for rigid globe rotation and continuous gesture behavior.
test/modules/core/controllers/view-states.spec.ts Adds regressions for pole crossing, equivalent bearings, pointer anchoring, and polar maxBounds constraints.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Pointer drag or zoom gesture] --> B[Capture geographic and screen anchor]
  B --> C[Build camera frame]
  C --> D[Rotate position and up vector together]
  D --> E[Derive longitude latitude and bearing]
  E --> F[Apply zoom and maxBounds constraints]
  F --> G[Render coherent GlobeView state]
  A --> H[Pan history]
  H --> I[Derive fixed inertia axis]
  I --> D
Loading

Reviews (7): Last reviewed commit: "Merge remote-tracking branch 'upstream/m..." | Re-trigger Greptile

@coveralls

coveralls commented Aug 26, 2026 •

Copy link
Copy Markdown

Coverage Status

No base build to compare — codex/globe-pole-zoom-stability into master

@charlieforward9 charlieforward9 changed the title fix(core): stabilize GlobeView zoom near poles fix(core): rotate GlobeView like a ball during pointer zoom Aug 26, 2026
@charlieforward9

Copy link
Copy Markdown
Member Author

Refreshed this onto the current #10385 head (4ff4aa4f) with a normal merge commit, no history rewrite.

Fresh CI is green on 7f7c8d1b, Greptile is 5/5 with no blocking finding, and the exact-head dev server passed wheel + continuous-pinch pole stress in both hemispheres. I also verified all four live control combinations: Globe/Map × Pointer/Center.

This is ready to land immediately after #10385. Once #10385 merges, the final stack cleanup is to merge fresh master here and retarget this PR to master.

@charlieforward9 charlieforward9 changed the title fix(core): rotate GlobeView like a ball during pointer zoom fix(core): rotate GlobeView like a ball through poles Aug 30, 2026
Base automatically changed from codex/globe-anchored-zoom to master August 31, 2026 01:47
…zoom-stability

# Conflicts:
#	modules/core/src/controllers/globe-controller.ts
#	modules/core/src/viewports/globe-viewport.ts
#	test/modules/core/controllers/controllers.spec.ts
@charlieforward9
charlieforward9 merged commit 93f0fe0 into master Aug 31, 2026
7 checks passed
@charlieforward9
charlieforward9 deleted the codex/globe-pole-zoom-stability branch August 31, 2026 02:05
- `minPitch` (number, optional) - min pitch angle. Default `0`.

When `bearing` is `0` (the default), north is always kept pointing up and the globe behaves like a traditional desk globe — horizontal drag changes longitude, vertical drag changes latitude, and the polar axis stays fixed. When the user changes the bearing (via shift+drag or right-click drag), the globe enters free rotation mode where bearing evolves naturally to avoid orientation discontinuities near the poles.
The globe behaves like a physical ball. Dragging and pointer-anchored zoom rotate the full camera frame, so an initial `bearing` of `0` does not lock north up: `bearing` evolves naturally as the camera crosses a pole. This avoids orientation discontinuities and keeps interaction consistent across latitudes. Use `zoomAround: 'center'` to zoom without steering the camera frame.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@charlieforward9 @Pessimistress I'm not convinced about this behavior. The function of maintaining north up was deliberately added and matches what Maplibre does.

This change makes the controls be "Trackball controls", which is a different thing. For a globe it is desirable to keep north up as that is what people expect, especially once they zoom in

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

OK so you've put my comment into Codex and it has spat out yet another PR. My original rotateFrame has a lockBearing to handle this and worked. Now it is dead code which was never cleaned up and instead an AI has piled a load of new changes on top, did you read them before posting it?

@chrisgervang

Copy link
Copy Markdown
Collaborator

This PR looks prematurely merged. While it had one approval, it had comments that weren't addressed and an alternative PR too.

Any PR that changes default behavior, as this one does, needs to reach consensus - not just approval.

I recommend reverting in the short term and reopening - and, having a discussion with the maintainers on this topic at a community meeting

@charlieforward9

charlieforward9 commented Sep 8, 2026 •

Copy link
Copy Markdown
Member Author

Agreed - apologies for jumping the gun.

I was testing an automation with aggressive permissions and it let this one rip through the usual process after getting approval from X.

Ive since paused it and will be more careful about automating these things.

@chrisgervang @felixpalmer

charlieforward9 added a commit that referenced this pull request Sep 28, 2026
…" (#10713)

This reverts commit 93f0fe0.

Restore the original north-up globe navigation while alternative navigation modes await maintainer consensus. Preserve subsequent release-note changes.

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
chrisgervang pushed a commit that referenced this pull request Oct 22, 2026
…" (#10713)

This reverts commit 93f0fe0.

Restore the original north-up globe navigation while alternative navigation modes await maintainer consensus. Preserve subsequent release-note changes.

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
(cherry picked from commit c62e58e)
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.

5 participants