strip_skin: export GLB not FBX — Blender 5 FBX exporter flattens slotted actions
This was the entire 'MIRPAMO retarget is mushy' mystery: the retarget math was fine, the converted clips were flat. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
c3d682b7dd
commit
b033879963
@ -23,7 +23,9 @@ out = Path(args.out).expanduser()
|
|||||||
out.mkdir(parents=True, exist_ok=True)
|
out.mkdir(parents=True, exist_ok=True)
|
||||||
for clip in args.clips.split(","):
|
for clip in args.clips.split(","):
|
||||||
clip = Path(clip).expanduser()
|
clip = Path(clip).expanduser()
|
||||||
dest = out / clip.name
|
# GLB out: Blender 5's FBX exporter flattens slotted actions to identity;
|
||||||
|
# the glTF exporter is slot-native and MIRPAMO imports glb clips fine.
|
||||||
|
dest = (out / clip.name).with_suffix(".glb")
|
||||||
if dest.exists():
|
if dest.exists():
|
||||||
print("SKIP", clip.name)
|
print("SKIP", clip.name)
|
||||||
continue
|
continue
|
||||||
@ -33,13 +35,33 @@ for clip in args.clips.split(","):
|
|||||||
if o.type == "MESH":
|
if o.type == "MESH":
|
||||||
bpy.data.objects.remove(o, do_unlink=True)
|
bpy.data.objects.remove(o, do_unlink=True)
|
||||||
# normalise numbered Mixamo namespaces (mixamorig7: -> mixamorig:) so
|
# normalise numbered Mixamo namespaces (mixamorig7: -> mixamorig:) so
|
||||||
# downstream mappers (MIRPAMO retarget) match by exact name
|
# downstream mappers (MIRPAMO retarget) match by exact name.
|
||||||
|
# NOTE: bone rename does NOT fix up slotted-action fcurve paths in
|
||||||
|
# Blender 5 — rewrite them explicitly or the action drives nothing.
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
def all_fcurves(act):
|
||||||
|
if hasattr(act, "fcurves") and len(getattr(act, "fcurves", [])):
|
||||||
|
return list(act.fcurves)
|
||||||
|
out = []
|
||||||
|
for layer in act.layers:
|
||||||
|
for strip in layer.strips:
|
||||||
|
for cb in strip.channelbags:
|
||||||
|
out.extend(cb.fcurves)
|
||||||
|
return out
|
||||||
|
|
||||||
for o in bpy.data.objects:
|
for o in bpy.data.objects:
|
||||||
if o.type == "ARMATURE":
|
if o.type == "ARMATURE":
|
||||||
for b in o.data.bones:
|
for b in o.data.bones:
|
||||||
b.name = re.sub(r"^mixamorig\d+:", "mixamorig:", b.name)
|
b.name = re.sub(r"^mixamorig\d+:", "mixamorig:", b.name)
|
||||||
bpy.ops.export_scene.fbx(filepath=str(dest), use_selection=False,
|
for act in bpy.data.actions:
|
||||||
add_leaf_bones=False, bake_anim=True)
|
for fc in all_fcurves(act):
|
||||||
|
if '"' in fc.data_path:
|
||||||
|
bone = fc.data_path.split('"')[1]
|
||||||
|
fixed = re.sub(r"^mixamorig\d+:", "mixamorig:", bone)
|
||||||
|
if fixed != bone:
|
||||||
|
fc.data_path = fc.data_path.replace('"%s"' % bone, '"%s"' % fixed)
|
||||||
|
bpy.ops.export_scene.gltf(filepath=str(dest), export_format="GLB",
|
||||||
|
export_animations=True)
|
||||||
print("STRIPPED", clip.name)
|
print("STRIPPED", clip.name)
|
||||||
print("DONE")
|
print("DONE")
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user