# Vectorgons A starfield simulator — except instead of stars, colorful **vector-drawn platonic solids** tumble through space toward the camera. **~165 shape types** are rendered as glowing wireframes — each spawns far away at a random size, tumbles on its own random axis, and streams past the camera before being recycled at the render-distance sphere. Solids never overlap. The shape set includes: - **Platonic solids:** tetrahedron, cube, octahedron, dodecahedron, icosahedron - **Other polyhedra:** cuboctahedron, truncated octahedron, stella octangula - **Prisms / antiprisms / bipyramids** (various base polygons) - **Many-faced solids named for their face count:** tridecahedron (13), tetradecahedron (14), pentadecahedron (15), heptadecahedron (17), octadecahedron (18), enneadecahedron (19), icosahedron (20), icositetrahedron (24), triacontahedron (30), hexacontahedron (60), and hecatohedron (100) — built from prism / bipyramid / trapezohedron families so each lands on exactly the requested number of faces - **Star polygons:** {5/2}, {6/2}, {7/2}, {7/3}, {8/3}, {9/2}, {9/4}, {12/5}, plus the **unicursal hexagram** - **Googie / atomic-age shapes** — a large set in the jet-age / space-age idiom: bowling-alley twinkles (4- and 8-point), a layered double starburst, atomic bursts with electron caps, ray sunbursts, boomerangs, kidney/amoeba blobs, concentric orbit rings, plus **30+ more truly-3-D objects**: radial **starbursts** and **sea-urchins** (6/8/12/20/32-spike, some ball-tipped), **gyroscope** orbit cages (2–6 rings), **orbital atoms** (2–6 orbits), ringed **Saturn** planets, ball-and-stick **molecules**, **diabolo** hourglasses, ray-stars, and a **Sputnik** satellite - **Symbols, signs & faces**, each in a flat **2-D** and an extruded **3-D** form: smiley, **frowny**, and **angry** faces, biohazard, peace sign, cross, question mark, exclamation point, hash/pound (`#`), dollar sign (`$`), pound sterling (`£`), and the **at sign (`@`)** - **Object iconography**, each in **2-D** and **3-D**: space invaders, UFOs, pac-man, alien heads, smoking pipes, umbrellas, and hands - **Live clocks** (analog and digital, 2-D and 3-D) that show the **actual current time** — their geometry is rebuilt every frame, so the analog hands sweep and the seven-segment digital display ticks along in real time - **Random 3-D asteroids:** lumpy convex-hull rocks generated fresh each run, with random vertex counts (≈7–26) giving each a different number of sides and level of complexity - **4-, 5- and 6-dimensional polytopes:** the 5-cell, **tesseract (hypercube)**, penteract (5-cube), 6-cube, 16-cell, 5- and 6-orthoplexes, the 24-cell, and the 5-simplex. These are rotated *in their own dimension* and perspective-projected down to 3D every frame, so they morph (the classic "cube-within-a-cube" unfolding) while also tumbling in 3D. ## Build & run Requires a C compiler, GLFW3, and GLU (all detected via `pkg-config`). ```sh make ./vectorgons # or: make run ``` ## Settings persistence Your settings are saved automatically on exit to `~/.vectorgons` (a plain `key=value` text file) and reloaded on the next launch as the new defaults — so the speed, tumble, render distance, density, colors, glow, fullscreen, etc. you last used carry over. Delete the file to return to the built-in defaults; it's safe to hand-edit (values are range-clamped on load). ## On-screen display A vector-drawn OSD (top-left) lists every setting and its key binding. It stays fully visible for **10 seconds** after your last keypress, then fades out over a few seconds. Press any key to bring it back. ## Controls | Setting | Keys | Notes | |---------------------|-----------------|------------------------------------------| | Move camera | `W`/`A`/`S`/`D` | Pan the camera up / left / down / right (hold to fly) | | Rotate camera | `←`/`→`/`↑`/`↓` | Yaw / pitch the camera view (hold to turn) | | Approach speed | `PgUp`/`PgDn` | How fast solids fly at you; `PgDn` past 0 reverses (fly backward) | | Tumble rate | `Q` / `E` | Base rotation speed | | Tumble variance | `T` / `Y` | Spread of tumble speeds: low = uniform, high = a very wide range (responds live) | | Render distance | `Z` / `X` | Radius of the field sphere / far plane (40–1520; hold to ramp) | | Density | `+` / `-` | Baseline number of solids (scales up with render distance; readout shows the live count) | | Size min | `U` / `J` | Minimum random solid size | | Size max | `I` / `K` | Maximum random solid size | | Hue | `[` / `]` | Base color | | Hue cycle | `C` / `V` | Continuously cycle through all hues (0 = off); all objects sweep the spectrum | | Color mode | `M` | Toggle **single-hue** ⇄ **multicolor** | | Glow | `O` / `L` | CRT glow / light bleed around vectors | | Flicker | `G` / `H` | Vector flicker intensity | | Shapes | `N` | Toggle random ⇄ cycling shape spawns | | Fullscreen | `F` or `F11` | Toggle fullscreen | | Pause | `Space` | | | Quit | `Esc` | | ## Color modes - **Single hue:** every solid uses the hue set with `[` / `]`. - **Multicolor:** each solid gets its own hue (its base offset plus the global hue, so `[` / `]` rotates the whole palette). - **Hue cycle (`C` / `V`):** continuously advances the base hue over time (up to ~120°/sec). In single-hue mode every object sweeps through the spectrum together; in multicolor mode the whole palette rotates. Set to `0` to stop. ## How it works - **Geometry** comes from an N-dimensional polytope engine (3–6 dimensions). For regular figures, edges are derived automatically by connecting every vertex pair at the shared minimum distance; parametric families (prisms, stars, ...) set edges explicitly. - **Higher-dimensional shapes** keep their full 4/5/6-D coordinates and are rotated in their own dimension (driven by the tumble angle plus a per-body phase), then perspective-projected down to 3D each frame and renormalized to the unit sphere — which also keeps the no-overlap bound intact. - **Asteroids** scatter random points over a sphere at jittered radii and wire them up as a brute-force convex hull, so each rock is a unique faceted blob. - **The field is a sphere** of radius *render distance* centered on the camera. Bodies stream along −Z (or +Z when speed is negative) and, once they leave the sphere, are recycled back to the **render-distance shell** on the incoming side — so objects always appear far away and approach, never popping in close. They ease in over a fraction of a second at the shell. The initial fill spreads bodies through the volume so the field starts populated. Because culling is purely radial, the camera can yaw/pitch a full 360° without revealing an edge. - **Render distance** (`Z`/`X`, 40–1520) sets the sphere radius and the perspective far plane. The **active body count scales with it**, so a deeper field simply holds proportionally more shapes (constant near-field density) instead of thinning out to empty space — the `DENSITY` readout shows the live count, and `+`/`-` sets the baseline (the count at the default distance). - **The camera** pans in world space via `WASD` and yaws/pitches via the arrow keys (both polled per frame so movement is smooth and frame-rate independent); the rest of the field streams past it. - **No overlap:** each solid's bounding-sphere radius equals its size, and spawn positions are rejection-sampled so no two spheres intersect (with a margin). Because every solid translates by the same amount each frame, non-overlap at spawn is preserved for the body's whole flight. - **Tumble variance** is applied live as a log-uniform spread (`spin = 4^(seed · variance)`), so changing it re-spreads every solid's rotation rate instantly — `0` makes them all tumble alike, `100` gives a very wide range. - **CRT glow** wraps each sharp vector in a soft phosphor mist: many faint additive width layers fade outward into a halo, and a few faint enlarged ghost copies bloom that glow into a larger volume than the hardware line-width cap (~10px) could reach on its own. The crisp core is drawn last so the vector stays sharp; the glow setting scales the mist's spread and brightness. - **Flicker** randomly dips each solid's brightness per frame, scaled by the flicker setting. - **Rendering** uses legacy OpenGL immediate mode (`GL_LINES`) with additive blending, MSAA, and line smoothing; depth-based fading brightens and thickens solids as they approach. The OSD uses a self-contained vector stroke font (no font dependencies).