先日他のソフトからインポートしたアーマチュアを元にRigifyリグを作成する手順を書きました
ここに書いた状態のままでは メッシュは元のアーマチュアにバインドしたままで
Rigifyリグでは動きがつけられない状態です。
頂点グループを設定し直して モディファイアの設定を変更するという手順もありますが
ボーンコンストレイントを使って Rigifyリグの動きを元のアーマチュアを同期させる方法をとりたいと思います
Rigifyのデフォームボーン
まずRigifyのボーン構造についてみておきたいと思います
キャプチャの 左はRigify標準のメタリグで 既存ボーンの分割設定のLimb Segmentsを1にして
右側のアーマチュアは その設定で生成したリグで ボーンレイヤ29番のみ表示しています
リグの中に入っているボーンの動きを元に ボーンレイヤ29番に入っているボーンの変形が計算されて
このボーンの変形を元にバインドしたメッシュの動きが決まります
左右を比較すると 同じ場所のボーン名の頭にDEF-とついているだけで同じ構造になっているのが分かります
腕や脚のLimb Segments を標準設定の 2 にすると
関節間のボーンが2分割された状態になり、同じではなくなります
トランスフォームコピー コンストレイント
Blenderのボーンには他オブジェクト等の情報を元に ボーンの状態を決定するボーンコンストレイントがあります
トランスフォームコピーでは移動回転拡縮の変形をそのまま転送できます
オブジェクト名-ボーン名の形で指定するので スクリプト化は単純です
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ストリップを利用する方法で考えます
NLAストリップにアクションを並べることで 出力ファイルの長さやアニメーション名がストリップの設定にが従ったものになります。
ただ、トランスフォームコピーで動きを付けている場合 アニメーションを作成するのはリグのアーマチュアで
元のアーマチュアの方には NLAストリップ等もない状態です
どうすればいいでしょう?
元のアーマチュアで書き出したい場合 そちらのNLAに目的の名称・長さのNLAストリップを設定しておくと
その設定に合わせて動きが切り出されます。
また 「アニメーションデータをリンク」を使うと アクティブオブジェクトと他のNLAストリップを同一にできます
リグのアーマチュアがアクティブ状態になるように 元オブジェクトとリグのアーマチュアを選択して
オブジェクトメニューの 「データのリンク転送[Ctrl L]」から「アニメーションデータをリンク」を選びます
書き出し時の切り出しはタイムライン順に再生した時の動きがベイクされるような挙動になるので
NLA上ではストリップが一列に並んだ状態にする必要があります
トランスフォームコピー の解除スクリプト
コンストレイントは コンストレイントのパネル上にある目玉アイコンを閉じることで一時無効にできます
複数のボーンを選択した状態で Altを押しながら目玉アイコンを押すことで 一気に無効にすることができます
コンストレイントを消してしまいたいと思うこともあると思うので
一括削除するスクリプトも置いておきます
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])
トランスフォームコピー作成時に固有の名前を付けておいたのでそれで判別して削除するようにしています
手元でもまだ検証中の内容ですが 何かの参考になれば幸いです