Excellent state.
This commit is contained in:
commit
d85fb2e638
5 changed files with 1796 additions and 0 deletions
29
.claude/settings.local.json
Normal file
29
.claude/settings.local.json
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(pkg-config --list-all)",
|
||||
"Read(//usr/include/GLFW/**)",
|
||||
"Bash(ldconfig -p)",
|
||||
"Bash(make *)",
|
||||
"Bash(echo \"exit: $?\")",
|
||||
"Bash(timeout 2 ./vectorgons)",
|
||||
"Read(//tmp/**)",
|
||||
"Bash(glxinfo)",
|
||||
"Bash(grep -iE '^\\(scrot|grim|import|maim|spectacle\\)$')",
|
||||
"Bash(convert vg_shot.png -crop 270x210+0+0 +repage -resize 300% vg_crop.png)",
|
||||
"Bash(identify -format \"%wx%h\\\\n\" vg_multi.png)",
|
||||
"Bash(convert vg_multi.png -crop 760x600+460+0 +repage vg_multi_solids.png)",
|
||||
"Bash(convert vg2.png -crop 740x620+0+0 +repage vg2_crop.png)",
|
||||
"Bash(convert vg_ast.png -resize 1000x vg_ast_full.png)",
|
||||
"Bash(xwininfo -name Vectorgons -int)",
|
||||
"Bash(timeout 3 ./vectorgons)",
|
||||
"Bash(timeout 4 ./vectorgons)",
|
||||
"Bash(cat)",
|
||||
"Bash(cc -O2 -o /tmp/sim /tmp/sim.c -lm)",
|
||||
"Bash(/tmp/sim)",
|
||||
"Bash(cc -O2 -o /tmp/st2 /tmp/st2.c -lm)",
|
||||
"Bash(/tmp/st2)",
|
||||
"Bash(rm -f /tmp/st2 /tmp/st2.c)"
|
||||
]
|
||||
}
|
||||
}
|
||||
19
Makefile
Normal file
19
Makefile
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
CC ?= gcc
|
||||
CFLAGS ?= -O2 -Wall -Wextra -std=c11
|
||||
PKGS = glfw3 glu
|
||||
CPPFLAGS += $(shell pkg-config --cflags $(PKGS))
|
||||
LDLIBS += $(shell pkg-config --libs $(PKGS)) -lGL -lm
|
||||
|
||||
TARGET = vectorgons
|
||||
SRC = vectorgons.c
|
||||
|
||||
$(TARGET): $(SRC)
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(SRC) $(LDLIBS)
|
||||
|
||||
run: $(TARGET)
|
||||
./$(TARGET)
|
||||
|
||||
clean:
|
||||
rm -f $(TARGET)
|
||||
|
||||
.PHONY: run clean
|
||||
141
README.md
Normal file
141
README.md
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
# 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).
|
||||
BIN
vectorgons
Executable file
BIN
vectorgons
Executable file
Binary file not shown.
1607
vectorgons.c
Normal file
1607
vectorgons.c
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue