
FK/IK切り替え機能のあるリグにて、FK← →IKそれぞれの回転値にスナップする機能のソースコード。
これによって、ぴったりスナップするので、切り替え後の動きのブレをなくせる。
ソースコード
getting IK constrained rotations - Coding / Python Support - Blender Artists Community
ビジュアルトランスフォームの取得は上記参考。
使い方
- tgt_bnameに、対象のボーン名を複数設定する。
- prefix_nameに、FKまたはIKのプレフィックス名を追加する。
- IKをFKに沿わせる場合は、ik_prefix_nameにIKボーン名のプレフィックスを追加する。
- FKなら空にする。
- コンソール画面にコピペして実行する。
import bpy
# スナップしたいデフォームボーン名を入力
tgt_bname = ["upperarm_l","lowerarm_l","hand_l"]
# IK/FKのプレフィックス
# ("REFIK_upperarm_l"のような形を想定。他の形の名前の場合はソースコードを編集すること)
prefix_name = "REFIK_"
# IKの場合、IKボーン名を設定する。
# ik_prefix_nameに値がある場合は、先にIKボーンの位置を手の位置に移動する処理が入る。
# ik_prefix_name = "" # ← FKなら空にする。行頭の「#」をつければ無効化されるので、それで切り替える。
ik_prefix_name = "MYIK_"
def_ik_name = 'hand_l'
# ポーズのビジュアルトランスフォーム(IKを考慮した最終的な位置)を得る
# getting IK constrained rotations - Coding / Python Support - Blender Artists Community
# https://blenderartists.org/t/getting-ik-constrained-rotations/494434/19
def visualmatrix(armature, bone_name):
'''
return a local transformation matrix that
captures the visual transformation including
IK chain etc
'''
pose_bone = armature.pose.bones[bone_name]
data_bone = armature.data.bones[bone_name]
#
M_pose = pose_bone.matrix
M_data = data_bone.matrix_local
#
# grab the parent's world pose and rest matrices
if data_bone.parent:
M_parent_data = data_bone.parent.matrix_local.copy()
M_parent_pose = pose_bone.parent.matrix.copy()
else:
M_parent_data = mathutils.Matrix()
M_parent_pose = mathutils.Matrix()
#
M1 = M_data.copy()
M1.invert()
#
M2 = M_parent_pose.copy()
M2.invert()
#
visual_matrix = M1 @ M_parent_data @ M2 @ M_pose
#
return visual_matrix
###################################
###################################
# メイン処理
obj = bpy.context.object
tgt_poseb = obj.pose.bones
# IKボーンの位置を手の位置に移動
if ik_prefix_name:
def_hand = obj.pose.bones[def_ik_name]
tgt_ik = tgt_poseb[ik_prefix_name + def_ik_name]
new_matrix = obj.convert_space(pose_bone=tgt_ik, matrix=def_hand.matrix, from_space='POSE', to_space='LOCAL')
tgt_ik.location = new_matrix.to_translation()
# デフォームボーンのビジュアルトランスフォームを取得し、クォータニオン回転に変換し、対象ボーンの回転値をそれに変更する。
for bn in tgt_bname:
tgt_poseb[prefix_name+bn].rotation_quaternion = visualmatrix(obj, bn).to_quaternion()
リンク
IK/FK切り替え可能なリグを作る記事はこちら。