RCS Indicators

Overview

Visual indicators showing which RCS thrusters are currently firing. Ships have 8 RCS pods at hull corners, each with 3 nozzles (one per axis), for 24 total nozzles. A 24-bit bitmask computed by the physics service maps torque and translation demands to individual nozzles for visual feedback.

See also: Ships for RCS thrust/fuel specs, Tick Processor for physics model

Thruster Geometry

Pod Layout

8 pods at the corners of the ship hull bounding box. Each pod has 3 nozzles oriented along the body-frame axes (X, Y, Z). Nozzles fire outward from ship center (exhaust direction = sign of pod position on that axis).

Physics body frame: X = right, Y = up, Z = forward.

Pod Positions (Physics Body Frame)

Pod Cargo Hauler [X, Y, Z] Fast Frigate [X, Y, Z] Corner
0 [5, 5, 24] [3.5, 3.5, 6] +X +Y +Z (Stbd-Top-Fwd)
1 [-5, 5, 24] [-3.5, 3.5, 6] -X +Y +Z (Port-Top-Fwd)
2 [5, -5, 24] [3.5, -3.5, 6] +X -Y +Z (Stbd-Bot-Fwd)
3 [-5, -5, 24] [-3.5, -3.5, 6] -X -Y +Z (Port-Bot-Fwd)
4 [5, 5, -24] [3.5, 3.5, -6] +X +Y -Z (Stbd-Top-Aft)
5 [-5, 5, -24] [-3.5, 3.5, -6] -X +Y -Z (Port-Top-Aft)
6 [5, -5, -24] [3.5, -3.5, -6] +X -Y -Z (Stbd-Bot-Aft)
7 [-5, -5, -24] [-3.5, -3.5, -6] -X -Y -Z (Port-Bot-Aft)

Bit Layout

bit = pod_index * 3 + nozzle_offset

Where nozzle_offset: 0 = X-axis nozzle, 1 = Y-axis nozzle, 2 = Z-axis nozzle.

Bits 0-23 in a uint32 field rcs_firing.

Bitmask Computation

Computed in physics service after attitude control and translation processing. Visual only — does not affect physics forces (forces are already computed by existing RCS systems).

Translation Bits

For a translation demand along axis a with sign d:

  • Fire nozzle a on every pod where sign(pod_pos[a]) * d < 0
  • This means the exhaust pushes the ship in the demanded direction (reaction force)
  • Each axis activates exactly 4 nozzles (the 4 pods on the opposite side)

Example: Translation +X (rightward) fires X-nozzles (offset 0) on pods with negative X position: pods 1, 3, 5, 7 → bits 3, 9, 15, 21.

Rotation Bits

For RCS torque demand (rotation only, excluding reaction wheel torque):

  • For each nozzle, precompute its torque contribution: cross(pod_pos, -nozzle_direction)
    • nozzle_direction = unit vector along the nozzle’s axis, with sign matching the pod position sign on that axis (exhaust fires outward)
  • Fire nozzle if dot(torque_contribution, rcs_torque_demand) > 0

Combined

rcs_firing = translation_bits | rotation_bits

No-Fire Conditions

  • rcs_firing = 0 when:
    • No attitude control active and no manual rotation input and no translation input
    • Ship has no fuel (fuel <= 0)

Wire Format

Proto

uint32 rcs_firing = 19 in ShipState message (all 6 proto copies).

Redis

rcs_firing integer field in ship:{id} hash.

WebSocket

rcs_firing integer in ship state dicts (own ship and other ships).

Visual Rendering (Web Client)

Pod Housing

  • BoxGeometry at each pod position (physics → model transform applied)
  • Cargo Hauler: 1.5m cube, Fast Frigate: 0.8m cube
  • Material: dark metallic (color 0x444444, metalness 0.8, roughness 0.3)

Nozzle Cones

  • 3 ConeGeometry per pod, protruding outward from ship center along each axis
  • Cargo Hauler: height 1.0m, radius 0.3m. Fast Frigate: height 0.6m, radius 0.2m
  • Material: darker metallic (color 0x333333, metalness 0.9, roughness 0.2)

Exhaust Plumes

  • 24 additive-blended cone meshes (one per nozzle), hidden by default
  • Color: orange-yellow 0xffaa44 (distinct from blue main engine plume)
  • Blending: THREE.AdditiveBlending, transparent: true, opacity: 0.6, toneMapped: false, depthWrite: false
  • Cargo Hauler: 3m length, 0.6m radius. Fast Frigate: 1.5m length, 0.4m radius
  • Plumes indexed by bit number in rcsGroup.userData.plumes[0..23]
  • Visibility: plumes[bit].visible = (rcs_firing & (1 << bit)) !== 0

Animation

  • Visible plumes flicker: opacity = sin(now * 20) * 0.15 + 0.85 applied each frame
  • Plume orientation matches nozzle direction (outward from ship center)

Coordinate Transform

Physics body frame (X=right, Y=up, Z=forward) → Three.js model space (ship +Y=forward):

  • (x, y, z)(x, z, -y)

Back to top

Galaxy — Kubernetes-based multiplayer space game

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