Skip to content

ADR-049 — Tiangong module pickability and scene graph

Status · Accepted Date · 2026-05-07 Closes · RFC-014 (with ADR-048, ADR-050) TA anchor · §components Related · ADR-048, ADR-041 (the ISS analogue), PRD-011

Context

RFC-014 OQ-2 + OQ-5 asked how to balance pick granularity vs draw calls for Tiangong. PRD-011 / GH-50 require 6 pick targets: 3 pressurised modules (Tianhe / Wentian / Mengtian) + Chinarm + 2 visiting vehicles (Shenzhou / Tianzhou). Solar arrays are scenery in V1. The small experimental arm (RFC OQ-5 option B) is deferred.

Decision

Hybrid mesh split (RFC OQ-2 Option C)

  1. Pickable: one THREE.Mesh (or group leaf) per canonical id in tiangong-modules.json and tiangong-visitors.json, with userData.moduleId === id and userData.stationPickable === true.
  2. Non-pickable: structural geometry (truss spurs, solar wings, MLI wraps) carries userData.stationPickable === false so the raycaster walk-up filters them out.

stationPickable rename

ISS V1 used userData.issPickable. Since /tiangong reuses the same raycaster + walk-up pattern, the convention is generalised to userData.stationPickable and the same key is renamed in iss-proxy-model.ts + src/routes/iss/+page.svelte. The picking convention is now station-agnostic so a third station (e.g. a future Mir route) drops in with no protocol churn.

Highlight

OutlinePass on hover (matches /iss post-V1 — ADR-041's emissive-only V1 was upgraded). Emissive scale-pulse (1 + sin(t · 2.6) · 0.04) on the selected module when its panel is open. Unselected modules render at base scale.

Draw calls

Expect ~7 pickable meshes (3 modules + Chinarm + 2 visitors + 1 merged truss-and-radiator group) — comfortably under any mobile budget.

Consequences

Positive: Identical raycaster + selection logic across /iss and /tiangong; trivial per-mesh userData.moduleId wiring from raycast → panel.

Negative: A future CMSA / Sketchfab GLB import must preserve the four module ids (tianhe, wentian, mengtian, chinarm) and two visitor ids (shenzhou, tianzhou) on its mesh names, or carry an alias table in code.

Implementation notes

Scene traversal after buildTiangongProxyStation(): register pickables in a Map keyed by userData.moduleId for raycaster + INDEX drawer + deep-link sync. Same pattern as iss-proxy-model.ts post-rename.

Orrery — architecture documentation · MIT · No tracking