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.02R→t = 0→ ecliptic upd <= 1.01R→t = 1→ local vertical- Between: linear interpolation
Algorithm
Each frame in cockpitExtrapolation, after updating ship position:
- If local-up is disabled in settings, skip (use ecliptic Y)
- Find the nearest body (use
state.referenceBodyor nearest body with radius) - Compute distance from ship to body center (ICRF → Three.js coords)
- Compute blend factor
t - 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 factort - Set
camera.upto the result
- If
t == 0: setcamera.upto(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 frameservices/web-client/src/settings.js— AddlocalUpdefaultservices/web-client/src/cockpitSettings.js— Add checkbox handler, persist, syncservices/web-client/index.html— Add checkbox to Display tab