# Vectorgons
A starfield simulator — except instead of stars, colorful **vector-drawn
platonic solids** tumble through space toward the camera.
**~530 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 and pac-man ghosts, alien heads, smoking pipes, umbrellas, hands,
ice cream cones, light bulbs, mitochondria, windowpanes, bowling balls and
pins, baseball bats, beer bottles, nonic pint glasses, whiskey bottles,
telephones, telephone booths, radio towers, and atoms with orbiting electrons
(the volumetric bowling ball is a true wireframe sphere, and the 3-D atom has
real orbits + nucleus + electron balls rather than a flat extrusion)
- **More 3-D objects** — many built as true **solids of revolution** (a profile
lathed around an axis): a full **chess set** (pawn, rook, bishop, knight,
queen, king), candlesticks with a flame, coffee cups, lanterns, hurricane
lamps, quartz crystals, pineapples, and a parametric **torus** — plus extruded
silhouettes of padlocks, antique keys, bananas, electric guitars, tacos, pizza
slices, hammers, wrenches, directional and drafting compasses, set-squares,
eyeglasses, forks, spoons, fountain pens, the four classical element symbols
(fire/water/air/earth), the squared-circle "philosopher's stone", a couple of
retro stylized gaming/OS marks, a retro joystick, and a generic starship
- **Even more objects** in 2-D and 3-D: top hats, baseball caps, noses, hearts,
computer keyboards, floppy disks, bells, books, and two more stylized retro
computer marks. Every representational *object* now has both a flat 2-D and a
3-D form — the once-3-D-only chess pieces, lathed solids, torus, and atomic
starbursts all gained matching 2-D silhouettes.
- **Yet more**, all in 2-D and 3-D: IC chip packages (DIP, QFP, PGA, and a
generic CPU — the styles behind the 6502/Z80/386/486 and friends), hot dogs,
hamburgers, monoliths, ringed planets, unicycles, hula hoops, mechanical
gyroscopes, microscopes, telescopes, **magnifying glasses that actually
magnify the field behind them**, thermometers, calculators, staplers, paper
clips, palm trees, saguaro cacti, grape bunches, sushi rolls, corkscrews (a
real 3-D helix), bottle openers, lightning bolts, and batteries
- **An even bigger batch** in 2-D and 3-D: everlasting gobstoppers, pants,
shirts, jacks, dice, K/Q/J/A playing cards, roulette wheels, slot machines,
fire hydrants, bucky balls (a real truncated icosahedron), yo-yos, brains,
d6 and d20 dice, thimbles, automobiles, couches, stop signs, office chairs,
DNA double helices, skull-and-crossbones, goldfish, squid, pine cones, maple
leaves, sea anemones, wagon wheels, submarines, sailing ships, anchors, swiss
cheese wedges, and the anarchy symbol
- **Animated objects** (the 3-D form is rebuilt every frame): a **Hoberman
sphere** that unfolds and folds, a **Rubik's cube** whose top layer turns, a
**spinning top** and **dreidel** that precess, a **lighthouse** with a beam
that sweeps around, a **blinking eyeball**, a **skull with a chattering jaw**,
**chattering teeth**, an **octopus** with waving arms, a **jellyfish** with
drifting tentacles, a **fish** swimming with a flapping tail, **scissors**
that scissor, **flickering flames** (free and on a zippo lighter), and
**spinning gears** and a **spinning fan**
- A **3-D refracting prism**: a triangular glass prism that takes a white beam
in one face and splits it into a full rainbow spectrum fanning out the other —
the colours are drawn straight into the shape, independent of the field hue
- A **3-D glass sphere** (crystal ball): a real ball lens that grabs the field
behind it and shows it **inverted and fish-eye-distorted**, with a bright
fresnel rim and a specular reflection highlight. Like the magnifier it samples
the grabbed framebuffer, but with an inverting non-linear radial warp
- An **opaque polished mirror sphere** (chrome ball): a convex mirror that
**reflects the surrounding field upright** in a wide fish-eye — the optical
opposite of the glass ball (which inverts what's behind it). It has metallic
sky/ground shading so it reads as a solid metal ball even over empty space,
plus a sharp specular highlight. The magnifier, glass-ball and mirror-ball
**counts are each user-settable (0–1000)** — these are *extra* bodies added on
top of the density field, so dialling them up never thins out the normal shapes
- **Still more** in 2-D and 3-D: cassette tapes, vinyl records, CDs, quarters,
kites, baseballs, a police box, roses, shoes, boots, pianos, clouds, soup
cans, icebergs, pyramids (a real square pyramid in 3-D), bombs, combs, train
crossing signs, mailboxes, ship's wheels, axes, popcorn, teapots, church
bells, anvils, book stacks, springs and slinkies (real 3-D helices), extra
old keys, and a set of traditional alchemical and occult symbols (sulfur,
mercury, salt, antimony, pentagram, ankh, all-seeing eye, triple moon)
- **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
```
## Windows 11 (cross-compiled from Linux)
A self-contained `vectorgons.exe` can be cross-compiled with the
**MinGW-w64** toolchain. It statically links GLFW and the GCC/threads runtime,
so on Windows it needs **only system DLLs** (`opengl32`, `glu32`, `gdi32`,
`user32`, `shell32`, `kernel32`) — just copy `vectorgons.exe` to a Windows 11
machine and double-click it. No console window, no extra DLLs.
```sh
# 1. toolchain: sudo apt install gcc-mingw-w64-x86-64 binutils-mingw-w64-x86-64 mingw-w64-x86-64-dev
# 2. GLFW: download the WIN64 binaries from https://www.glfw.org/download
# 3. build:
make windows WINCC=x86_64-w64-mingw32-gcc GLFWDIR=/path/to/glfw-3.4.bin.WIN64
make screensaver WINCC=x86_64-w64-mingw32-gcc GLFWDIR=/path/to/glfw-3.4.bin.WIN64
```
The legacy immediate-mode OpenGL it uses (and the `glu32` perspective helpers)
are provided by the standard Windows OpenGL driver, so it runs on any Windows 11
box with working GPU drivers.
### Screensaver (`vectorgons.scr`)
`make screensaver` builds the **same program as a Windows screensaver** (it's
the same source with `-DSCREENSAVER`, output named `.scr`). It handles the
standard screensaver command line:
- **`/s`** (or no argument) — run full-screen on the primary monitor; **any key,
mouse click, or real mouse movement exits**. The on-screen control panel is
hidden.
- **`/c`** — show a short configuration dialog. There are no in-saver controls;
the saver simply uses whatever settings the main app last saved (see below),
so run `vectorgons.exe`, dial in the look you want, quit, and the saver picks
it up.
- **`/p`** — preview (the little monitor in Windows' settings); not supported, so
it exits cleanly and the preview stays blank.
To install on Windows: right-click `vectorgons.scr` → **Install** (or copy it to
`C:\Windows\System32` and choose it under *Settings → Personalization → Lock
screen → Screen saver*). Like the `.exe`, it needs only Windows system DLLs.
## Browser (WebAssembly)
The same source compiles to WebAssembly with [Emscripten](https://emscripten.org),
which maps the GLFW3 windowing and the legacy/immediate-mode OpenGL onto WebGL
(`-sLEGACY_GL_EMULATION`). The retained-mode VBO geometry, the FBO bloom, and the
frustum culling all run unchanged; the browser-specific bits (GLU helpers, the
`requestAnimationFrame` main loop, and the WebGL-incompatible `double`/`glReadBuffer`
calls) are guarded behind `#ifdef __EMSCRIPTEN__`.
```sh
source /path/to/emsdk/emsdk_env.sh # put emcc on PATH
make web # -> web/vectorgons.js + web/vectorgons.wasm
```
Serve the `web/` directory over HTTP (WebAssembly will **not** load from a
`file://` URL) and open `index.html`:
```sh
cd web && python3 -m http.server 8000 # then visit http://localhost:8000/
```
`web/index.html` is a ready-made page. To embed in your own page, drop a focusable
canvas with `id="canvas"`, point Emscripten's `Module` at it, and load the script:
```html
```
Serve `vectorgons.js`, `vectorgons.wasm`, and `vectorgons-boot.js` from the same
directory. Click the canvas to give it keyboard focus; all the usual controls
then work, and `F` requests browser fullscreen. (Settings are not persisted in
the browser.)
### Content-Security-Policy
WebAssembly needs a couple of CSP allowances. If your server sends a strict CSP
(symptom: the canvas appears but nothing runs, and the console shows
`both async and sync fetching of the wasm failed`), the page's `script-src` must
include **`'wasm-unsafe-eval'`** (required to instantiate any WASM — there is no
nonce/hash alternative) and **`connect-src`** must allow fetching the `.wasm`
(e.g. `'self'`). Loading the `Module` config from `vectorgons-boot.js` (rather
than an inline `