141 lines
8.4 KiB
Markdown
141 lines
8.4 KiB
Markdown
# Vectorgons
|
||
|
||
A starfield simulator — except instead of stars, colorful **vector-drawn
|
||
platonic solids** tumble through space toward the camera.
|
||
|
||
**~110 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**, most in both flat **2-D** and **3-D** forms:
|
||
jet-age bowling-alley twinkles (4- and 8-point), a layered double starburst,
|
||
an atomic burst with electron caps, a ray sunburst, boomerangs, kidney/amoeba
|
||
blobs, orbital atoms, concentric orbit rings, and a dense ray-star — plus the
|
||
naturally-3-D **Sputnik** satellite, a three-ring **gyroscope** cage, and a
|
||
spike-orb sea-urchin
|
||
- **Symbols & signs**, each in a flat **2-D** and an extruded **3-D** form:
|
||
smiley face, biohazard, peace sign, cross, question mark, exclamation point,
|
||
hash/pound (`#`), dollar sign (`$`), and pound sterling (`£`)
|
||
- **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).
|