Character workshop
The character workshop is a permanent development page at character-workshop.html
(entry script src/review/astra-review.ts). It loads characters through the same
AstraCharacter loader and animation runtime (src/animation/astra-character.ts) that
the game’s WebGPU player and NPC visuals use, so what you tune here is what ships.
The companion pages cover the Model settings panel (export, import, reset) and the Animation & grip tuning panel (weapon grips, per-clip pose offsets, publishing).
Run the workshop
Section titled “Run the workshop”npm run review:assetsThis starts Vite on 127.0.0.1:5186 and opens /character-workshop.html?asset=meshy.
Any Vite dev server works; the page reads these query parameters:
/character-workshop.html # the registered Grey (default)/character-workshop.html?base=grey-female-v1 # another registered character base/character-workshop.html?asset=fixture # the body/gear/cloth fitting fixture/character-workshop.html?model=/path/object.glb # static GLB inspection/character-workshop.html?manifest=/path/manifest.json&body=standard/character-workshop.html?clothBackend=cpu # force the CPU reference capeWithout asset=fixture the page loads a registered base (default grey-v2) and writes
the chosen base back into the URL. The registered bases and their manifest paths are
in CHARACTER_BASES in src/character/character-assets.ts. A static GLB keeps its
scene transforms, is scaled to fit the stage and reports its source dimensions; all
character controls are disabled in that mode. The Open an asset form in the sidebar
(just above Wings) builds the model or manifest URL for you.
Character manifests must follow the body/gear binding and the semantic bone names the
runtime expects; the workshop is not a retargeter for arbitrary rigs. The preview
renderer accepts at most 64 palette joints and 32 simultaneous morph targets
(src/character/character-preview-renderer.ts).
Inspect and tune
Section titled “Inspect and tune”The sticky shortcut row jumps to Motion, Tuning, Body, Stance, Eyes, Wings, Surface, Physics, Fabrics and Outfit. Directly below it, Model selects the character base and the mesh detail (full, or the 30,000-triangle NPC mesh when the source has one), followed by the Model settings panel.
- Body proportions: 27 morph sliders for the Grey, grouped as Frame, Arms and hands, Legs and feet, and Head and neck, plus a body preset list (Original Grey, Slender, Athletic, Stocky, Heavy, Tall) and a Link fullness to frame toggle. Each group has its own reset.
- Stance and foot pose: arm spacing (-18 to 25 degrees), leg spread (-8 to 18), left and right toe-out (-25 to 45) and left and right toe bend (-20 to 45). These are rotation offsets layered on top of the clip; they never change bone lengths.
- Eyes: edit both eyes or one side. Pupil shape (round, cat-eye slit, crescent, four-point star, three-lobed), iris pattern, colour preset, iris and outer-eye colours, iris and pupil size, horizontal iris offset, vein strength and colour, gaze (yaw ±28, pitch ±22 degrees) with Look forward, and a per-eye condition (clear, clouded, cataracted). The Iris, pupil & vein detail group adds a per-eye seed, pigment colour, fibre, mottle, pupil and vein controls.
- Hand states: each hand follows the animation or is held relaxed, open, fist, grip or point. These rotate the finger joints on top of the body animation.
- Surface inspection: lit material, geometry normals, base colour only, or clay. Toggle Baked normal detail to tell a bake error from a mesh deformation. Show skeleton draws the animated, proportion-adjusted joints; Show cloth colliders draws the cape collision shapes.
- Camera: ¾, Front, Side, Back, Feet, Face, Left hand and Right hand views. Face and hand views focus a bone. Camera follows animation is on by default; turn it off to hold the framing while a clip travels.
- Character: name (with Randomize name), skin tint, detail colour,
Save character, Load saved and Play this character, which saves the
character as the player and opens the game with
?workshopCharacter.
Edits are kept as a local draft automatically. Only Save character (or Play this character) writes the player save. Use Reload asset after a rebuild; if a load fails the button becomes Retry model and the last valid character stays on screen.
The Wings panel equips any item whose definition carries equip.wing (four designs
in src/game/items/item-defs.ts), previews the motion (follow character, folded, flap,
soar, dive), sets the growth level (1 to 20), and fits an offset, rotation and scale
per axis. Wings have their own skeleton, pass through the cape without joining its
collision set, and their fitting is included in Export all settings. Reset
wings leaves eyes, clothing and weapon work alone. scripts/verify-workshop-wings.mjs
is the browser check (it expects a dev server on port 5188).
Rebuild the Grey from source
Section titled “Rebuild the Grey from source”npm run assets:grey-v2scripts/build-grey-v2.mjs rebuilds the Grey from Meshy source art that is already on
disk: it never calls the Meshy API or spends credits, and it stops with an error if
mesh/mesh.glb or rig/rig.glb is missing from the profile’s source folder. It needs
Blender 5.2 or later; set BLENDER_EXE unless Blender 5.2 is installed at its default
Windows location.
Options (after --):
--profile=FILEpicks a source profile, as a path from the repository root (defaultassets/character/sources/grey-male-v2.json; the others sit in the same folder). The profile names every input and output folder.--through=clean|anatomy|refine|bake|reviewstops after that stage.--rebuild-surfaceforces the surface cleanup to run again.--rebakeforces the texture bake to run again.
The surface cleanup runs only when its report is missing or --rebuild-surface is
given. The UV, anatomy and bake stages keep a receipt of their input hashes and rerun
only when an input changed; the refine, check and review steps run every time. The
Grey profile reads its source art from art-input/meshy/grey-base-v2 and writes its
intermediates under .gear-work/; both folders are ignored by Git.
Paid generation is a separate command, npm run meshy:recipe, which runs
node scripts/astra-meshy.mjs <recipe.json> --through <stage>. It resumes existing
tasks from the recipe’s pipeline-state.json, refuses a run whose estimate exceeds
--max-credits (default 40), and never retries an uncertain paid request automatically.
--status and --plan report without submitting. Reuse existing task outputs before
generating again.
Build stages
Section titled “Build stages”For the default Grey profile, in order:
scripts/blender/clean-character-surface.pyrebuilds a continuous body from the high-detail source (voxel remesh, then QuadriFlow by default, about 18,000 quads) and transfers normalised weights from the original rig.scripts/blender/unwrap-character.pybuilds anatomical UV charts with minimum-stretch unwrapping, flip prevention and padded island packing.scripts/blender/build-character-anatomy.pyrestores eyelid detail, cuts the eye apertures and builds the inner sockets. Eye positions and radii come from the authoredassets/character/grey-refinement.json.scripts/prepare-grey-bake.mjsprepares the static bake surface.scripts/refine-meshy-grey.mjskeeps Meshy’s animation coordinate frames, adds fingers, eyes and toe tips, and writes the morph targets with matching rest-joint offsets and the stance definitions.scripts/blender/bake-meshy-detail.pybakes base colour, material maps and normal detail at 2048 pixels from the high-detail source through a character cage.- Checks:
scripts/test-grey-refinement.mjs,scripts/verify-character-source.mjsandscripts/blender/validate-character-proportions.py(rest-pose pelvis intersection checks at full fullness, full belly and the Stocky and Heavy presets). scripts/prepare-meshy-review.mjswrites the manifest, eye parts, maps and animation GLBs to the profile’s publication folder (.gear-work/meshy-greyfor the Grey), which the workshop loads in development.
The Grey-specific projection cage and authored landmarks are fitted to this source;
refine-meshy-grey.mjs refuses a source whose hash does not match the refinement file.
Other sources get their own profile, landmarks and calibration steps. The review
publication is written only in the last step, so a failed stage leaves the previous
publication in place.
The full production chain (outfit, crouch, actions, held items and tuning) is
npm run assets:character. npm run assets:character-runtime then packs the
publication’s resources into public/models/character-runtime/, and
npm run assets:character-publish writes the manifests into
public/models/characters/<id>/ (default id grey-v2), which production builds load.
Deformation contract
Section titled “Deformation contract”Morph geometry and rig offsets are generated from the same profile. Each character keeps its own morph weights and adjusted bind palette, while geometry and morph buffers can be shared between characters.
The Grey uses dual-quaternion skinning (extras.astra.skinning in the body GLB) to
keep volume through blended joint rotations. The runtime falls back to matrix skinning
when the palette cannot be expressed that way, for example under non-rigid scale.
Stature and body shape come from morph geometry and matching rest joints, never from
non-uniform animated bone scaling. CPU skin sampling follows the same skinning choice
as the preview shader.
Fullness, hip width and limb volume must vary continuously through the pelvis midline. Offsets that switch on the sign of X can fold inner-thigh triangles across each other even when the base mesh is a single closed shell, so check deformed meshes as well as base topology.
Verification
Section titled “Verification”npx tsc --noEmitnode scripts/test-grey-refinement.mjsnode scripts/verify-astra-browser.mjs "http://127.0.0.1:5186/character-workshop.html?asset=meshy"test-grey-refinement.mjs reads .gear-work/grey-refined/body.glb, so run it after a
local build. verify-astra-browser.mjs launches headless Edge or Chrome (set
CHROME_EXE to choose) with a throwaway profile against a running dev server, checks
clips and controls, and captures material and geometry comparisons. Reports land under
.gear-work/.
The surface report, UV and bake report, rest-pose proportion checks and animation checks cover different failure modes. Finite-number checks alone do not prove that extreme proportions are free of intersections; extreme body combinations still need art review and corrective shapes.
Source art, editable Blender files and generated intermediates are not in Git. Keep the approved source library backed up separately; the authored profiles, scripts and published runtime files are what the repository versions.
Written by release:site-sync from docs/character-workshop.md at v2026.10.04. Edit the engine document, not this page.