Files
settled-reach/tooling/check_hair_symmetry.py
T
jpmschweitzerandClaude Opus 4.6 093b24e38e feat(assets): face-based segmentation pipeline + solidify for hair/clothing
Segmentation:
- Face-based exclusive assignment (no overlap, no caps needed)
- Hips split from torso (pelvis as own segment)
- Torso_upper independent (spine_03 + clavicle, not a variant)
- Clavicle moved from arm_upper to torso_upper

Hair pipeline:
- Solidify modifier (20mm) for scalp hair volume
- Normal recalculation before solidify for consistent direction
- Eyebrows/facial hair NOT solidified
- Fixed mask generation (was outputting black, now white)

Clothing pipeline:
- Solidify modifier (25mm) for clothing thickness
- Peasant shoes added from Fantasy pack

Tooling:
- convert_outfit.py with solidify support
- inspect_glb.py, check_hair_symmetry.py for debugging
- Segment reference distribution locked
- Q-063 footsteps VFX filed

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 17:43:04 +01:00

32 lines
1.1 KiB
Python

"""Check if a hair mesh is symmetric across the X axis."""
import sys
import bpy
if __name__ == "__main__":
argv = sys.argv
if "--" not in argv:
sys.exit(1)
path = argv[argv.index("--") + 1]
bpy.ops.wm.read_factory_settings(use_empty=True)
bpy.ops.import_scene.gltf(filepath=path)
for obj in bpy.context.scene.objects:
if obj.type != 'MESH' or 'Hair' not in obj.name:
continue
verts = obj.data.vertices
xs = [v.co.x for v in verts]
zs = [v.co.z for v in verts]
print(f"{obj.name}: {len(verts)} verts")
print(f" X range: {min(xs):.4f} to {max(xs):.4f}")
print(f" Z range: {min(zs):.4f} to {max(zs):.4f}")
left = sum(1 for x in xs if x > 0.01)
right = sum(1 for x in xs if x < -0.01)
center = sum(1 for x in xs if abs(x) <= 0.01)
print(f" left(+X): {left}, right(-X): {right}, center: {center}")
# Check normals for consistency
normals = [v.normal for v in verts]
outward = sum(1 for n in normals if n.length() > 0.5)
print(f" verts with normals: {outward}/{len(verts)}")