LoginSignup
1
1

他のボーンにRigifyと同期するコンストレイントを付加する

Posted at

先日他のソフトからインポートしたアーマチュアを元にRigifyリグを作成する手順を書きました

ここに書いた状態のままでは メッシュは元のアーマチュアにバインドしたままで
Rigifyリグでは動きがつけられない状態です。

頂点グループを設定し直して モディファイアの設定を変更するという手順もありますが
ボーンコンストレイントを使って Rigifyリグの動きを元のアーマチュアを同期させる方法をとりたいと思います
24052501.gif

Rigifyのデフォームボーン

まずRigifyのボーン構造についてみておきたいと思います
キャプチャの 左はRigify標準のメタリグで 既存ボーンの分割設定のLimb Segmentsを1にして
右側のアーマチュアは その設定で生成したリグで ボーンレイヤ29番のみ表示しています
image.png

リグの中に入っているボーンの動きを元に ボーンレイヤ29番に入っているボーンの変形が計算されて
このボーンの変形を元にバインドしたメッシュの動きが決まります

左右を比較すると 同じ場所のボーン名の頭にDEF-とついているだけで同じ構造になっているのが分かります

腕や脚のLimb Segments を標準設定の 2 にすると
関節間のボーンが2分割された状態になり、同じではなくなります

トランスフォームコピー コンストレイント

Blenderのボーンには他オブジェクト等の情報を元に ボーンの状態を決定するボーンコンストレイントがあります
image.png
トランスフォームコピーでは移動回転拡縮の変形をそのまま転送できます
オブジェクト名-ボーン名の形で指定するので スクリプト化は単純です

rig_copy_transforms.py
import bpy
# ターゲットボーンに付いている接頭語
target_prefix = "DEF-"
context = bpy.context
active_object = context.active_object
selected_objects = context.selected_objects
constraint_name = "COPY_DEF-TRANSFORMS"

def set_copy_constraint(constrainted_obj, target_obj, target_prefix):
    # ターゲットオブジェクト内のボーン名の一覧
    target_bone_names = target_obj.data.bones.keys()
    for pose_bone in constrainted_obj.pose.bones:
        # 変形がオフなボーンは無視
        if pose_bone.bone.use_deform == False: continue
        target_name = target_prefix +pose_bone.name
        if target_name in target_bone_names:
            # トランスフォームコピー コンストレイントの設定
            constraint = pose_bone.constraints.new('COPY_TRANSFORMS')
            constraint.name = constraint_name
            # ターゲットオブジェクト
            constraint.target = target_obj
            # ターゲットボーンの名前
            constraint.subtarget = target_name
            # 変形の元になる座標空間
            constraint.target_space = 'POSE' # Default 'WORLD'
            constraint.owner_space = 'POSE'

if active_object.type == 'ARMATURE':
    for constrainted_obj in selected_objects:
        if constrainted_obj != active_object  and constrainted_obj.type == 'ARMATURE':
            set_copy_constraint(constrainted_obj, active_object, target_prefix)

転送元のリグがアクティブになるように
リグと転送先のアーマチュアを選択して スクリプトを実行します。

エクスポート時の設定

ここまでで 元のボーンとリグが同じ動きをするようにはなりました。
ただ、ゲーム用モーションを作る場合だと 最終的なFBX出力時に個々のアニメーションとして別れた状態で出力したいところです

いくつか出力の手法はありますが
今回はNLAストリップを利用する方法で考えます
image.png
NLAストリップにアクションを並べることで 出力ファイルの長さやアニメーション名がストリップの設定にが従ったものになります。

ただ、トランスフォームコピーで動きを付けている場合 アニメーションを作成するのはリグのアーマチュアで
元のアーマチュアの方には NLAストリップ等もない状態です
image.png
どうすればいいでしょう?

元のアーマチュアで書き出したい場合 そちらのNLAに目的の名称・長さのNLAストリップを設定しておくと
その設定に合わせて動きが切り出されます。

また 「アニメーションデータをリンク」を使うと アクティブオブジェクトと他のNLAストリップを同一にできます
image.png
リグのアーマチュアがアクティブ状態になるように 元オブジェクトとリグのアーマチュアを選択して
オブジェクトメニューの 「データのリンク転送[Ctrl L]」から「アニメーションデータをリンク」を選びます

書き出し時の切り出しはタイムライン順に再生した時の動きがベイクされるような挙動になるので
NLA上ではストリップが一列に並んだ状態にする必要があります

トランスフォームコピー の解除スクリプト

コンストレイントは コンストレイントのパネル上にある目玉アイコンを閉じることで一時無効にできます
image.png
複数のボーンを選択した状態で Altを押しながら目玉アイコンを押すことで 一気に無効にすることができます

コンストレイントを消してしまいたいと思うこともあると思うので
一括削除するスクリプトも置いておきます

remove_rig_transforms.py
import bpy
constraint_name = "COPY_DEF-TRANSFORMS"
context = bpy.context
active_object = context.active_object
if active_object.type == 'ARMATURE':
    for pose_bone in active_object.pose.bones:
        # 変形がオフなボーンは無視
        if pose_bone.bone.use_deform == False: continue
        if constraint_name in pose_bone.constraints.keys():
            pose_bone.constraints.remove(pose_bone.constraints[constraint_name])

トランスフォームコピー作成時に固有の名前を付けておいたのでそれで判別して削除するようにしています

手元でもまだ検証中の内容ですが 何かの参考になれば幸いです

1
1
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
1
1