Files
settled-reach/tooling/convert_outfit.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

54 lines
1.8 KiB
Python

"""Convert a Quaternius outfit gltf to glb with optional solidify."""
import sys
import bpy
CLOTHING_THICKNESS = 0.025 # 25mm outward solidify
if __name__ == "__main__":
argv = sys.argv
if "--" not in argv:
print("Usage: blender --background --python convert_outfit.py -- <input.gltf> <output.glb>")
sys.exit(1)
args = argv[argv.index("--") + 1:]
input_path = args[0]
output_path = args[1]
bpy.ops.wm.read_factory_settings(use_empty=True)
bpy.ops.import_scene.gltf(filepath=input_path)
# Solidify clothing meshes for thickness
meshes = [o for o in bpy.context.scene.objects if o.type == 'MESH']
for m in meshes:
if m.name.startswith("Icosphere") or len(m.data.vertices) < 50:
continue
bpy.context.view_layer.objects.active = m
m.select_set(True)
# Recalculate normals for consistent outward direction
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.normals_make_consistent(inside=False)
bpy.ops.object.mode_set(mode='OBJECT')
# Solidify
sol = m.modifiers.new(name="Solidify", type='SOLIDIFY')
sol.thickness = CLOTHING_THICKNESS
sol.offset = 1.0 # grow outward only
sol.use_rim = True
bpy.ops.object.modifier_apply(modifier=sol.name)
m.select_set(False)
print(f" Solidified: {m.name} ({CLOTHING_THICKNESS*1000:.0f}mm)")
bpy.ops.object.select_all(action='SELECT')
bpy.ops.export_scene.gltf(
filepath=output_path,
use_selection=True,
export_format='GLB',
export_animations=False,
export_yup=True,
export_texcoords=True,
export_normals=True,
export_skins=True,
export_materials='EXPORT',
)
print(f"Exported: {output_path}")