Nine agent skills for building Makepad/Rust games, ported from majidmanzarpour/threejs-game-skills. Same director-routed workflow and premium bar; runtime rewritten for this fork's game crates. - makepad-game-director entrypoint, routing, continuity, asset probe - makepad-gameplay-systems loop, movers vs rigid bodies, input, camera, netplay - makepad-aaa-graphics-builder lighting, shaders, budget, visual scorecard - makepad-game-ui-designer HUD, menus, touch and XR UI - makepad-debug-profiler defect bisection and profiling - makepad-qa-release verification ladder, evidence, packaging - makepad-3d-generator CC0 model search, casts, procedural geometry - makepad-image-generator texgen textures, palettes, sky, icons - makepad-audio-generator sample bank, mixer, material impacts, 3D audio Written against the real APIs in libs/game/*, libs/sim and apps/arcade: the game.* verb table, GameRenderer adaptive quality, the packed 6-float GameMeshVertex layout, script_mod! splash styling, makepad-test driving, and the BUDGETS.md numbers. No paid generation API is required - the CC0 library plus seeded makepad-game-gen replaces them. Includes install.sh (Codex/Claude), validate-skills.sh and a repo-aware probe_assets.sh; both scripts verified against this checkout.
103 lines
6 KiB
Markdown
103 lines
6 KiB
Markdown
---
|
||
name: makepad-3d-generator
|
||
description: "Source and create 3D content for Makepad games: search the CC0 model library by description, pick rigged character casts, and generate geometry procedurally with makepad-game-gen (terrain, trees, splines, interiors, level kits, implicit surfaces, meshes). Use for characters, vehicles, weapons, buildings, props, rigs, animation, terrain and level geometry requests."
|
||
---
|
||
|
||
# Makepad 3D Generator
|
||
|
||
Two sources, and choosing between them is most of the job.
|
||
|
||
| Source | Best for | Cost |
|
||
| --- | --- | --- |
|
||
| **CC0 library** (`makepad-game-assets`) | hero props, vehicles, characters, anything whose silhouette must read as a specific recognisable object | a one-time download |
|
||
| **Procedural** (`makepad-game-gen`) | terrain, roads, foliage, interiors, level layout, tiling detail, anything needed in bulk or varied by seed | free, deterministic, replicates as a seed |
|
||
|
||
No paid generation API is involved, and none is required. When neither source fits, extend the procedural generator — do not hand-author vertex dumps into the repo.
|
||
|
||
## The library
|
||
|
||
Fetch once (binaries are not in git):
|
||
|
||
```bash
|
||
./apps/arcade/download_assets.sh # core, ~1900 models, ~75 MB
|
||
./apps/arcade/download_assets.sh --packs=all # 4669 models / 47 packs, ~185 MB
|
||
./apps/arcade/download_assets.sh --list
|
||
bash skills/makepad-game-director/scripts/probe_assets.sh
|
||
```
|
||
|
||
Everything is pinned and sha256-verified; a moved or tampered upstream fails loudly. Downloads are sequential with a delay — do not parallelise someone else's bandwidth.
|
||
|
||
**Search by description, never filename.** `makepad-game-assets` provides `AssetIndex`, `find_model`, `find_cast`, `Filters`, `Hit`, `AssetKind`, `KitInfo`, `CastInfo`, `CATEGORIES`. Ids look like `kenney/racing/vehicle-truck-yellow` and are stable across re-downloads, because generated game code writes them.
|
||
|
||
The index is ~120 ms to build, ~0.2 ms per search, ~2.1 MB heap at 4,999 entries. Query-side stemming handles inflections; on a score tie the kind the query implies wins.
|
||
|
||
## Rigged characters
|
||
|
||
`find_cast` lists animated casts. **A cast is a set of characters sharing one skeleton** — any clip works on any member, so a part can be recast without touching animation code.
|
||
|
||
| rig | members | clips |
|
||
| --- | --- | --- |
|
||
| 41 joints (KayKit) | 9 | 76–95 — block, dodge, hurt, dance, sleep, carry |
|
||
| 7 joints (Kenney mini) | 22 | 25–32 — walk, run, jump, attack, sit, wave |
|
||
| 6 joints (Kenney platformer) | 5 | 25 |
|
||
|
||
Two rules: **one cast per scene**, and **different members within it** so a crowd is not clones. Mixing casts means an animation authored for one will not play on the other — a common and confusing failure.
|
||
|
||
Rendering: `SkinnedModel`, `PoseBuffer`, `SkinnedBatch`, `SkinnedDraw` in `makepad-game-render::skin`. Skinning is CPU-side and re-uploads every frame, so skinned character count is the most expensive visual budget you control.
|
||
|
||
## Procedural generation
|
||
|
||
`makepad-game-gen` modules: `mesh`, `terrain`, `tree`, `lsystem`, `spline`, `scatter`, `interior`, `kit`, `levelgen`, `implicit`, `texgen`, `cache`, `rng`. Plus `libs/rtsmap` for tiled RTS maps and `makepad-game-script::compose` (`kit_from_index`, `level_placements`, `PlacedTile`).
|
||
|
||
**Everything is seeded.** `makepad-game-math` supplies deterministic transcendentals so two devices generate byte-identical meshes from the same seed — which is what lets a forest replicate as `(preset, seed, position)` instead of vertex data. Never use `std` float math or unseeded RNG in a generator.
|
||
|
||
Pick by shape:
|
||
|
||
- **Heightfield ground** → `terrain` + `LandKind`
|
||
- **Organic branching** → `tree`, `lsystem`
|
||
- **Roads, rivers, rails** → `spline`
|
||
- **Fields of things** → `scatter` (with seeded scale/yaw jitter)
|
||
- **Rooms and buildings** → `interior`
|
||
- **Tile-based levels** → `levelgen`, `kit`, `rtsmap`
|
||
- **Blobs, caves, smooth solids** → `implicit`
|
||
- **Anything else** → `mesh` directly
|
||
|
||
## Rules that keep output usable
|
||
|
||
**Scale to the player capsule.** Decide player height in world units first (gameplay), then obey it. A door at 1.6 m in a world with a 1.8 m player is the sort of error that is invisible in a screenshot and obvious in play. Check with `model_bounds(id)`.
|
||
|
||
**Use the packed vertex layout.** `geom.GameMeshVertex` — 6 floats / 24 B (exact position, octahedral normal, f16 uv, unorm8 colour). Do not emit a fatter vertex for convenience; skinned and shadow meshes especially.
|
||
|
||
**Validate what you generate.** Is the spawn clear? Is the goal reachable? Is there a navigable path? An unvalidated level generator produces unwinnable levels about as often as good ones, and only playtesting finds them.
|
||
|
||
**Provide colliders.** `model_collider_parts(id)` gives library colliders. For generated geometry, produce a simplified collider — never collide against the render mesh.
|
||
|
||
**Cache.** `makepad-game-gen::cache`, keyed by `(preset, seed)`. Regenerating a forest every frame is a stutter source; an uncapped cache is a leak. Bound it.
|
||
|
||
## Variety without new assets
|
||
|
||
The library is shared, so default scenes look like everyone else's project. Four seeded levers, all free:
|
||
|
||
1. **Tint** — `ModelInstance::with_tint`, from `Palette` / `Spread` / `VarietyParams`
|
||
2. **Scale jitter** — ±10%
|
||
3. **Yaw jitter** — full range
|
||
4. **Member variety** — different cast members, different props from the same kit
|
||
|
||
Seeded, so all four still replicate across the wire.
|
||
|
||
## Verification
|
||
|
||
```rust
|
||
assert!(renderer.model_is_loaded(id), "missing {id}"); // silent primitive fallback otherwise
|
||
renderer.model_bounds(id); // scale sanity
|
||
renderer.model_triangles(id); // budget
|
||
|
||
assert_eq!(generate(1234), generate(1234), "generator must be deterministic");
|
||
```
|
||
|
||
Judge geometry by eye where a number cannot: the `ao_render` dev example in `makepad-game-render` software-rasterises props so baked AO and form read correctly without a `Cx` or the app.
|
||
|
||
## Required reading
|
||
|
||
- `references/asset-search.md` — querying, casts, kits, ids, filters.
|
||
- `references/procedural-recipes.md` — generator recipes and validation.
|