LoginSignup
0
0

他のソフトからインポートしたアーマチュアにRigifyリグを作成する

Last updated at Posted at 2024-05-23

Blenderでキャラクターのデータを作成する時に
Blenderだけで完結すればいいのですが 他のソフトで作成されたデータに動きを付けることもあります

他のソフトで作成されたアーマチュア(ボーン)を利用して
Blender標準搭載のリグシステムのRigifyのリグを作成する手順を考えたいと思います。

今回はmixamoからダウンロードしたモデルを使用します
(mixiamoのモデルからRigifyリグを生成するアドオン等はありますが 手順の例としての利用です)

バージョン4.0以降ではボーン周りに変更されていますが
私が現在業務で使用しているのは3.3のため3.3の内容です

トランスフォームの調整

mixamoモデルをインポートした状態ではアーマチュアのオブジェクトにスケール等のトランスフォームが入っています
Rigifyではオブジェクトにトランスフォームは無視した状態で作成されますので
トランスフォームを適用します
image.png

このままだと アニメーションデータのルートボーンの移動量が100倍になってしまっているので
グラフエディタでルートボーンの移動のカーブのみ選択して 1/100に変更します
image.png
グラフエディタはX軸が時間軸 Y軸がそれぞれのチャンネルの数値なので
グラフエディタのピボットポイントを2Dカーソルにして カーソルのY軸が0の状態で
Y軸に0.01倍に拡大 (S Y 0.01 とキー入力)すればいいことになります
image.png

Rigifyのリグのトランスフォームが初期値になるだけなので
作成後 リグのトランスフォームを揃えてしまっても問題ないかもしれません

編集モードでのボーン調整

Rigifyのリグでは 背骨 腕 脚等の一連のものとして利用するボーンは
親子関係の上で 接続されている必要があります
単純に「接続」をチェックしただけでは親側のテールの位置に子のボーンが移動してしまうので
子のヘッドの位置に親ボーンのテールを移動させます
image.png
Shiftキーを押しながら 親側のボーンのテール 子側のボーンのヘッド の順に選択して
スナップメニューの「選択→アクティブ」を実行することで位置を揃えます
image.png

mixamoのボーンで位置を揃えて接続する必要があるのは背骨と頭部 足先と手首親指のボーンになります
image.png

またリグの設定の都合で首の手前の背骨のボーンのテールも位置は揃えておきます

手元のmixamoモデルでは
左ひじはインポート時に「接続」がチェックされていたものの 右ひじが接続になっていない
といったこともあったので選択していないボーンもチェックする必要があるかもしれません

カカトのボーンの追加

Rigifyで脚の部分の接地の挙動を利用するために カカトのボーンを追加する必要があります
image.png

カカトの位置に横向きにボーンを作成して heel.L heel.Rと名付け
足先の接地部分のボーンの子に設定します 「変形」のチェックボックスは外しておきます

Rigifyのメタリグ設定

Rigifyは ポーズモードでのボーンプロパティに表示される
Rigify Typeという設定項目の情報を元にリグを作成します
キャプチャはRigifyの標準のメタリグの左上腕部の標準の設定です
image.png

背骨や腕などの操作に適したリグのプリセットが用意されていて
Rig typeから選択できます それぞれのタイプについては以前解説しました ので参照してください

このRigify Typeでボーンの分割数や リグを配置するボーンレイヤ
形式によってはリグの表示に使うシェイプの設定もできます

Rigifyの機能で作成できるアーマチュアの主要な部分の初期設定をキャプチャしてみるとこんな感じです
image.png

キャプチャ中の腕や脚のボーンでは
ひねりを加えるために肩と肘等の関節間を2分割(Limb Segments)する入っていて
Blender独自のボーン形式のベンディボーンで中間部分が滑らかに変形する設定になっています
ゲーム等のモーション作成では逆に邪魔になってしまう設定です

これらの設定を自前のボーンに設定していくのは大変です。
関連する設定を目的に合ったように自動設定するスクリプトを作成してみました

メタリグ情報自動設定スクリプト

先に調整を行ったボーンにこのような設定を付けるスクリプトを作成しました
image.png
手動で設定した時の初期値に近いものですが
Limb Segmentsを1にしたり ボーンレイヤの設定を調整して手間を減らしてあります。

目的のアーマチュアオブジェクトを選択して実行してください

Apply_rigify_settings_mixamo.py
import bpy
## 外部から持ってきたボーンにRigifyセッティングをつける
setting_List = [
    ['mixamorig:Neck', 'neck_base'], ['mixamorig:Hips', 'spine_base'], 
    ['mixamorig:LeftArm', 'LeftArm'], ['mixamorig:RightArm', 'RightArm'], 
    ['mixamorig:LeftUpLeg', 'LeftLeg'], ['mixamorig:RightUpLeg', 'RightLeg'], 
    ['mixamorig:LeftHandThumb1', 'finger'], ['mixamorig:LeftHandIndex1', 'finger'],
    ['mixamorig:LeftHandMiddle1', 'finger'], ['mixamorig:LeftHandRing1', 'finger'], ['mixamorig:LeftHandPinky1', 'finger'],
    ['mixamorig:RightHandThumb1', 'finger'], ['mixamorig:RightHandIndex1', 'finger'],
    ['mixamorig:RightHandMiddle1', 'finger'], ['mixamorig:RightHandRing1', 'finger'], ['mixamorig:RightHandPinky1', 'finger'],
    ['mixamorig:LeftShoulder', 'Shoulder'], ['mixamorig:RightShoulder', 'Shoulder']
]

## メタリグ設定のテンプレート
# extra_ik_toe = Separate IK Toe[bool],rotation_axis = Rotation Axis['X','Z','automatic'] 
# segments= Limb[int] segments, bbones= bbone segments[int], ik_local_location[bool]
rigify_type_settings = {
    # 首の基部
    'neck_base': {'rigify_type': 'spines.super_head', 'layers':[3,],
                  'connect_chain': True, 'tweak_layers':[4,] ,},
    # 背骨の基部
    'spine_base': {'rigify_type': 'spines.basic_spine', 'layers':[3,],
                  'pivot_pos': 2, 'ik_local_location':False, 'make_fk_controls': True,
                  'fk_layers': [4,], 'tweak_layers': [4,],},
     
    # 左上腕
    'LeftArm': {'rigify_type': 'limbs.arm', 'layers': [7,],
                'segments': 1, 'bbones': 1, 'rotation_axis':'x', 'ik_local_location':False, 'auto_align_extremity':False,
                'fk_layers': [8,], 'tweak_layers':  [9,],},
    # 右上腕
    'RightArm':{'rigify_type': 'limbs.arm', 'layers': [10,],
                'segments': 1, 'bbones': 1, 'rotation_axis':'x', 'ik_local_location':False, 'auto_align_extremity':False,
                'fk_layers':[11,], 'tweak_layers': [12,],},
     
    # 左太もも
    'LeftLeg':{'rigify_type': 'limbs.leg', 'layers': [13,],
                'segments': 1, 'bbones': 1, 'rotation_axis':'x', 'ik_local_location':False,
                'fk_layers': [14,], 'tweak_layers': [15,],},
    # 右太もも
    'RightLeg':{'rigify_type': 'limbs.leg', 'layers': [16,],
                'segments': 1, 'bbones': 1, 'rotation_axis':'x', 'ik_local_location':False,
                'fk_layers': [17,], 'tweak_layers': [18,],},
    # 指
    'finger' :{'rigify_type': 'limbs.super_finger', 'layers': [5,],
                'bbones': 1, 'rotation_axis':'x', 'tweak_layers':[6,],},
    
    # 鎖骨
    'Shoulder':{'rigify_type': 'basic.super_copy', 'layers': [3,], 'relink_constraints':False,
                'make_control':True, 'make_widget':True, 'super_copy_widget_type':'bone', 'make_deform':True,},
    # 汎用のサークルコントローラ
    'Circle':{'rigify_type': 'basic.super_copy', 'layers': [20,], 'relink_constraints':False,
                'make_control':True, 'make_widget':True, 'super_copy_widget_type':'circle', 'make_deform':True,},
}
def set_rigify_type(pose_bones):
    for bone_name, set_name in setting_List:
        attr = rigify_type_settings[set_name]
        for key in attr.keys():
            if 'layers' == key:
                # ボーンレイヤ設定
                pose_bones[bone_name].bone.layers = [(i in attr[key]) for i in range(32)]
            elif 'rigify_type' == key:
                pose_bones[bone_name].rigify_type = attr[key]
            elif 'fk_layers' == key:
                # fkレイヤの配置レイヤ
                pose_bones[bone_name].rigify_parameters.fk_layers = [(i in attr[key]) for i in range(32)]
            elif 'tweak_layers' == key:
                # tweakレイヤ配置レイヤ
                pose_bones[bone_name].rigify_parameters.tweak_layers = [(i in attr[key]) for i in range(32)]
            else:
                # その他の属性
                setattr(pose_bones[bone_name].rigify_parameters, key, attr[key]) 


# Rigify Layer name Settings
# name = Layer Name, row = UI row, group = bone group
rigify_layers_data = (
    {'layers':  0, 'acrive':  True, 'name': "Face", 'row': 1, 'select': False, 'group': 5},
    {'layers':  3, 'acrive':  True, 'name': "Torso", 'row': 3, 'select': False, 'group': 3},
    {'layers':  4, 'acrive': False, 'name': "Torso (Tweak)", 'row': 4, 'select': False, 'group': 4},
    {'layers':  5, 'acrive':  True, 'name': "Fingers", 'row': 5, 'select': False, 'group': 6},
    {'layers':  6, 'acrive': False, 'name': "Fingers (Detail)", 'row': 6, 'select': False, 'group': 5},
    {'layers':  7, 'acrive':  True, 'name': "Arm.L (IK)", 'row': 7, 'select': False, 'group': 2},
    {'layers':  8, 'acrive': False, 'name': "Arm.L (FK)", 'row': 8, 'select': False, 'group': 5},
    {'layers':  9, 'acrive': False, 'name': "Arm.L (Tweak)", 'row': 9, 'select': False, 'group': 4},
    {'layers': 10, 'acrive':  True, 'name': "Arm.R (IK)", 'row': 7, 'select': False, 'group': 2},
    {'layers': 11, 'acrive': False, 'name': "Arm.R (FK)", 'row': 8, 'select': False, 'group': 5},
    {'layers': 12, 'acrive': False, 'name': "Arm.R (Tweak)", 'row': 9, 'select': False, 'group': 4},
    {'layers': 13, 'acrive':  True, 'name': "Leg.L (IK)", 'row': 10, 'select': False, 'group': 2},
    {'layers': 14, 'acrive': False, 'name': "Leg.L (FK)", 'row': 11, 'select': False, 'group': 5},
    {'layers': 15, 'acrive': False, 'name': "Leg.L (Tweak)", 'row': 12, 'select': False, 'group': 4},
    {'layers': 16, 'acrive':  True, 'name': "Leg.R (IK)", 'row': 10, 'select': False, 'group': 2},
    {'layers': 17, 'acrive': False, 'name': "Leg.R (FK)", 'row': 11, 'select': False, 'group': 5},
    {'layers': 18, 'acrive': False, 'name': "Leg.R (Tweak)", 'row': 12, 'select': False, 'group': 4},
    )
def set_rigify_layers(bones):
    # ボーンレイヤ設定の作成
    # 全てのボーンレイヤを非表示状態に
    bones.layers  = [False]*32
    # Rigifyのレイヤを設定
    for attr in rigify_layers_data:
        if 'layers' in attr.keys():
            index = attr.pop('layers')
            bones.layers[index] = attr.pop('acrive')
            for key in attr.keys():
                setattr(bones.rigify_layers[index], key, attr[key])
        

active_object = bpy.context.active_object
if active_object.type == 'ARMATURE':
    bones = active_object.data
    pose_bones = active_object.pose.bones
    # ボーングループの作成
    bpy.ops.armature.rigify_add_bone_groups()
    # レイヤ設定の作成
    bpy.ops.pose.rigify_layer_init()
    # ボーンレイヤ情報の設定
    set_rigify_layers(bones)
    # Rigify用のメタリグ情報も設定
    set_rigify_type(pose_bones)
    #現在のボーンの表示するボーンレイヤ
    active_object.data.layers = [(i in [0,3,5,7,10,13,16,20]) for i in range(32)]

スクリプトの
rigify_type_settingsの辞書に自分で名前をつけたメタリグの設定のテンプレートを記述していて
setting_Listの配列に[設定したいボーン名,使用するテンプレート名] のペアで設定対象を記述してます

ボーン名の対応付け設定を変更すれば 他の自作アーマチュアでも同じスクリプトが利用できるかと思います

設定が終わったら オブジェクトデータプロパティの 「Generete Rig」のボタンを押すことでリグが作成されます
image.png
うまくリグが作成されない場合には ボーンの「接続」のチェックが抜けてないか確認してみてください
image.png
例えばこのエラーでは左脚の足先のボーンの接続のチェックを外して実行した例です
エラー箇所まではプログラムが進むので中途半端なアーマチュアが作成されます。

メッシュとの対応付けについては状況によって色々なので 別の機会に触れたいと思います。

Rigify Type取得スクリプト

最後にRigify Typeの設定されているボーンの情報を取得するスクリプトを置いておきます

import bpy
rigify_atrr = ['auto_align_extremity', 'bbones', 'cluster_ctrls', 'connect_chain', 'conv_bone', 'conv_def', 'copy_rotation_axes', 
 'def_parenting', 'extra_ik_layers', 'extra_ik_layers_extra', 'extra_ik_toe', 'eyelid_detach_option', 
 'eyelid_follow_default', 'eyelid_follow_split', 'fk_layers', 'fk_layers_extra', 'foot_pivot_type', 
 'front_paw_heel_influence', 'ik_local_location', 'jaw_locked_influence', 'jaw_mouth_influence', 
 'jaw_secondary_influence', 'limb_type', 'limb_uniform_scale', 'make_control', 'make_controls', 
 'make_custom_pivot', 'make_deform', 'make_deforms', 'make_extra_control', 'make_extra_deform', 
 'make_extra_ik_control', 'make_fk_controls', 'make_ik_wrist_pivot', 'make_parent_switch', 'make_widget', 
 'name', 'neck_pos', 'optional_widget_type', 'palm_both_sides', 'palm_rotation_axis', 'parent_bone', 
 'pivot_master_widget_type', 'pivot_pos', 'primary_layers', 'primary_layers_extra', 'primary_rotation_axis', 
 'register_parent', 'register_parent_tags', 'relink_constraints', 'rna_type', 'roll_alignment', 'rotation_axis', 
 'secondary_layers', 'secondary_layers_extra', 'segments', 'skin_anchor_hide', 'skin_chain_connect_ends', 
 'skin_chain_connect_mirror', 'skin_chain_connect_sharp_angle', 'skin_chain_falloff', 'skin_chain_falloff_length', 
 'skin_chain_falloff_scale', 'skin_chain_falloff_spherical', 'skin_chain_falloff_to_controls', 
 'skin_chain_falloff_twist', 'skin_chain_pivot_pos', 'skin_chain_priority', 'skin_chain_use_reparent', 
 'skin_chain_use_scale', 'skin_control_orientation_bone', 'skin_glue_add_constraint', 
 'skin_glue_add_constraint_influence', 'skin_glue_head_mode', 'skin_glue_tail_reparent', 'skin_glue_use_tail', 
 'skin_primary_layers', 'skin_primary_layers_extra', 'skin_secondary_layers', 'skin_secondary_layers_extra', 
 'super_copy_widget_type', 'tail_pos', 'tweak_axis', 'tweak_layers', 'tweak_layers_extra', 'use_head', 'use_tail', 
 'wgt_align_axis', 'wgt_offset']
dic_ = {}
active_object = bpy.context.active_object
if active_object.type == 'ARMATURE':
    active_pose_bone = bpy.context.active_pose_bone
    dic_['rigify_type'] = active_pose_bone.rigify_type
    rigify_parameters = active_pose_bone.rigify_parameters
    for attr in rigify_atrr:
            if  hasattr(rigify_parameters, attr):
                dic_[attr] = getattr(rigify_parameters, attr)
print(dic_)

先のスクリプトのrigify_type_settingsの辞書に何を記述すれば目的の設定になるのか調べるのに使えるかと思います
image.png

私もテスト中の内容になりますが 一通り形になったので記事にしてみました
何かの参考になれば幸いです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0