Created
September 16, 2020 14:12
-
-
Save UuuNyaa/299dcae8fe7f95cced4a8b8699cba447 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # -*- coding: utf-8 -*- | |
| # Issue: https://github.com/powroupi/blender_mmd_tools/issues/185 | |
| # (patch script for model from https://free3d.com/3d-model/female-robot-39128.html) | |
| # | |
| # How to use: | |
| # 1. Open robot.blend | |
| # 2. Open this file in Blender Text Editor, and click [Run Script] to run this script | |
| # 3. Import a VMD file with import option: [Scale] 0.48, enable [Treat Current Pose as Rest Pose] | |
| import bpy | |
| name_map_csv = ''' | |
| 上半身,c_spine_01.x | |
| 上半身2,c_spine_02.x | |
| 首,c_neck.x | |
| 頭,c_head.x | |
| 左肩,c_shoulder.l | |
| 左腕,arm_ik_nostr.l | |
| 左ひじ,forearm_ik_nostr.l | |
| 左手首,hand.l | |
| 左人指1,c_index1.l | |
| 左人指2,c_index2.l | |
| 左人指3,c_index3.l | |
| 左中指1,c_middle1.l | |
| 左中指2,c_middle2.l | |
| 左中指3,c_middle3.l | |
| 左薬指1,c_ring1.l | |
| 左薬指2,c_ring2.l | |
| 左薬指3,c_ring3.l | |
| 左小指1,c_pinky1.l | |
| 左小指2,c_pinky2.l | |
| 左小指3,c_pinky3.l | |
| 左親指0,c_thumb1.l | |
| 左親指1,c_thumb2.l | |
| 左親指2,c_thumb3.l | |
| 右肩,c_shoulder.r | |
| 右腕,arm_ik_nostr.r | |
| 右ひじ,forearm_ik_nostr.r | |
| 右手首,hand.r | |
| 右人指1,c_index1.r | |
| 右人指2,c_index2.r | |
| 右人指3,c_index3.r | |
| 右中指1,c_middle1.r | |
| 右中指2,c_middle2.r | |
| 右中指3,c_middle3.r | |
| 右薬指1,c_ring1.r | |
| 右薬指2,c_ring2.r | |
| 右薬指3,c_ring3.r | |
| 右小指1,c_pinky1.r | |
| 右小指2,c_pinky2.r | |
| 右小指3,c_pinky3.r | |
| 右親指0,c_thumb1.r | |
| 右親指1,c_thumb2.r | |
| 右親指2,c_thumb3.r | |
| 下半身,c_root.x | |
| 左足,thigh_ik_nostr.l | |
| 左ひざ,leg_ik_nostr.l | |
| 左足首,foot.l | |
| 左足IK,heel_ik.l | |
| 左つま先IK,toe_ik.l | |
| 右足,thigh_ik_nostr.r | |
| 右ひざ,leg_ik_nostr.r | |
| 右足首,foot.r | |
| 右足IK,heel_ik.r | |
| 右つま先IK,toe_ik.r | |
| センター,center | |
| 全ての親,c_pos | |
| ''' | |
| def set_bone(target_edit_bones, **kwargs): | |
| if kwargs['name'] not in target_edit_bones: | |
| b = target_edit_bones.new(name=kwargs['name']) | |
| for key in kwargs: | |
| setattr(b, key, kwargs[key]) | |
| def patch_bones(armObj): | |
| from math import radians | |
| from mathutils import Vector | |
| bpy.ops.object.mode_set(mode='EDIT') | |
| edit_bones = armObj.data.edit_bones | |
| set_bone(edit_bones, | |
| name='center', | |
| use_connect=False, | |
| parent=edit_bones['c_pos'], | |
| head=(0,0,0.76), | |
| tail=(0,0,0.56) | |
| ) | |
| set_bone(edit_bones, | |
| name='heel_ik.l', | |
| use_connect=False, | |
| parent = edit_bones['c_traj'], | |
| head = edit_bones['c_leg_fk.l'].tail, | |
| tail = edit_bones['c_leg_fk.l'].tail - 0.1 * edit_bones['c_foot_ik.l'].vector.normalized() | |
| ) | |
| set_bone(edit_bones, | |
| name = 'toe_ik.l', | |
| use_connect = False, | |
| parent = edit_bones['heel_ik.l'], | |
| head = edit_bones['foot.l'].tail, | |
| tail = edit_bones['foot.l'].tail + Vector((0,0,-0.1)) | |
| ) | |
| set_bone(edit_bones, | |
| name='heel_ik.r', | |
| use_connect=False, | |
| parent=edit_bones['c_traj'], | |
| head = edit_bones['c_leg_fk.r'].tail, | |
| tail = edit_bones['c_leg_fk.r'].tail - 0.1 * edit_bones['c_foot_ik.r'].vector.normalized() | |
| ) | |
| set_bone(edit_bones, | |
| name = 'toe_ik.r', | |
| use_connect = False, | |
| parent = edit_bones['heel_ik.r'], | |
| head = edit_bones['foot.r'].tail, | |
| tail = edit_bones['foot.r'].tail + Vector((0,0,-0.1)) | |
| ) | |
| # disable leg <-> foot IK | |
| bpy.data.objects['Tifa_rig'].data.edit_bones['foot.r'].parent = bpy.data.objects['Tifa_rig'].data.edit_bones['leg_ik_nostr.r'] | |
| bpy.data.objects['Tifa_rig'].data.edit_bones['foot.r'].use_inherit_rotation = True | |
| bpy.data.objects['Tifa_rig'].data.edit_bones['foot.l'].parent = bpy.data.objects['Tifa_rig'].data.edit_bones['leg_ik_nostr.l'] | |
| bpy.data.objects['Tifa_rig'].data.edit_bones['foot.l'].use_inherit_rotation = True | |
| # neck <-> head connection | |
| bpy.data.objects['Tifa_rig'].data.edit_bones['head_scale_fix.x'].parent = bpy.data.objects['Tifa_rig'].data.edit_bones['c_neck.x'] | |
| bpy.data.objects['Tifa_rig'].data.edit_bones['head_scale_fix.x'].use_inherit_rotation = True | |
| def set_constraint(target_pose_bone, type, **kwargs): | |
| if kwargs['name'] not in target_pose_bone.constraints: | |
| c = target_pose_bone.constraints.new(type) | |
| for key in kwargs: | |
| setattr(c, key, kwargs[key]) | |
| def remove_all_constraints(armObj): | |
| # remove all constraints | |
| for (c,b) in [(c,b) for b in bpy.data.objects['Tifa_rig'].pose.bones for c in b.constraints if ('COPY_SCALE' in c.type or 'COPY_TRANS' in c.type )]: | |
| b.constraints.remove(c) | |
| def patch_ik(armObj): | |
| from math import radians | |
| bpy.ops.object.mode_set(mode='POSE') | |
| pose_bones = armObj.pose.bones | |
| ## root | |
| set_constraint(pose_bones['c_root_master.x'],'COPY_LOCATION', | |
| name = 'MMD_loc', | |
| target = armObj, | |
| subtarget = 'center', | |
| owner_space = 'LOCAL', | |
| target_space = 'LOCAL', | |
| invert_y = True, | |
| invert_z = True | |
| ) | |
| set_constraint(pose_bones['c_root_master.x'],'COPY_ROTATION', | |
| name = 'MMD_rot', | |
| target = armObj, | |
| subtarget = 'center', | |
| owner_space = 'LOCAL', | |
| target_space = 'LOCAL', | |
| invert_y = True | |
| ) | |
| # fix neck <-> head connection | |
| for (c,b) in [(c,b) for b in bpy.data.objects['Tifa_rig'].pose.bones if b.name == 'head_scale_fix.x' for c in b.constraints if c.type == 'CHILD_OF']: | |
| b.constraints.remove(c) | |
| ## remove hand IK | |
| for (c,b) in [(c,b) for b in bpy.data.objects['Tifa_rig'].pose.bones for c in b.constraints if hasattr(c,'subtarget') and 'c_hand_ik' in c.subtarget]: | |
| b.constraints.remove(c) | |
| ## hand.[lr] | |
| # disable Hand rotation lock | |
| bpy.data.objects['Tifa_rig'].pose.bones['hand.l'].lock_rotation = (False,False,False) | |
| # add 'Child Of' constraint | |
| set_constraint(bpy.data.objects['Tifa_rig'].pose.bones['hand.l'],'CHILD_OF', | |
| name = 'Child Of', | |
| target = bpy.data.objects['Tifa_rig'], | |
| subtarget = 'forearm_ik_nostr.l', | |
| set_inverse_pending = True | |
| ) | |
| # move 'Child Of' constraint on top | |
| bpy.data.objects['Tifa_rig'].pose.bones['hand.l'].constraints.move(len(bpy.data.objects['Tifa_rig'].pose.bones['hand.l'].constraints)-1,0) | |
| ## forearm_ik_nostr.[lr] | |
| # disable forearm rotation lock | |
| bpy.data.objects['Tifa_rig'].pose.bones['forearm_ik_nostr.l'].lock_rotation = (False,False,False) | |
| ## arm_ik_nostr.[lr] | |
| # disable arm rotation lock | |
| bpy.data.objects['Tifa_rig'].pose.bones['arm_ik_nostr.l'].lock_rotation = (False,False,False) | |
| ## remove foot and leg IK | |
| for (c,b) in [(c,b) for b in bpy.data.objects['Tifa_rig'].pose.bones for c in b.constraints if c.type == 'COPY_ROTATION' and 'foot_ik' in c.subtarget]: | |
| b.constraints.remove(c) | |
| for (c,b) in [(c,b) for b in bpy.data.objects['Tifa_rig'].pose.bones if 'leg_ik_nostr' in b.name for c in b.constraints if c.type == 'IK']: | |
| b.constraints.remove(c) | |
| for (c,b) in [(c,b) for b in bpy.data.objects['Tifa_rig'].pose.bones for c in b.constraints if hasattr(c,'subtarget') and 'c_toes_ik' in c.subtarget]: | |
| b.constraints.remove(c) | |
| ## foot.[lr] | |
| set_constraint(bpy.data.objects['Tifa_rig'].pose.bones['foot.l'],'IK', | |
| name = 'MMD_IK', | |
| target = bpy.data.objects['Tifa_rig'], | |
| subtarget = 'toe_ik.l', | |
| chain_count = 1, | |
| iterations = 3 | |
| ) | |
| set_constraint(bpy.data.objects['Tifa_rig'].pose.bones['foot.r'],'IK', | |
| name = 'MMD_IK', | |
| target = bpy.data.objects['Tifa_rig'], | |
| subtarget = 'toe_ik.r', | |
| chain_count = 1, | |
| iterations = 3 | |
| ) | |
| ## leg_ik_nostr.[lr] | |
| bpy.data.objects['Tifa_rig'].pose.bones['leg_ik_nostr.l'].rotation_mode = 'XYZ' | |
| set_constraint(bpy.data.objects['Tifa_rig'].pose.bones['leg_ik_nostr.l'],'LIMIT_ROTATION', | |
| name = 'Limit Rotation', | |
| owner_space = 'LOCAL', | |
| min_z = radians(0), max_z = radians(+180), | |
| use_limit_x = True, | |
| use_limit_y = True, | |
| use_limit_z = True | |
| ) | |
| set_constraint(bpy.data.objects['Tifa_rig'].pose.bones['leg_ik_nostr.l'],'IK', | |
| name = 'MMD_IK', | |
| target = bpy.data.objects['Tifa_rig'], | |
| subtarget = 'heel_ik.l', | |
| chain_count = 3, | |
| iterations = 40 | |
| ) | |
| bpy.data.objects['Tifa_rig'].pose.bones['leg_ik_nostr.r'].rotation_mode = 'XYZ' | |
| set_constraint(bpy.data.objects['Tifa_rig'].pose.bones['leg_ik_nostr.r'],'LIMIT_ROTATION', | |
| name = 'Limit Rotation', | |
| owner_space = 'LOCAL', | |
| min_z = radians(0), max_z = radians(+180), | |
| use_limit_x = True, | |
| use_limit_y = True, | |
| use_limit_z = True | |
| ) | |
| set_constraint(bpy.data.objects['Tifa_rig'].pose.bones['leg_ik_nostr.r'],'IK', | |
| name = 'MMD_IK', | |
| target = bpy.data.objects['Tifa_rig'], | |
| subtarget = 'heel_ik.r', | |
| chain_count = 3, | |
| iterations = 40 | |
| ) | |
| ## thigh.[lr] | |
| bpy.data.objects['Tifa_rig'].pose.bones['thigh_ik_nostr.l'].lock_rotation = (False,False,False) | |
| bpy.data.objects['Tifa_rig'].pose.bones['thigh_ik_nostr.r'].lock_rotation = (False,False,False) | |
| def patch_pose(armObj): | |
| from math import radians | |
| from mathutils import Euler, Quaternion | |
| bpy.ops.object.mode_set(mode='POSE') | |
| pose_bones = armObj.pose.bones | |
| for b in pose_bones: | |
| b.matrix_basis.identity() | |
| pose_bones['heel_ik.l'].matrix = pose_bones['heel_ik.l'].matrix @ Euler((0.0,0.0,radians(-14.0))).to_matrix().to_4x4() | |
| #pose_bones['heel_ik.l'].location = (-0.1,0.05,0) # (-0.10281755775213242, 0.03844242915511131, 0.03638792783021927) | |
| #pose_bones['toe_ik.l'].location = (-0.005,0,0) # (+0.009050948545336723, 0.04268583655357361, -0.05635549873113632) | |
| pose_bones['heel_ik.r'].matrix = pose_bones['heel_ik.r'].matrix @ Euler((0.0,0.0,radians(+14.0))).to_matrix().to_4x4() | |
| #pose_bones['heel_ik.r'].location = (+0.1,0.05,0) # (+0.10281755775213242, 0.03844242915511131, 0.03638792783021927) | |
| #pose_bones['toe_ik.r'].location = (+0.005,0,0) # (-0.009050948545336723, 0.04268583655357361, -0.05635549873113632) | |
| pose_bones['center'].location = (0,-0.005,0) # (0, -0.03882210701704025, 0.011079655028879642) | |
| pose_bones['thigh_ik_nostr.l'].rotation_mode = 'XYZ' | |
| pose_bones['thigh_ik_nostr.l'].rotation_euler = (-0.021631652489304543, +0.2279348373413086, -0.025270408019423485) | |
| pose_bones['heel_ik.l'].location = (-0.10281755775213242, 0.03844242915511131, 0.03638792783021927) | |
| pose_bones['toe_ik.l'].location = (+0.009050948545336723, 0.04268583655357361, -0.05635549873113632) | |
| pose_bones['thigh_ik_nostr.r'].rotation_mode = 'XYZ' | |
| pose_bones['thigh_ik_nostr.r'].rotation_euler = (-0.021631654351949692, -0.2279348522424698, 0.025270409882068634) | |
| pose_bones['heel_ik.r'].location = (+0.10281755775213242, 0.03844242915511131, 0.03638792783021927) | |
| pose_bones['toe_ik.r'].location = (-0.009050948545336723, 0.04268583655357361, -0.05635549873113632) | |
| pose_bones['center'].location = (0, -0.03882210701704025, 0.011079655028879642) | |
| pose_bones['c_root.x'].location = (4.2299497238218464e-13, -0.005019493401050568, -0.03553156927227974) | |
| def patch_mmd_name(armObj): | |
| pose_bones = armObj.pose.bones | |
| for l in name_map_csv.strip().split('\n'): | |
| name_j, name_e = l.split(',') | |
| if name_e in pose_bones: | |
| pose_bones[name_e].mmd_bone.name_j = name_j | |
| try: | |
| bpy.ops.object.mode_set(mode='OBJECT') | |
| except: | |
| pass | |
| armObj = bpy.data.objects['Tifa_rig'] | |
| armObj.hide = False | |
| armObj.select = True | |
| bpy.context.view_layer.objects.active = armObj | |
| patch_bones(armObj) | |
| patch_ik(armObj) | |
| patch_pose(armObj) | |
| patch_mmd_name(armObj) | |
| bpy.ops.object.mode_set(mode='POSE') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment