makepad/skills/makepad-3d-generator/SKILL.md
Arena Agent fe21c07d84 skills: add Makepad game skills pack ported from threejs-game-skills
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.
2026-09-05 21:18:58 +00:00

6 KiB
Raw Permalink Blame History

name description
makepad-3d-generator 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):

./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 7695 — block, dodge, hurt, dance, sleep, carry
7 joints (Kenney mini) 22 2532 — 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 groundterrain + LandKind
  • Organic branchingtree, lsystem
  • Roads, rivers, railsspline
  • Fields of thingsscatter (with seeded scale/yaw jitter)
  • Rooms and buildingsinterior
  • Tile-based levelslevelgen, kit, rtsmap
  • Blobs, caves, smooth solidsimplicit
  • Anything elsemesh 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. TintModelInstance::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

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.