Camera Local-Up Near Body Surfaces

Issue: TBD Parent: Cockpit View

Problem

The cockpit camera always uses ecliptic Y-up (Three.js default (0, 1, 0)). When orbiting close to a body or landed on its surface, this feels unnatural — the horizon tilts at arbitrary angles instead of appearing level.

Solution

Smoothly blend camera.up from ecliptic Y-up to local vertical (radial direction from nearest body center) when the ship is within 1.02× the body’s radius. Fully local at 1.01× radius. Cockpit view only. The very tight transition zone ensures only landed or final-approach ships get local-up; orbiting ships always have normal camera controls.

Blend Parameters

Parameter Value
Outer threshold 1.02× body radius (~35 km for Luna, ~128 km for Earth)
Inner threshold 1.01× body radius (~17 km for Luna, ~64 km for Earth)
Interpolation Linear blend factor, slerp on direction
Ecliptic up (0, 1, 0) in Three.js
Local up Unit vector from body center to ship (Three.js coords)

Blend Factor

t = clamp((1.02 - d/R) / 0.01, 0, 1)

Where d = distance from ship to body center, R = body radius.

  • d >= 1.02Rt = 0 → ecliptic up
  • d <= 1.01Rt = 1 → local vertical
  • Between: linear interpolation

Algorithm

Each frame in cockpitExtrapolation, after updating ship position:

  1. If local-up is disabled in settings, skip (use ecliptic Y)
  2. Find the nearest body (use state.referenceBody or nearest body with radius)
  3. Compute distance from ship to body center (ICRF → Three.js coords)
  4. Compute blend factor t
  5. If t > 0:
    • Compute local-up: normalize(ship_position - body_position) in Three.js coords
    • Slerp between ecliptic up (0, 1, 0) and local-up by factor t
    • Set camera.up to the result
  6. If t == 0: set camera.up to (0, 1, 0)

Landed Ships

When landed, distance is ~1× radius, so t = 1.0 — fully local vertical. The up direction equals the surface normal, which is correct.

Precision: When landed, the local-up vector is computed directly from bodyMesh.quaternion * landedLocalOffset (Three.js space) instead of from ICRF position subtraction. This avoids a Float64 round-trip through astronomical-scale coordinates that introduces sub-pixel orientation jitter between the camera and terrain rotation.

Orbital Flight

When orbiting within the blend zone, the up direction tracks the radial direction continuously. The horizon stays visually level as the ship orbits.

Settings

New setting localUp (boolean, default: true). Appears in the Display tab of the settings window as “Local Up” checkbox.

Files Changed

  • services/web-client/src/cockpitExtrapolation.js — Compute and apply camera.up blend each frame
  • services/web-client/src/settings.js — Add localUp default
  • services/web-client/src/cockpitSettings.js — Add checkbox handler, persist, sync
  • services/web-client/index.html — Add checkbox to Display tab

Back to top

Galaxy — Kubernetes-based multiplayer space game

This site uses Just the Docs, a documentation theme for Jekyll.