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
aon every pod wheresign(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 = 0when:- 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.85applied 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)