pipelines/BLENDER_ASSEMBLY_GUIDE.md
Written 2026-08-13 for Josh doing the 3D assembly manually. Everything here was measured on this
project's own assets during the 2026-08-12/13 sitting, not copied from a tutorial. Where a number
is a measurement it says so; where it is a starting point it says that too.
---
A head task and a body task, each ~1.9M triangles, with an 8192 base colour plus metallic,
roughness and normal maps. The body arrives with an adult head Meshy invented — that is
expected, not a failure, and it gets cut off.
Both halves must be cut at the same anatomical ring or they will not meet. That ring is the
neck's narrowest cross-section, and it is the one landmark that exists in every view including the
back of a head.
---
Do not eyeball it and do not use a fixed height — a constant cuts a 7-year-old through the jaw and
an 18-year-old through the collarbone. The neck is the **narrowest horizontal cross-section between
the jaw and the shoulders**.
In Blender:
1. Select the mesh, N panel → note the Z extent (Dimensions).
2. In Edit Mode, box-select a thin horizontal band at roughly 60–70% of the head-to-shoulder span
and read the X width in the N panel.
3. Move the band down in small steps. The width falls, reaches a minimum, then rises sharply as the
shoulders begin. The minimum is the ring.
4. On this project's ladder that ring measures 0.32–0.38 of the head's maximum width, consistent
across all 28 head views and all 21 body plates. If your band reads much outside that, you are on
the jaw (too high) or the shoulders (too low).
---
1. Body: Ctrl+R a loop cut at the ring, or use Bisect (Edit Mode → Mesh → Bisect) with the
plane at the ring height. Delete everything above it — that removes Meshy's invented adult head.
2. Head: same bisect at its own ring. Keep a collar of neck below the ring rather than
cutting flush; a bust that ends exactly at the seam has nothing to weld with.
3. Align: snap the head's ring centroid to the body's ring centroid (`Shift+S → Cursor to
Selected on one, then Selection to Cursor` on the other). Match rotation before scale.
4. Scale to fit: scale the head uniformly until its ring diameter matches the body's. Uniform
only — non-uniform scaling changes the skull proportions you approved.
5. Join (Ctrl+J), then in Edit Mode select both ring loops and M → Merge by Distance with a
threshold just above the gap. Check the vertex count drops by roughly the loop's vertex count —
if it does not, they did not weld.
6. Close the seam: a Shrinkwrap modifier on the joined band, or F to bridge, then Smooth on
the seam vertices only (not the face).
---
Meshy returns a mesh at its own scale, and per-rung scale will not agree across the ladder.
then apply scale (Ctrl+A → Scale). Do this before any other proportion work or every later
measurement is in different units.
API). With split parts you scale limbs and torso independently. Without it, select by region and
use proportional editing (O) with Connected falloff.
the failed ladders got wrong — the old set compressed the age range by 40%, which is what made
every rung read like the same person at different sizes.
---
Do not put head and body on one atlas. This is arithmetic, not preference:
| layout | texel size |
|---|---|
| one 4096 over a whole ~1.7 m² figure at 0.57 UV utilisation | 0.42 mm/texel — cannot hold a pore |
| head alone (~0.09 m²) on its own 4096 | 0.095 mm |
| head alone on 8192 | 0.047 mm — roughly one texel per follicle |
So: head 8192, body 4096, hair/garment 4096, as separate objects with separate material slots.
Retopo with QuadriFlow (Object → Quad Remesh in Blender 5.x): head 15–25k tris with loops
around eyes and mouth, body 30–50k. Then UV: Smart UV Project with island margin 0.003, or
xatlas if you want tighter packing.
---
Bake from the ~1.9M Meshy mesh onto your retopo low-poly. Meshy's own maps are a starting point;
the detail lives in the high-poly.
Settings, each one measured on this project:
proportional cage was 32.6 mm of extrusion, which sends nose-bridge rays into the eyeball and
in-ear rays into the skull. Head: 1.5 mm cage, 3 mm ray. Body: keep the larger cage.
samples 1. It is a deterministic ray query — there is nothing stochastic to average,and higher samples cost time for an identical result.
camera pulls back.
Emit off a Geometry → Pointiness node through a ColorRampnarrowed to roughly 0.42–0.58 (pointiness clusters near 0.5; widening it gives you a flat grey
useless map). You need this — it is the mask that makes micro-detail land in creases instead of
uniformly over a mannequin.
Blender bakes OpenGL (+Y, green up). Unreal expects DirectX (−Y, green down).
Set Render Properties → Bake → Normal Space: Tangent, and swizzle G to −Y. Measured proof: a
control bake of a plane tilted a known 20° returned green 171/255 — the OpenGL prediction — not 84.
880 normal maps in this project were inverted because of it, and inverted normals read in-engine as
exactly the flat waxy plastic you are trying to escape.
The project rule: every normal map on disk is DirectX. Flip at the bake, never per-consumer.
In UE, leave *Flip Green Channel* off — the file is already correct.
---
Below ~0.40 mm the source carries no signal, so that last octave is authored once and reused,
never inferred per asset. There is a tiling skin normal + cavity pair at
build/3d/shared/skin_microdetail/ — 2048, tiles by construction (measured wrap seam 1.019× the
interior discontinuity), born DirectX.
Blend it in the material masked by the baked curvature, not uniformly. Uniform micro-detail
reads as noise wrapped over a mannequin; masked, it reads as skin. Scale the UVs per subject so the
pore pitch stays physically plausible.
---
MetaHuman is not a look tool — Meshy and TRELLIS own the look, and a MetaHuman face is not better
geometry than a good sculpt. MetaHuman is the rig, LOD and performance layer for humans in UE5,
and that is the only reason it is in the plan:
expression on every human in the game
and you keep everything above
So the division of labour is: your sculpt is the character, MetaHuman is the actor. Without it,
~1,500 named characters each need bespoke rigging and facial animation, which is not a thing one
person does. Creatures never route through it — the topology is human-only.
Where it enters your bench flow: after the head/body weld and the retopo, not before. You hand
Mesh-to-MetaHuman a clean neutral-expression head; it wants topology it can conform to, and the
1.9M raw Meshy mesh is not that.
Three things that are true and worth knowing before you queue a roster behind it:
since UE 5.6, is the surviving route. Build one end-to-end before that date.
throughput at roster scale. At 1,500 characters that is the real unknown — measure it on one.
Only CHAR_0001 and the fairy-realm cast have pointed ears; the fairy realm is his origin world and
appears in the Prologue, Ch 1, and Ch 70-77. Every one of the 76 real-world regions is human-eared.
The route: conform MetaHuman on the human-eared head, then edit the ear vertices on LOD0 in
Blender. The ear is a small, isolated vertex island on a fixed topology, so the skin weights carry
and the face rig is untouched. Sculpt it once, reuse the shape across the whole fairy cast — about
80 rows, not the roster.
---
python harness/asset_factory/identity_lens.py --ref <approved>.png --probe <render>.png
Render the mesh under lighting matched to the plate first — scoring a clay render on black
against a soft-lit portrait is not a valid comparison and will read low regardless.
python harness/asset_factory/face_geometry_lens.py --ref … --probe …Six ratios below the hairline; detector noise floor is 2.27%, so under ~8% is the same skull.
chest, the lost ears, the slab — was caught by eye. Every one of them passed a number first.