Mixamo2 / character_refine.py
jasongzy's picture
🦄 refactor: utils
e9eca74
raw
history blame
3.62 kB
import os
from glob import glob
import bpy
from tqdm import tqdm
from utils import (
HiddenPrints,
get_all_armature_obj,
get_rest_bones,
load_file,
mesh_quads2tris,
remove_all,
select_objs,
)
def rename_maxiamo_bone(armature_obj):
"""Replace name like 'mixamorig10:xxx' to 'mixamorig:xxx, so that character can be correctly animated.'"""
import re
pattern = re.compile(r"mixamorig[0-9]+:")
for bone in armature_obj.data.bones:
bone.name = re.sub(pattern, "mixamorig:", bone.name)
return armature_obj
if __name__ == "__main__":
input_dir = "."
keep_texture = False
output_dir = os.path.join(input_dir, "character_refined")
if keep_texture:
output_dir += "_textured"
os.makedirs(output_dir, exist_ok=True)
character_list = sorted(glob(os.path.join(input_dir, "character", "*.fbx")))
character_list_upgraded = sorted(glob(os.path.join(input_dir, "character_fbx_upgraded", "*.fbx")))
character_list_upgraded = {os.path.basename(x): x for x in character_list_upgraded}
for i, path in enumerate(character_list):
path_upgraded = character_list_upgraded.get(os.path.basename(path))
if path_upgraded is not None:
character_list[i] = path_upgraded
animation_list = sorted(glob(os.path.join(input_dir, "animation", "*.fbx")))
unposed_list_file = "character_unposed.txt"
if os.path.isfile(unposed_list_file):
with open(unposed_list_file, "r") as f:
unposed_list = f.readlines()
unposed_list = [x.strip() for x in unposed_list if x.strip() != ""]
else:
unposed_list = None
logfile = "character_bones.txt"
bones_name_list = []
for file in tqdm(character_list, dynamic_ncols=True):
try:
with HiddenPrints():
remove_all()
obj_list = load_file(file)
armature_obj = get_all_armature_obj(obj_list)
assert len(armature_obj) == 1, "Armature number is not 1"
armature_obj = armature_obj[0]
if unposed_list is None or file in unposed_list:
rename_maxiamo_bone(armature_obj)
rest_bones, bones_idx_dict = get_rest_bones(armature_obj)
# mesh_quads2tris(get_all_mesh_obj(obj_list))
select_objs(obj_list, deselect_first=True)
bpy.ops.export_scene.fbx(
filepath=os.path.join(output_dir, os.path.basename(file)),
check_existing=False,
use_selection=True,
use_triangles=True, # !
add_leaf_bones=False,
bake_anim=False,
path_mode="COPY",
embed_textures=keep_texture,
)
bones_name_list += list(bones_idx_dict.keys())
with open(logfile, "a") as f:
f.write(f"{file}: {len(bones_idx_dict)}\n")
except Exception as e:
# raise
tqdm.write(f"{file}: {e}")
with open(logfile, "a") as f:
f.write(f"{file}: {e}\n")
# Calculate the coverage of each bone among all characters
print(sorted(set(bones_name_list)))
# with HiddenPrints():
# remove_all()
# rest_bones, bones_idx_dict = get_rest_bones(get_all_armature_obj(load_file(animation_list[0]))[0])
with open(logfile, "a") as f:
# for v in bones_idx_dict.keys():
for v in sorted(set(bones_name_list)):
f.write(f"{v}: {bones_name_list.count(v)}/{len(character_list)}\n")