Skip to content

Blender Build Pipeline

Moshu edited this page Oct 5, 2026 · 1 revision

Blender Build Pipeline

Every UO equipment build ends in Blender: the item is bound to the canonical rig, animated through the original actions, rendered through the UO camera with the body as a holdout, and encoded as a UOFiddler .vd file. Content Studio and Fit Lab both drive this same pipeline.

Source: tools/uo-content/README.md, docs/body-occlusion.md.

The model it renders with

The pipeline uses UO_Model3D v13 by Levy, installed with pipeline.py setup --source <folder> (see Installation). The October 2026 update is supported: the same body topology, a 112-bone rig UO_Rig (v13's 108 plus weapon1h.R, axe2h.L, bow.L, polearm.L), new lighting and a renderer with a native 256x256 canvas.

Constant Value
Canvas 256 x 256 px
Anchor (ground origin) (128, 192)
Scale 36 pixels per metre, camera orientation preserved
Directions 5 stored (0–4); the client mirrors 5, 6, 7 from 3, 2, 1
Timeline UO frame i = scene frame 1 + 3i
Facing Driver -d*pi/4 on the rig's Z rotation

Steps of a build

item mesh ──► place on body region ──► bind to UO_Rig ──► apply fit + corrections ──► hide body under clothes
   ──► for each action x stored direction: pose, render with body holdout ──► PNG frames ──► .vd ──► validate
  1. Place and bind. Automatic placement at the slot's body region, or your supplied world coordinates. Helmets bind rigidly to the head, clothing gets surface-weight transfer, cloaks/skirts use cloth templates; pack parts use their mapping (skinned or rigid).
  2. Fit. Slot fit, item and left/right offsets and scoped corrections from Fit Lab are applied to rest geometry before animation, in Blender XYZ metres/degrees.
  3. Hide body. With hide_body enabled, body faces under the part are deleted from the fitting body. The count is written to scene-report.json.
  4. Render. Each action/direction block is rendered from the same untouched base geometry.
  5. Encode and validate. Frames become a VD file, and every frame's alpha and anchor is checked by SpriteMotion's own independent MUL decoder.

Body holdout and occlusion

The body is a holdout: it hides parts of the item behind it but never appears in the item image. Body poking through clothing would therefore cut holes in the item sprite, which is why body hiding exists.

  • A pristine copy of the complete animated body (torso included) decides final visibility, even when the fitting body has hidden faces.
  • Clothing mode allows a bounded contact tolerance only where the nearest body and item surfaces are the same anatomical region; left and right stay distinct.
  • Body mode has no garment allowance. None disables body masking.
  • Rigid items do not get the mesh-deforming push-out solver.
  • The upstream original-sprite outline correction and mounted horse masking remain in place.

Selective rebuilds

python tools/uo-content/pipeline.py rebuild <job> --adjustments <lab-adjustments.json>

The rebuild compares the resolved fit for every existing block and renders only blocks that changed, into a new validated revision. Untouched VD blocks stay byte-identical; the source build is preserved. A failed revision stays under staging/ and is not promoted.

A rebuild is refused when the canonical model, renderer code, source meshes or palette changed since the source build (render_fingerprint and source_fingerprints are recorded per job). Make a fresh build in that case.

Outputs

workspace/ultima-online/content-studio/jobs/<id>/ holds item.blend, item.vd, render/clothing/ PNGs, review/ atlases and viewer, inventory.png, contact-sheet.png, validation.json, scene settings, input provenance and import-package.zip.

UOFiddler

Import the full item.vd into an unused people/equipment animation slot.

Stage for a classic client

Both commands write new files in a fresh folder, with source/output hashes and a verification report. Your source client is never modified. Pass your own UO client folder (the same one as SPRITEMOTION_UO_SOURCE).

python tools/uo-content/client_import.py stage --vd <job>/item.vd --client <client-folder> --body <unused-animation-id> --out <new-staging-folder>
python tools/uo-content/equipment.py --job <job> --client <client-folder> --body <unused-animation-id> --graphic <unused-static-graphic-id> --server modernuo

The second command also stages inventory art in art.mul/artidx.mul, clones a known equipment tiledata record with the new animation ID and name, and generates a cosmetic ModernUO or ServUO item class (no combat stats).

  • Both reject animation IDs that are already used; equipment staging also rejects occupied art/tiledata.
  • Animation ID and static graphic ID are different numbers.
  • artLegacyMUL.uop can shadow MUL art; the tool reports this and gives you inventory.png for a UOP importer.
  • Not authored automatically: Body.def / Bodyconv.def / Equipconv.def rules, custom paperdoll gumps and the female-body conversion.
  • Generated server code must be compiled in your server and tested in game. Staging does not update a running shard.
  • A failed staging may leave a partial output folder; fix the error and use a fresh destination.

VD tools

tools/vd/ (contributed by Levy from his UO_Model3D project) reads and checks VD files:

python tools/vd/mul2vd.py "<your UO client folder>/anim.idx" "<your UO client folder>/anim.mul" <out dir> 400 0x1F3
python tools/vd/vdtool.py info <out dir>/anim_0400.vd
python tools/vd/vdtool.py extract anim_0400.vd frames/
python tools/vd/vdtool.py pack frames/ new.vd
python tools/vd/vdtool.py verify anim_0400.vd new.vd

Format in brief: a header (magic 6, type 2 = people/equipment, 35 actions), one index entry per action x 5 stored directions, and per block a 256-color 15-bit palette plus RLE frames. Color 0x0000 is transparent, so pure black is written as 0x0001. Alpha is on or off; soft edges and glows get flattened.

Known limits

  • Running a fresh physics cloth bake is not automated.
  • Mounted occlusion uses the source project's horse proxy and needs visual review.
  • Not yet verified on the updated model: a full 35-action lab build, mounted actions, cloaks with the torso mask, weapons on the new weapon bones. See UO Parity Roadmap.

Clone this wiki locally