在这里就不详细说了,详细使用请看视频:
https://www.bilibili.com/video/BV1zh4y1w7kQ
因为不同的mmd模型作者往往不会使用相同的骨骼层级结构,所以mmd模型就很难去用通用的脚本去进行自动化改造
所以在使用过程中会不可避免的出现错误
改造效果:
代码如下:
import c4d
# region
def Process_Node(layer, obj, func):
chlidren_list = obj.GetChildren()
layer_current = []
for str in layer:
layer_current.append(str)
layer_current.append(obj.GetName())
pass
func(obj, layer_current)
pass
for child in chlidren_list:
Process_Node(layer_current, child, func)
def Package_Other(obj_name, ex_list, proc_times):
pass
par_obj = doc.SearchObject(obj_name)
if par_obj is None:
return
child_tmp = par_obj.GetChildren()
# 阻止重复打包
for child in child_tmp:
if child.GetName().find("other") != -1:
return
new_null_obj = c4d.BaseObject(c4d.Onull)
doc.InsertObject(new_null_obj)
new_null_obj.InsertUnder(par_obj)
new_null_obj.SetName("other"+str(proc_times))
c4d.EventAdd()
for child in child_tmp:
if child.GetName() in ex_list:
continue
child.InsertUnder(new_null_obj)
print("package:", obj_name, ex_list)
c4d.EventAdd()
def Get_Child_By_Name(obj, child_name):
pass
c_list = obj.GetChildren()
for c in c_list:
if c.GetName() == child_name:
return c
def Delete(name):
bone = doc.SearchObject(name)
bone.Remove()
c4d.EventAdd()
def Delete_And_Move_Children(name):
bone = doc.SearchObject(name)
if bone is None:
return
children_list = bone.GetChildren()
parent_obj = bone.GetUp()
for child in children_list:
pos = child.GetMg()
child.InsertUnderLast(parent_obj)
child.SetMg(pos)
bone.Remove()
c4d.EventAdd()
def Insert_With_Position(obj, par_obj):
pass
pos = obj.GetMg()
obj.InsertUnderLast(par_obj)
obj.SetMg(pos)
def Re_Name(obj_name, new_name):
pass
# M_左手首
obj = doc.SearchObject(obj_name)
obj.SetName(new_name)
def Add_Control_Obj(obj_name, ctl_name, ctl_par_name):
pass
obj = doc.SearchObject(obj_name)
if obj is None:
return
ctl_obj = None
# 检查创建控制器
if obj.GetUp().GetName() != ctl_name:
pass
ctl_obj = c4d.BaseObject(c4d.Onull)
doc.InsertObject(ctl_obj)
ctl_obj.SetName(ctl_name)
pos = obj.GetMg()
ctl_obj.SetMg(pos)
Insert_With_Position(obj, ctl_obj)
else:
pass
ctl_obj = doc.SearchObject(ctl_name)
# 控制器位置
ctl_par = doc.SearchObject(ctl_par_name)
if not ctl_obj.GetUp() is None:
pass
if ctl_obj.GetUp().GetName() != ctl_par_name:
Insert_With_Position(ctl_obj, ctl_par)
else:
Insert_With_Position(ctl_obj, ctl_par)
c4d.EventAdd()
def Add_Control_Obj_Std_Rou(obj_name, ctl_name, ctl_par_name):
pass
obj = doc.SearchObject(obj_name)
if obj is None:
return
ctl_obj = None
# 检查创建控制器
if obj.GetUp().GetName() != ctl_name:
pass
ctl_obj = c4d.BaseObject(c4d.Onull)
doc.InsertObject(ctl_obj)
ctl_obj.SetName(ctl_name)
pos = obj.GetMg()
ctl_obj.SetMg(pos)
ctl_obj.SetAbsRot((0, 0, 0))
Insert_With_Position(obj, ctl_obj)
else:
pass
ctl_obj = doc.SearchObject(ctl_name)
# 控制器位置
ctl_par = doc.SearchObject(ctl_par_name)
if not ctl_obj.GetUp() is None:
pass
if ctl_obj.GetUp().GetName() != ctl_par_name:
Insert_With_Position(ctl_obj, ctl_par)
else:
Insert_With_Position(ctl_obj, ctl_par)
c4d.EventAdd()
def Set_IK_Tag(ik_root_name, ik_end_name, ik_target_name, handle_offset_v3):
pass
ik_root = doc.SearchObject(ik_root_name)
ik_end = doc.SearchObject(ik_end_name)
ik_target = doc.SearchObject(ik_target_name)
ik_tag = ik_root.MakeTag(1019561) # IK标签
ik_tag[c4d.ID_CA_IK_TAG_TIP] = ik_end
ik_tag[c4d.ID_CA_IK_TAG_TARGET] = ik_target
handle = c4d.BaseObject(c4d.Onull)
doc.InsertObject(handle)
handle.SetName(ik_root.GetName()+"旋转手柄")
handle.InsertAfter(ik_root)
pos = ik_root.GetAbsPos()
print(pos)
print(ik_root.GetRelPos())
handle.SetAbsPos(pos+handle_offset_v3)
ik_tag[c4d.ID_CA_IK_TAG_POLE] = handle
handle[c4d.ID_BASEOBJECT_USECOLOR] = 2
handle[c4d.ID_BASEOBJECT_COLOR] = c4d.Vector(1, 1, 1)
handle[c4d.NULLOBJECT_DISPLAY] = 11
handle[c4d.NULLOBJECT_RADIUS] = 20
handle[c4d.NULLOBJECT_ORIENTATION] = 3
def Set_Control_Type(obj_name, v3, type, radius, dir_type):
pass
obj = doc.SearchObject(obj_name)
if obj is None:
return
obj[c4d.ID_BASEOBJECT_USECOLOR] = 2
obj[c4d.ID_BASEOBJECT_COLOR] = v3
obj[c4d.NULLOBJECT_DISPLAY] = type
obj[c4d.NULLOBJECT_RADIUS] = radius
obj[c4d.NULLOBJECT_ORIENTATION] = dir_type
c4d.EventAdd()
def Set_IK_Control(obj_name, IK_Ctl_name, root_name, v3, type, radius, dir_type):
pass
obj = doc.SearchObject(obj_name)
root_obj = doc.SearchObject(root_name)
if obj is None:
return
IK_Ctl = c4d.BaseObject(c4d.Onull)
doc.InsertObject(IK_Ctl)
IK_Ctl.SetName(IK_Ctl_name)
IK_Ctl.InsertUnder(root_obj)
pos = obj.GetMg()
IK_Ctl.SetMg(pos)
IK_Ctl[c4d.ID_BASEOBJECT_USECOLOR] = 2
IK_Ctl[c4d.ID_BASEOBJECT_COLOR] = v3
IK_Ctl[c4d.NULLOBJECT_DISPLAY] = type
IK_Ctl[c4d.NULLOBJECT_RADIUS] = radius
IK_Ctl[c4d.NULLOBJECT_ORIENTATION] = dir_type
c4d.EventAdd()
def Set_Bind_Tag_Rou(obj_name, bind_name):
pass
obj = doc.SearchObject(obj_name)
bind = doc.SearchObject(bind_name)
tag = obj.MakeTag(1019364) # 绑定
tag[c4d.ID_CA_CONSTRAINT_TAG_PSR] = 1
tag[10005] = 0
tag[10001] = bind
def Set_Bone_Type(obj_name, joint_type, radius):
pass
obj = doc.SearchObject(obj_name)
obj[c4d.ID_CA_JOINT_OBJECT_JOINT_SIZE_MODE] = 0
obj[c4d.ID_CA_JOINT_OBJECT_JOINT_DISPLAY] = joint_type
obj[c4d.ID_CA_JOINT_OBJECT_JOINT_SIZE] = radius
c4d.EventAdd()
# endregion
# -----------------------名称标准化------------------------------D
root_name = doc.GetFirstObject().GetName()
Re_Name(root_name, "root")
# 一些mmd模型的骨骼名称不带字母“D”
try:
pass
Re_Name("右足", "右足D")
Re_Name("右ひざ", "右ひざD")
Re_Name("右足首", "右足首D")
Re_Name("左足", "左足D")
Re_Name("左ひざ", "左ひざD")
Re_Name("左足首", "左足首D")
except:
pass
# ---------------------------------------------------------------
bone_root_obj = doc.SearchObject("全ての親")
# -----------------------名称唯一化-----------------------
# region
Name_List = []
def Rename_Repeated_Name(obj, layer_current):
pass
name_tmp = obj.GetName()
changed = False
while True:
if name_tmp in Name_List:
name_tmp = name_tmp+"_"
changed = True
continue
break
if changed:
print(obj.GetName(), "--->", name_tmp)
obj.SetName(name_tmp)
Name_List.append(name_tmp)
Process_Node([], bone_root_obj, Rename_Repeated_Name)
# endregion
# ----------------------- 删除无子级无权重的对象-----------------------
# region
class Node_With_Weight:
def __init__(self, name, obj_ref, bone_root_obj):
pass
self.obj_ref = obj_ref
self.bone_root_obj = bone_root_obj
self.name = name
self.parent_List = []
node_tmp = obj_ref
while True:
self.parent_List.append(node_tmp.GetName())
if node_tmp.GetName() != bone_root_obj.GetName():
pass
else:
self.parent_List.reverse()
break
node_tmp = node_tmp.GetUp()
# 更新路径信息
def Path_Update(self):
pass
self.parent_List = []
node_tmp = self.obj_ref
while True:
self.parent_List.append(node_tmp.GetName())
if node_tmp.GetName() != bone_root_obj.GetName():
pass
else:
self.parent_List.reverse()
break
node_tmp = node_tmp.GetUp()
# 判断给定的路径是否是带有权重的对象的路径
def Is_Path_Has_Weight(list):
pass
for node in Obj_Name_With_Weight:
if node.parent_List == list:
return True
return False
Obj_Name_With_Weight = []
mesh_obj = doc.SearchObject("Mesh")
weight_tag = mesh_obj.GetTag(c4d.Tweights)
joint_count = weight_tag.GetJointCount()
# 获取所有带有权重的骨骼的名称
for i in range(joint_count):
node = Node_With_Weight(weight_tag.GetJoint(
i).GetName(), weight_tag.GetJoint(i), bone_root_obj)
Obj_Name_With_Weight.append(node)
obj_ready_for_delete_list = []
def Delete_Obj_With_No_Children_No_Weight(obj, layer_current):
pass
children_list = obj.GetChildren()
if (not Is_Path_Has_Weight(layer_current)) and len(children_list) == 0:
obj_ready_for_delete_list.append(obj)
# print(obj.GetName())
while True:
pass
obj_ready_for_delete_list = []
Process_Node([], bone_root_obj, Delete_Obj_With_No_Children_No_Weight)
for obj in obj_ready_for_delete_list:
obj.Remove()
if len(obj_ready_for_delete_list) == 0:
break
c4d.EventAdd()
# endregion
# -------------------------删除所有保护,IK,绑定标签---------------------------
# region
def Delete_Protection_Tag(obj, layer_current):
pass
obj.KillTag(c4d.Tprotection)
try:
obj.KillTag(1019561)
except:
pass
try:
obj.KillTag(1019364)
except:
pass
Process_Node([], bone_root_obj, Delete_Protection_Tag)
c4d.EventAdd()
# endregion
# --------------------------打包组件骨骼---------------------------------
proc_times = 0
Package_Other("下半身", ["右足", "左足"], proc_times)
proc_times = proc_times+1
Package_Other("上半身2", ["右肩", "左肩", "首"], proc_times)
proc_times = proc_times+1
Package_Other("頭", [], proc_times)
# --------------------------转换Tpose----------------------------------
doc.SearchObject("右腕")[c4d.ID_BASEOBJECT_REL_ROTATION, c4d.VECTOR_Z] = 0.611
doc.SearchObject("左腕")[c4d.ID_BASEOBJECT_REL_ROTATION, c4d.VECTOR_Z] = -0.611
# --------------------------删除无用对象-------------------------------------
Delete_And_Move_Children("全ての親")
Delete_And_Move_Children("センター")
Delete_And_Move_Children("グルーブ")
Delete_And_Move_Children("腰")
Delete_And_Move_Children("左肩P")
Delete_And_Move_Children("右肩P")
Delete_And_Move_Children("腰キャンセル右")
Delete_And_Move_Children("腰キャンセル左")
# ---------------------------加入控制器------------------------------------
Add_Control_Obj("上半身", "M_上半身", "root")
Add_Control_Obj("上半身2", "M_上半身_2", "M_上半身")
Add_Control_Obj("首", "M_首", "M_上半身_2")
Add_Control_Obj("頭", "M_首_2", "M_首")
Add_Control_Obj_Std_Rou("左肩", "M_左肩", "M_上半身_2")
Add_Control_Obj_Std_Rou("左肩", "M_左肩_2", "M_左肩")
Add_Control_Obj_Std_Rou("右肩", "M_右肩", "M_上半身_2")
Add_Control_Obj_Std_Rou("右肩", "M_右肩_2", "M_右肩")
Add_Control_Obj_Std_Rou("左腕", "M_L_0", "M_左肩_2")
Add_Control_Obj_Std_Rou("左ひじ", "M_L_1", "M_L_0")
Add_Control_Obj_Std_Rou("左手首", "M_L_2", "M_L_1")
Add_Control_Obj_Std_Rou("左手首", "M_左手首", "M_L_2")
Add_Control_Obj_Std_Rou("右腕", "M_R_0", "M_右肩_2")
Add_Control_Obj_Std_Rou("右ひじ", "M_R_1", "M_R_0")
Add_Control_Obj_Std_Rou("右手首", "M_R_2", "M_R_1")
Add_Control_Obj_Std_Rou("右手首", "M_右手首", "M_R_2")
Add_Control_Obj("下半身", "M_下半身", "root")
Add_Control_Obj("下半身", "M_下半身_2", "M_下半身")
Insert_With_Position(doc.SearchObject("右足D"), doc.SearchObject("M_下半身_2"))
Insert_With_Position(doc.SearchObject("左足D"), doc.SearchObject("M_下半身_2"))
c4d.EventAdd()
# -------------------------重命名----------------------------------
Re_Name("右足D", "M_右足D")
Re_Name("右ひざD", "M_右足D2")
Re_Name("右足首D", "M_右足首D")
Re_Name("左足D", "M_左足D")
Re_Name("左ひざD", "M_左足D2")
Re_Name("左足首D", "M_左足首D")
Re_Name("左手首", "M_左手首_2")
Re_Name("右手首", "M_右手首_2")
old_name_list_X = ["小指1", "小指2", "小指3"]
new_name_list_X = ["小指1", "小指2", "小指3"]
for id in range(0, 3):
Re_Name("左"+old_name_list_X[id], "M_左"+new_name_list_X[id])
Re_Name("右"+old_name_list_X[id], "M_右"+new_name_list_X[id])
old_name_list_X = ["薬指1", "薬指2", "薬指3"]
new_name_list_X = ["无名指1", "无名指2", "无名指3"]
for id in range(0, 3):
Re_Name("左"+old_name_list_X[id], "M_左"+new_name_list_X[id])
Re_Name("右"+old_name_list_X[id], "M_右"+new_name_list_X[id])
old_name_list_X = ["中指1", "中指2", "中指3"]
new_name_list_X = ["中指1", "中指2", "中指3"]
for id in range(0, 3):
Re_Name("左"+old_name_list_X[id], "M_左"+new_name_list_X[id])
Re_Name("右"+old_name_list_X[id], "M_右"+new_name_list_X[id])
old_name_list_X = ["人指1", "人指2", "人指3"]
new_name_list_X = ["人指1", "人指2", "人指3"]
for id in range(0, 3):
Re_Name("左"+old_name_list_X[id], "M_左"+new_name_list_X[id])
Re_Name("右"+old_name_list_X[id], "M_右"+new_name_list_X[id])
old_name_list_X = ["親指0", "親指1", "親指2"]
new_name_list_X = ["大拇指0", "大拇指1", "大拇指2"]
for id in range(0, 3):
Re_Name("左"+old_name_list_X[id], "M_左"+new_name_list_X[id])
Re_Name("右"+old_name_list_X[id], "M_右"+new_name_list_X[id])
Set_Bone_Type("M_左大拇指0", 2, 10)
Set_Bone_Type("M_左无名指1", 2, 10)
Set_Bone_Type("M_左中指1", 2, 10)
Set_Bone_Type("M_左小指1", 2, 10)
Set_Bone_Type("M_左人指1", 2, 10)
Set_Bone_Type("M_右大拇指0", 2, 10)
Set_Bone_Type("M_右无名指1", 2, 10)
Set_Bone_Type("M_右中指1", 2, 10)
Set_Bone_Type("M_右小指1", 2, 10)
Set_Bone_Type("M_右人指1", 2, 10)
c4d.EventAdd()
# ----------------------------------控制器样式----------------------------
Set_Control_Type("M_上半身", c4d.Vector(1, 0, 0), 2, 140, 3)
Set_Control_Type("M_首", c4d.Vector(1, 0, 0), 2, 150, 3)
Set_Control_Type("M_左肩", c4d.Vector(0, 1, 0), 13, 70, 3)
Set_Control_Type("M_右肩", c4d.Vector(0, 0, 1), 13, 70, 3)
Set_Control_Type("M_下半身", c4d.Vector(0, 0, 1), 8, 96, 3)
# ---------------------------------IK控制器------------------------------
Set_IK_Control("M_R_2", "右手IK", "root", c4d.Vector(1, 1, 1), 11, 50, 3)
Set_IK_Control("M_L_2", "左手IK", "root", c4d.Vector(1, 1, 1), 11, 50, 3)
Set_IK_Control("M_右足首D", "右足IK", "root", c4d.Vector(1, 1, 1), 11, 50, 3)
Set_IK_Control("M_左足首D", "左足IK", "root", c4d.Vector(1, 1, 1), 11, 50, 3)
Set_IK_Tag("M_右足D", "M_右足首D", "右足IK", c4d.Vector(0, -184, -488))
Set_IK_Tag("M_左足D", "M_左足首D", "左足IK", c4d.Vector(0, -184, -488))
Set_IK_Tag("M_R_0", "M_R_2", "右手IK", c4d.Vector(0, 0, 270))
Set_IK_Tag("M_L_0", "M_L_2", "左手IK", c4d.Vector(0, 0, 270))
# ------------------------------绑定----------------------
Set_Bind_Tag_Rou("M_右足首D", "右足IK")
Set_Bind_Tag_Rou("M_左足首D", "左足IK")
Set_Bind_Tag_Rou("M_左手首", "左手IK")
Set_Bind_Tag_Rou("M_右手首", "右手IK")
c4d.EventAdd()
# -----------------------重心对象-----------------------
weight_c_obj = c4d.BaseObject(c4d.Onull)
doc.InsertObject(weight_c_obj)
weight_c_obj.InsertUnder(doc.SearchObject("root"))
weight_c_obj.SetName("M_重心")
obj_M_dhb = doc.SearchObject("M_下半身")
weight_c_obj.SetMg(obj_M_dhb.GetMg())
Set_Control_Type("M_重心", c4d.Vector(1, 0, 0), 3, 450, 3)
Insert_With_Position(doc.SearchObject("M_上半身"), weight_c_obj)
Insert_With_Position(doc.SearchObject("M_下半身"), weight_c_obj)
# -----------------------中心对象-----------------------
c_obj = c4d.BaseObject(c4d.Onull)
doc.InsertObject(c_obj)
c_obj.InsertUnder(doc.SearchObject("root"))
c_obj.SetName("M_中心")
c_obj.SetMg(obj_M_dhb.GetMg())
Set_Control_Type("M_中心", c4d.Vector(0, 0, 1), 11, 108, 2)
c_obj[c4d.NULLOBJECT_ASPECTRATIO] = 1.5
Insert_With_Position(weight_c_obj, c_obj)
Insert_With_Position(doc.SearchObject("左足IK"), c_obj)
Insert_With_Position(doc.SearchObject("右足IK"), c_obj)
Insert_With_Position(doc.SearchObject("左手IK"), c_obj)
Insert_With_Position(doc.SearchObject("右手IK"), c_obj)
Insert_With_Position(doc.SearchObject("M_右足D旋转手柄"), doc.SearchObject("M_中心"))
Insert_With_Position(doc.SearchObject("M_左足D旋转手柄"), doc.SearchObject("M_中心"))
Insert_With_Position(doc.SearchObject("M_L_0旋转手柄"), doc.SearchObject("M_中心"))
Insert_With_Position(doc.SearchObject("M_R_0旋转手柄"), doc.SearchObject("M_中心"))
c4d.EventAdd()