9 KiB
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).
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 to0to 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 — theDENSITYreadout shows the live count, and+/-sets the baseline (the count at the default distance). - The camera pans in world space via
WASDand 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 —0makes them all tumble alike,100gives 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).