feat(assets): character body, head, and hair GLBs from Source tier #96

Closed
jpmschweitzer wants to merge 0 commits from visual into main
Owner

Summary

  • #707: 198 body segment GLBs (11 body types × 18 segments) exported from Quaternius Source .blends via headless Blender pipeline. 6 direct types (average, muscular, teen) + 5 auto-generated fork types (thin, heavy, child) flagged for artist review.
  • #708: 20 hair/facial_hair/eyebrow GLBs + recolor mask PNGs converted from Source tier glTF exports. Includes bald placeholder.
  • #709: 4 head template GLBs + mask PNGs from OnlyHead .blends (head_001–004).
  • 8 Blender headless pipeline scripts in tooling/ for reproducible asset processing.

257 files, ~250 GLBs + masks + pipeline scripts.

Test plan

  • Open representative GLBs in Blender to verify mesh integrity and bone weights
  • Verify body segments load onto shared armature (skeleton/armature.glb)
  • Check fork body type proportions (thin/heavy/child) — flagged for artist review
  • Verify hair GLBs attach correctly to Head bone via BoneAttachment3D
  • Confirm head templates are correctly scaled relative to body at gameplay zoom
  • Full integration test via character compositor (#693) once built

🤖 Generated with Claude Code

## Summary - **#707**: 198 body segment GLBs (11 body types × 18 segments) exported from Quaternius Source .blends via headless Blender pipeline. 6 direct types (average, muscular, teen) + 5 auto-generated fork types (thin, heavy, child) flagged for artist review. - **#708**: 20 hair/facial_hair/eyebrow GLBs + recolor mask PNGs converted from Source tier glTF exports. Includes bald placeholder. - **#709**: 4 head template GLBs + mask PNGs from OnlyHead .blends (head_001–004). - 8 Blender headless pipeline scripts in `tooling/` for reproducible asset processing. 257 files, ~250 GLBs + masks + pipeline scripts. ## Test plan - [ ] Open representative GLBs in Blender to verify mesh integrity and bone weights - [ ] Verify body segments load onto shared armature (skeleton/armature.glb) - [ ] Check fork body type proportions (thin/heavy/child) — flagged for artist review - [ ] Verify hair GLBs attach correctly to Head bone via BoneAttachment3D - [ ] Confirm head templates are correctly scaled relative to body at gameplay zoom - [ ] Full integration test via character compositor (#693) once built 🤖 Generated with [Claude Code](https://claude.com/claude-code)
jpmschweitzer added 4 commits 2026-03-22 15:14:11 +01:00
Adds 8 scripts to tooling/ for the Sprint 28 character asset pipeline:

- blender_segment_body.py: segments a FullBody GLTF into 18 body-part
  GLBs using BMesh vertex-weight selection + 1-ring boundary expansion
- blender_process_bodies.py: batch driver for all 11 body types (6 direct
  + 5 auto-scaled forks: thin, heavy, child)
- blender_process_heads.py: processes 4 OnlyHead .blend files into GLBs
  + 1024x1024 solid-white mask PNGs (D-159, D-160)
- blender_process_hair.py: converts 20 GLTF hairstyle/eyebrow exports
  to accessory GLBs + mask PNGs, creates bald.glb placeholder
- blender_inspect_body.py: diagnostic — lists mesh objects + vertex counts
- blender_inspect_vgroups.py: diagnostic — lists vertex groups on skinned mesh
- glb_strip_utility_nodes.py: post-process GLBs to strip utility nodes
  (Icosphere, WGT-*, DEF-*, ORG-* meshes) from the GLTF scene graph
- check_icosphere.py: diagnostic — reads GLB JSON chunk to verify node list

All Blender scripts require flatpak Blender via tooling/blender wrapper.
Scripts must live in project directories (flatpak sandbox blocks /tmp/).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds the character head and hair accessory asset tiers:

HEAD TEMPLATES (client/assets/characters/heads/templates/)
  4 head GLBs from Quaternius OnlyHead .blends:
  head_001 (regular_f), head_002 (regular_m),
  head_003 (teen_f), head_004 (teen_m)
  Each paired with a 1024x1024 solid-white _mask.png (full-face tintable)

HAIR (client/assets/characters/hair/)
  13 hairstyle GLBs + masks: bob, buns, cornrows, curly, long_wavy,
  medium_wavy, pixie, ponytail, short_fade, short_messy, short_neat,
  undercut, up_do; plus bald.glb placeholder

FACIAL HAIR (client/assets/characters/facial_hair/)
  3 GLBs + masks: beard, moustache, mutton_chops

EYEBROWS (client/assets/characters/eyebrows/)
  4 GLBs (no masks — tinted directly by shader):
  female, regular, teen, thick

Masks are white (full coverage) pending future artist-authored greyscale
maps for per-region tinting. Eyebrows excluded per compositor spec.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds 198 body segment GLBs (11 body types × 18 segments each) to
client/assets/characters/bodies/:

DIRECT BODY TYPES (6): average_m, average_f, muscular_m, muscular_f,
teen_m, teen_f — segmented from Quaternius FullBody GLTF exports

FORK BODY TYPES (5, auto-scaled from source mesh):
  thin_m, thin_f   — scale (0.82, 1.0, 0.88), narrower/ectomorph
  heavy_m, heavy_f — scale (1.20, 1.08, 1.0), wider/endomorph
  child            — scale (0.75, 0.72, 0.75), forked from teen_m

Each body type contains 18 segments:
  seg_head, seg_neck, seg_torso, seg_torso_upper,
  seg_arm_upper_l/r, seg_arm_lower_l/r, seg_hand_l/r,
  seg_leg_upper_l/r, seg_leg_lower_l/r, seg_foot_l/r,
  seg_eyes, seg_eyebrows

Fork directories include README.md flagging auto-generated status
and scale values. Fork proportions may need artist refinement.

Segmentation uses BMesh vertex-weight selection + 1-ring boundary
overlap for seam-free deformation. D-159 (11 body types), D-160
(18 segments), D-164 (Quaternius source assets).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Author
Owner

Review: visual -> main (type: visual)

Hoshe (QA): REQUEST_CHANGES

Asset library is structurally sound — all 11 body types, naming conventions, mask sidecar pairing all verified correct. One blocker.

# File Severity Issue
1 character-asset-organization.md, blender_segment_body.py, blender_process_bodies.py critical "21 segments" in spec + script docstrings vs 18 actually delivered. Implementation is consistently 18 — the "21" references are stale. Fix docs and docstrings.
2 blender_inspect_body.py, blender_inspect_vgroups.py, check_icosphere.py suggestion Missing __main__ guards (inconsistent with other pipeline scripts)
3 blender_process_bodies.py:107 suggestion sys.exit(1) on missing source mid-loop — should preflight-check all paths first

Araminta (Art Direction): REQUEST_CHANGES

Pipeline architecture is sound, segmentation approach is correct (1-ring overlap, ankle extension). Two blockers, same root cause as Hoshe.

# File Severity Issue
1 Spec + scripts critical Segment count 21 vs 18 discrepancy — same as Hoshe
2 average_m/ warning Reference body type has no README noting its role as clothing reference body
3 blender_process_hair.py suggestion Solid-white hair masks should be commented as placeholder for multi-region
4 blender_process_heads.py suggestion Head mask sized from first-found texture — fragile iteration order
5 hair/bald.glb suggestion No mask sidecar — document as deliberate exception or add 1x1 black placeholder
6 child/README.md suggestion Non-uniform scale (Y=0.72 vs XZ=0.75) rationale should be documented

Verdict: CHANGES REQUESTED

Primary blocker (both reviewers): The "21 segments" figure in the architecture doc and two script docstrings is stale — the actual implementation is 18 segments, consistent with the CHANGELOG, SEGMENT_ORDER, and on-disk output. This is a doc cleanup, not a missing-segments bug.

Priority fixes:

  1. Update architecture doc Section 2 and disk budget: 21→18, 231→198
  2. Update docstrings in blender_segment_body.py and blender_process_bodies.py
  3. Add brief README to average_m/ noting it as the reference body for clothing

Reviewed by Hoshe (QA) and Araminta (art direction) via /pr-review

## Review: visual -> main (type: visual) ### Hoshe (QA): REQUEST_CHANGES Asset library is structurally sound — all 11 body types, naming conventions, mask sidecar pairing all verified correct. One blocker. | # | File | Severity | Issue | |---|------|----------|-------| | 1 | `character-asset-organization.md`, `blender_segment_body.py`, `blender_process_bodies.py` | critical | "21 segments" in spec + script docstrings vs 18 actually delivered. Implementation is consistently 18 — the "21" references are stale. Fix docs and docstrings. | | 2 | `blender_inspect_body.py`, `blender_inspect_vgroups.py`, `check_icosphere.py` | suggestion | Missing `__main__` guards (inconsistent with other pipeline scripts) | | 3 | `blender_process_bodies.py:107` | suggestion | `sys.exit(1)` on missing source mid-loop — should preflight-check all paths first | ### Araminta (Art Direction): REQUEST_CHANGES Pipeline architecture is sound, segmentation approach is correct (1-ring overlap, ankle extension). Two blockers, same root cause as Hoshe. | # | File | Severity | Issue | |---|------|----------|-------| | 1 | Spec + scripts | critical | Segment count 21 vs 18 discrepancy — same as Hoshe | | 2 | `average_m/` | warning | Reference body type has no README noting its role as clothing reference body | | 3 | `blender_process_hair.py` | suggestion | Solid-white hair masks should be commented as placeholder for multi-region | | 4 | `blender_process_heads.py` | suggestion | Head mask sized from first-found texture — fragile iteration order | | 5 | `hair/bald.glb` | suggestion | No mask sidecar — document as deliberate exception or add 1x1 black placeholder | | 6 | `child/README.md` | suggestion | Non-uniform scale (Y=0.72 vs XZ=0.75) rationale should be documented | ### Verdict: CHANGES REQUESTED **Primary blocker (both reviewers):** The "21 segments" figure in the architecture doc and two script docstrings is stale — the actual implementation is 18 segments, consistent with the CHANGELOG, SEGMENT_ORDER, and on-disk output. This is a doc cleanup, not a missing-segments bug. **Priority fixes:** 1. Update architecture doc Section 2 and disk budget: 21→18, 231→198 2. Update docstrings in `blender_segment_body.py` and `blender_process_bodies.py` 3. Add brief README to `average_m/` noting it as the reference body for clothing --- *Reviewed by Hoshe (QA) and Araminta (art direction) via `/pr-review`*
jpmschweitzer added 1 commit 2026-03-22 15:24:56 +01:00
- Fix stale 21→18 segment count in architecture doc, script docstrings,
  and disk budget table (critical — both reviewers)
- Add average_m/README.md noting role as clothing reference body
- Add __main__ guards to diagnostic scripts
- Preflight-check all source paths in blender_process_bodies.py
- Document solid-white hair masks as v0.2 placeholder for multi-region
- Add fallback size comment for head mask generation
- Add bald_mask.png (1×1 black) for sidecar convention consistency
- Document child non-uniform scale rationale (Y=0.72 vs XZ=0.75)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Author
Owner

Review: visual -> main (type: visual) — Round 2

Hoshe (QA): APPROVE

All 4 fixes verified. No remaining issues.

Araminta (Art Direction): APPROVE

All 6 fixes verified. One minor note: MASK_RESOLUTION is 1024 but fallback log message says "512x512" — logging inconsistency, not a blocker.

Verdict: APPROVED


Re-reviewed by Hoshe (QA) and Araminta (art direction) via /pr-review

## Review: visual -> main (type: visual) — Round 2 ### Hoshe (QA): APPROVE All 4 fixes verified. No remaining issues. ### Araminta (Art Direction): APPROVE All 6 fixes verified. One minor note: `MASK_RESOLUTION` is 1024 but fallback log message says "512x512" — logging inconsistency, not a blocker. ### Verdict: APPROVED --- *Re-reviewed by Hoshe (QA) and Araminta (art direction) via `/pr-review`*
jpmschweitzer closed this pull request 2026-03-22 15:27:15 +01:00

Pull request closed

This pull request cannot be reopened because the branch was deleted.
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: jpmschweitzer/settled-reach#96