From 028b0f55e84537e9a643f4df51ccee59adbe6128 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E5=A8=81=E5=BB=89=E4=BC=AF=E7=88=B5?= <958261649@qq.com> Date: Wed, 20 Apr 2022 15:26:39 +0800 Subject: [PATCH] 0.55 --- MikuMikuRig/mmr_operators/extra.py | 12 +- MikuMikuRig/mmr_operators/physics.py | 48 +++-- MikuMikuRig/mmr_operators/preset.json | 214 +++++++++++++++++++++ MikuMikuRig/mmr_operators/retarget.py | 2 +- MikuMikuRig/mmr_operators/rig.py | 258 +++++++++++++++++++++++++- 5 files changed, 503 insertions(+), 31 deletions(-) diff --git a/MikuMikuRig/mmr_operators/extra.py b/MikuMikuRig/mmr_operators/extra.py index c0c7bba..333f137 100644 --- a/MikuMikuRig/mmr_operators/extra.py +++ b/MikuMikuRig/mmr_operators/extra.py @@ -124,4 +124,14 @@ def execute(self,context): hide_skirt() return{"FINISHED"} -Class_list=[OT_Set_Min_IK_Loop,OT_Hide_Skirt] \ No newline at end of file +class OT_Decorate_MMD_Arm(Operator): + bl_idname = "mmr.decorate_mmd_arm" # python 提示 + bl_label = "Interface" + bl_options = {'REGISTER', 'UNDO'} + + def execute(self,context): + rig.decorate_mmd_arm(context) + return{"FINISHED"} + + +Class_list=[OT_Set_Min_IK_Loop,OT_Hide_Skirt,OT_Decorate_MMD_Arm] \ No newline at end of file diff --git a/MikuMikuRig/mmr_operators/physics.py b/MikuMikuRig/mmr_operators/physics.py index cbe3463..986ca52 100644 --- a/MikuMikuRig/mmr_operators/physics.py +++ b/MikuMikuRig/mmr_operators/physics.py @@ -142,24 +142,20 @@ def convert_rigid_body_to_cloth(context): bm=bmesh.new() bm.from_mesh(mesh) #bmesh.ops.edgenet_fill(bm, edges=bm.edges, mat_nr=0, use_smooth=True, sides=4) - bmesh.ops.holes_fill(bm, edges=bm.edges, sides=4) - - #删除大于四边的面 - #remove ngon - '''for f in bm.faces: - if len(f.verts)>4: - bm.faces.remove(f)''' - #删除多余边 - #remove extra edge - for e in bm.edges: - true_edge=False - for i in edge_index: - if e.verts[0].index in i and e.verts[1].index in i: - true_edge=True - break - if true_edge==False: - bm.edges.remove(e) - bm.faces.ensure_lookup_table() + if mmr_property.cloth_convert_mod!='Bone Constrain': + bmesh.ops.holes_fill(bm, edges=bm.edges, sides=4) + + #删除多余边 + #remove extra edge + for e in bm.edges: + true_edge=False + for i in edge_index: + if e.verts[0].index in i and e.verts[1].index in i: + true_edge=True + break + if true_edge==False: + bm.edges.remove(e) + bm.faces.ensure_lookup_table() #尝试标记出头发,飘带 #try mark hair or ribbon vertex @@ -313,7 +309,7 @@ def convert_rigid_body_to_cloth(context): #extend side vertex bm.verts.index_update( ) bm.faces.ensure_lookup_table() - new_side_verts=[None for i in range(len(bm.verts))] + new_side_verts={} for v in side_verts: for e in v.link_edges: if e not in side_edges: @@ -321,16 +317,18 @@ def convert_rigid_body_to_cloth(context): new_location=v.co*2-e.verts[1].co else: new_location=v.co*2-e.verts[0].co + #这里改了 + new_vert=bm.verts.new(new_location,v) + new_side_verts[v.index]=new_vert break - new_vert=bm.verts.new(new_location,v) - new_side_verts[v.index]=new_vert + for e in side_edges: vert1=e.verts[0] vert2=e.verts[1] - vert3=new_side_verts[vert2.index] - vert4=new_side_verts[vert1.index] - if vert3 != None and vert4 != None: + if vert2.index in new_side_verts and vert1.index in new_side_verts: + vert3=new_side_verts[vert2.index] + vert4=new_side_verts[vert1.index] bm.faces.new([vert1,vert2,vert3,vert4]) bm.verts.ensure_lookup_table() @@ -478,7 +476,7 @@ class OT_Convert_Rigid_Body_To_Cloth(Operator): bl_options = {'REGISTER', 'UNDO'} def execute(self,context): - if bpy.app.version[1]>=93: + if bpy.app.version>=(2, 93, 0): convert_rigid_body_to_cloth(context) else: alert_error('警告','该功能需要blender2.93及更新版本') diff --git a/MikuMikuRig/mmr_operators/preset.json b/MikuMikuRig/mmr_operators/preset.json index bc58860..5fe2117 100644 --- a/MikuMikuRig/mmr_operators/preset.json +++ b/MikuMikuRig/mmr_operators/preset.json @@ -479,6 +479,220 @@ "toe.R", false ] + }, + "VRM": { + "Hips": [ + "spine", + false + ], + "Spine": [ + "spine.002", + false + ], + "Chest": [ + "spine.003", + false + ], + "Neck": [ + "spine.004", + false + ], + "Head": [ + "spine.006", + false + ], + "LeftEye": [ + "eye.L", + false + ], + "RightEye": [ + "eye.R", + false + ], + "Shoulder.L": [ + "shoulder.L", + false + ], + "Upper Arm.L": [ + "upper_arm.L", + false + ], + "Lower Arm.L": [ + "forearm.L", + false + ], + "Hand.L": [ + "hand.L", + false + ], + "Index Proximal.L": [ + "f_index.01.L", + false + ], + "Index Intermediate.L": [ + "f_index.02.L", + false + ], + "Index Distal.L": [ + "f_index.03.L", + false + ], + "Little Proximal.L": [ + "f_pinky.01.L", + false + ], + "Little Intermediate.L": [ + "f_pinky.02.L", + false + ], + "Little Distal.L": [ + "f_pinky.03.L", + false + ], + "Middle Proximal.L": [ + "f_middle.01.L", + false + ], + "Middle Intermediate.L": [ + "f_middle.02.L", + false + ], + "Middle Distal.L": [ + "f_middle.03.L", + false + ], + "Ring Proximal.L": [ + "f_ring.01.L", + false + ], + "Ring Intermediate.L": [ + "f_ring.02.L", + false + ], + "Ring Distal.L": [ + "f_ring.03.L", + false + ], + "Thumb Proximal.L": [ + "thumb.01.L", + false + ], + "Thumb Intermediate.L": [ + "thumb.02.L", + false + ], + "Thumb Distal.L": [ + "thumb.03.L", + false + ], + "Shoulder.R": [ + "shoulder.R", + false + ], + "Upper Arm.R": [ + "ArmTwist_R", + false + ], + "Lower Arm.R": [ + "forearm.R", + false + ], + "Hand.R": [ + "hand.R", + false + ], + "Index Proximal.R": [ + "f_index.01.R", + false + ], + "Index Intermediate.R": [ + "f_index.02.R", + false + ], + "Index Distal.R": [ + "f_index.03.R", + false + ], + "Little Proximal.R": [ + "f_pinky.01.R", + false + ], + "Little Intermediate.R": [ + "f_pinky.02.R", + false + ], + "Little Distal.R": [ + "f_pinky.03.R", + false + ], + "Middle Proximal.R": [ + "f_middle.01.R", + false + ], + "Middle Intermediate.R": [ + "f_middle.02.R", + false + ], + "Middle Distal.R": [ + "f_middle.03.R", + false + ], + "Ring Proximal.R": [ + "f_ring.01.R", + false + ], + "Ring Intermediate.R": [ + "f_ring.02.R", + false + ], + "Ring Distal.R": [ + "f_ring.03.R", + false + ], + "Thumb Proximal.R": [ + "thumb.01.R", + false + ], + "Thumb Intermediate.R": [ + "thumb.02.R", + false + ], + "Thumb Distal.R": [ + "thumb.03.R", + false + ], + "Upper Leg.L": [ + "thigh.L", + false + ], + "Lower Leg.L": [ + "shin.L", + false + ], + "Foot.L.001": [ + "foot.L", + false + ], + "Foot.L.002": [ + "toe.L", + false + ], + "Upper Leg.R": [ + "thigh.R", + false + ], + "Lower Leg.R": [ + "shin.R", + false + ], + "Foot.R.001": [ + "foot.R", + false + ], + "Foot.R.002": [ + "toe.R", + false + ] } }, "retarget": { diff --git a/MikuMikuRig/mmr_operators/retarget.py b/MikuMikuRig/mmr_operators/retarget.py index 542bfc2..c83136b 100644 --- a/MikuMikuRig/mmr_operators/retarget.py +++ b/MikuMikuRig/mmr_operators/retarget.py @@ -61,7 +61,7 @@ def retarget_mixmao(OT,context): rigify_action.name=action_name old_frame=context.scene.frame_current - context.scene.frame_current=frame_range[0] + context.scene.frame_current=int(frame_range[0]) #写入MMR预设 fbx_preset=preset.preset_dict_dict['retarget'][mmr_property.retarget_preset_name] diff --git a/MikuMikuRig/mmr_operators/rig.py b/MikuMikuRig/mmr_operators/rig.py index 16b4aec..9d45ea4 100644 --- a/MikuMikuRig/mmr_operators/rig.py +++ b/MikuMikuRig/mmr_operators/rig.py @@ -348,18 +348,22 @@ def world_rotate(posebone_a,posebone_b,vector=(0,1,0),size=-0.2618): #修正骨骼轴向 positive_z_bone=[ 'shoulder.L','shoulder.R', - ] - positive_x_bone=[ + 'f_index.01.L','f_index.02.L','f_index.03.L', 'f_middle.01.L','f_middle.02.L','f_middle.03.L', 'f_ring.01.L','f_ring.02.L','f_ring.03.L', 'f_pinky.01.L','f_pinky.02.L','f_pinky.03.L', - ] - negative_x_bone=[ + 'f_index.01.R','f_index.02.R','f_index.03.R', 'f_middle.01.R','f_middle.02.R','f_middle.03.R', 'f_ring.01.R','f_ring.02.R','f_ring.03.R', 'f_pinky.01.R','f_pinky.02.R','f_pinky.03.R', + ] + positive_x_bone=[ + + ] + negative_x_bone=[ + ] negative_y_bone=[ 'hand.L','upper_arm.L','forearm.L','hand.R','upper_arm.R','forearm.R', @@ -794,4 +798,250 @@ def world_rotate(posebone_a,posebone_b,vector=(0,1,0),size=-0.2618): alert_error("提示","完成"+'匹配骨骼数:'+str(match_bone_nunber)) return(True) +def decorate_mmd_arm(context): + + if check_arm() is False: + return + + mmd_arm=context.view_layer.objects.active + + pose_bones=mmd_arm.pose.bones + edit_bones=mmd_arm.data.edit_bones + bones=mmd_arm.data.bones + mmd_dict={} + + #生成字典 + for pose_bone in pose_bones: + mmd_bone=pose_bone.mmd_bone + name_j=mmd_bone.name_j + mmd_dict[name_j]=pose_bone.name + + primary_bone_list=[ + '全ての親','センター','グルーブ','下半身','上半身','上半身2','首','頭', + '腰','グルーブ2','グルーブ','センター2', + '左足','左足IK','左ひざ', + '右足','右足IK','右ひざ', + '左足IK親','右足IK親', + '左肩','左腕','左ひじ','左手首', + '右肩','右腕','右ひじ','右手首', + '左肩P','左腕捩','左手捩', + '右肩P','右腕捩','右手捩', + + ] + secondary_bone_list=[ + '左目','右目','両目', + '左足首','左足先EX', + '右足首','右足先EX', + '左つま先IK','右つま先IK', + '左親指0','左親指1','左親指2', + '左人指1','左人指2','左人指3', + '左中指1','左中指2','左中指3', + '左薬指1','左薬指2','左薬指3', + '左小指1','左小指2','左小指3', + '右親指0','右親指1','右親指2', + '右人指1','右人指2','右人指3', + '右中指1','右中指2','右中指3', + '右薬指1','右薬指2','右薬指3', + '右小指1','右小指2','右小指3', + ] + + def set_bone_layer(bone,number): + + bone.layers[number]=True + for i in range(32): + if i != number: + bone.layers[i]=False + + def connect_bone_chain(bone_chain): + if bone_chain[0] in mmd_dict: + length=len(bone_chain) + for i in range(length-1): + if bone_chain[i+1] in mmd_dict: + name=mmd_dict[bone_chain[i]] + parent_name=mmd_dict[bone_chain[i+1]] + bone=edit_bones[name] + parent_bone=edit_bones[parent_name] + bone.parent=parent_bone + parent_bone.tail=bone.head + bone.use_connect=True + else: + return + else: + return + + bone_chain_list=[ + ['左手首','左手捩','左ひじ','左腕捩','左腕'], + ['右手首','右手捩','右ひじ','右腕捩','右腕'], + ['頭','首','上半身2','上半身'] + ] + arm_bone_dict={ + '頭':(None,(None,None),(None,None),(None,None)), + '首':(None,(None,None),(None,None),(None,None)), + '上半身2':(None,(None,None),(None,None),(None,None)), + '上半身':(None,(None,None),(None,None),(None,None)), + '左肩':(None,(None,None),(None,None),(None,None)), + '右肩':(None,(None,None),(None,None),(None,None)), + '左手捩':(None,None,(None,None),None), + '左腕捩':(None,None,(None,None),None), + '右手捩':(None,None,(None,None),None), + '右腕捩':(None,None,(None,None),None), + '左腕':(-2.463,(None,None),None,(None,None)), + '右腕':(-0.679,(None,None),None,(None,None)), + '左ひじ':(-2.48,None,None,(-0.001,None)), + '右ひじ':(-0.66,None,None,(-0.001,None)), + '左手首':(None,(None,None),None,(None,None)), + '右手首':(None,(None,None),None,(None,None)), + } + def extend_bone(bone): + + parent_bone=bone.parent + bone_vector=bone.head-parent_bone.head + bone.tail=bone.head+bone_vector + bone.roll=parent_bone.roll + + extend_bone_list=[ + '左親指2', + '左人指3', + '左中指3', + '左薬指3', + '左小指3', + '右親指2', + '右人指3', + '右中指3', + '右薬指3', + '右小指3', + ] + + bpy.ops.object.mode_set(mode = 'EDIT') + + for name_j,name in mmd_dict.items(): + pose_bone=pose_bones[name] + edit_bone=edit_bones[name] + + #延长骨骼 + if name_j in extend_bone_list: + extend_bone(edit_bone) + + #断开先骨骼 + if '先' in name_j: + edit_bone.use_connect=False + + #对称轴向 + if '左' in name_j: + name_j_R=name_j.replace('左','右') + if name_j_R in mmd_dict: + edit_bone_R=edit_bones[mmd_dict[name_j_R]] + edit_bone_R.roll=-edit_bone.roll + + #设置特定轴向 + if name_j in arm_bone_dict: + bone_setting=arm_bone_dict[name_j] + edit_bone.roll=bone_setting[0] or edit_bone.roll + + #链接骨骼 + for bone_chain in bone_chain_list: + connect_bone_chain(bone_chain) + + #修改手掌骨骼 + def adjust_hand_bone(hand_name,finger1_name,finger2_name): + if hand_name and finger1_name and finger2_name in mmd_dict: + hand_bone=edit_bones[mmd_dict[hand_name]] + finger1_bone=edit_bones[mmd_dict[finger1_name]] + finger2_bone=edit_bones[mmd_dict[finger2_name]] + hand_bone.tail=(finger1_bone.head+finger2_bone.head)/2 + + adjust_hand_bone('左手首','左中指1','左薬指1') + adjust_hand_bone('右手首','右中指1','右薬指1') + + bpy.ops.object.mode_set(mode = 'OBJECT') + + #设置层可见性 + #mmd_arm.data.layers[0]=True + #设置骨骼族颜色 + bone_color_dict={ + 'Root':'THEME09', + 'センター':'THEME09', + 'IK':'THEME02', + 'IK':'THEME02', + '体(上)':'THEME04', + '体上':'THEME04', + '上半身':'THEME04', + '腕':'THEME03', + '指':'THEME04', + '足':'THEME03', + '体(下)':'THEME04', + '下半身':'THEME04', + } + + #设置骨骼组颜色 + for bone_group in mmd_arm.pose.bone_groups: + name=bone_group.name + if name in bone_color_dict: + bone_group.color_set=bone_color_dict[name] + + #设置骨骼层 + for pose_bone in pose_bones: + bone=pose_bone.bone + name_j=pose_bone.mmd_bone.name_j + + if pose_bone.bone_group and pose_bone.bone_group.name in bone_color_dict: + set_bone_layer(bone,0) + else: + set_bone_layer(bone,1) + + #设置IK限制 + if name_j in arm_bone_dict: + pose_bone.lock_location=[False,False,False] + pose_bone.ik_stiffness_x=0.1 + pose_bone.ik_stiffness_y=0.1 + pose_bone.ik_stiffness_z=0.1 + bone_setting=arm_bone_dict[name_j] + + if bone_setting[1]: + pose_bone.lock_ik_x=False + pose_bone.ik_min_x=bone_setting[1][0] or pose_bone.ik_min_x + pose_bone.ik_max_x=bone_setting[1][1] or pose_bone.ik_max_x + else: + pose_bone.lock_ik_x=True + if bone_setting[2]: + pose_bone.lock_ik_y=False + pose_bone.ik_min_y=bone_setting[2][0] or pose_bone.ik_min_y + pose_bone.ik_max_y=bone_setting[2][1] or pose_bone.ik_max_y + else: + pose_bone.lock_ik_y=True + if bone_setting[3]: + pose_bone.lock_ik_z=False + pose_bone.ik_min_z=bone_setting[3][0] or pose_bone.ik_min_z + pose_bone.ik_max_z=bone_setting[3][1] or pose_bone.ik_max_z + else: + pose_bone.lock_ik_z=True + + #设置骨骼弯曲 + def world_rotate(posebone_a,posebone_b,vector=(0,1,0),size=-0.2618): + + v1=posebone_b.head-posebone_a.head + v2=v1.cross(vector) + mat1=mathutils.Matrix.Rotation(size,4,v2) + mat2=posebone_a.matrix.inverted() @ mat1 @ posebone_a.matrix + q=mat2.to_quaternion() + posebone_a.rotation_mode = 'QUATERNION' + posebone_a.rotation_quaternion = q + + rotate_list=[ + ['左ひじ','左腕',(0,1,0),0.2618], + ['右ひじ','右腕',(0,1,0),0.2618], + ] + for order in rotate_list: + if order[0] not in mmd_dict or order[1] not in mmd_dict: + continue + posebone_a=pose_bones[mmd_dict[order[0]]] + posebone_b=pose_bones[mmd_dict[order[1]]] + world_rotate(posebone_a,posebone_b,order[2],order[3]) + + #开启自动IK + bpy.context.object.pose.use_auto_ik = True + #设置各自中心 + bpy.context.scene.tool_settings.transform_pivot_point = 'INDIVIDUAL_ORIGINS' + + Class_list=[] \ No newline at end of file