極ベクトルのフリップを回避する

極ベクトルのフリップ問題

腕や脚のIKに、肘や膝の向きを制御する「極ベクトル」(Pole Vector)を設定した場合、IKハンドルを極端な位置に移動すると次の動画のようなフリップ(急激な反転)を起こします。

IKの開始点からハンドルを結ぶ直線(ハンドルベクトル)が、極ベクトルを越えるとフリップが生じます。

ネット記事を参考にこれを回避するリグ構成をつくりましたが、備忘録としてメモしておきます。

原因

原因のひとつとして、IKハンドルを移動したときに開始点からハンドルを結ぶ直線(ハンドルベクトル)が、極ベクトルシェイプを越えてしまうことがあります。

FarArm(前腕=肘の位置)の位置と連動して極ベクトルシェイプが動かない限り、この現象は避けられません。
次の図の❶でIKハンドルを太い矢印の方向へ移動… ❷で極ベクトルシェイプを越えると腕がフリップします。

解決方法として、単純にFarArm_jt_L(前腕=肘)ジョイント極ベクトルシェイプペアレントし、一緒に移動させれば良いように思われますが、その場合フリップは回避できてもサイクルが生じます。
極ベクトルを上下に動かして腕の向きを上下に回転させると極ベクトルによる動きペアレントによる動き無限ループしてしまい挙動がおかしくなります。

解決方法

最終的に極ベクトルを下図のような組み合わせにすることでフリップを回避し、サイクルも生じないようになりす。

要点は、極ベクトルシェイプ腕全体の中間点前腕=肘 付近)に追従させるために、新たに2つ作成したノード(空のグループ=Null)を使い、極ベクトルシェイプをこの子階層に設定したこと。 そして、この2つのノード向き(回転)あるいは位置をそれぞれIKハンドルからのエイム コンストレインポイント コンストレインで制御するようにしたことです。

L_Arm_IK(IKハンドル)エイム コンストレインによりUpArm_jt_L(腕の付け根)に設置した L_ArmRot_PV の向き(回転)を制御しています。
また、UpArm_jt_L(腕の付け根)L_Arm_IK(手首)の2つのポイントコンストレインにより L_Arm_PV_Pos が常に腕の中間点に位置するようにしています。
下図の矢印は、それぞれのノードを配置している位置を示しています。

結果的に次のGIFアニメーションのように、極ベクトルシェイプが腕の動きに追従し、尚且つ極ベクトルシェイプを上下させて腕全体の向きを制御できるようになりました。

作成手順

IKコントローラーの作成

最初に腕を動かすためのIKを作成します。
IKハンドルをコントロールするシェイプは、予めポリゴン球を元にカーブオブジェクトで作成したものを使用します。

Ctrl_L_Arm_IK を作成する

IKコントロール用シェイプ [Ctrl_L_Arm_IK] を原点に作成します。

Space_Ctrl_L_Arm_IK を作成する

親ノードとして[Space_Ctrl_L_Arm_IK] を原点に作成します。

親ノードは、「作成」「空のグループ」でつくります。
MayaにはNull(ヌル)の作成機能はありませんが、空のグループがNullと同じになります。

Space_Ctrl_L_Arm_IK をペアレントする

   [Ctrl_L_Arm_IK] [Space_Ctrl_L_Arm_IK] にペアレントします。        

Shoulder_jt_L に ペアレントする

[Space_Ctrl_L_Arm_IK] を [Shoulder_jt_L] にペアレントします。

Space_Ctrl_L_Arm_IK を移動する

[Space_Ctrl_L_Arm_IK] を [Hand_jt_L] の位置へスナップ移動します。

IKハンドルを作成する

IKハンドル [L_Arm_IK] を オプション「回転プレーンソルバ」で作成します。

Ctrl_L_Arm_IK にペアレントする

[L_Arm_IK] を [Ctrl_L_Arm_IK] にペアレントします。

極ベクトルコントローラー格納ノードの作成と準備

極ベクトルコントローラーを作成する前準備として、それらすべてを格納する最上位ノード [Space_L_ArmRot_PV] を作成します。

最上位ノードを作成する

❶ 最上位の親ノード [Space_L_ArmRot_PV] を作成します。

❷ [Space_L_ArmRot_PV] を腕の付け根 [UpArm_jt_L] の位置へスナップ移動し、トランスフォームをフリーズします。

エイム コンストレイントを作成する

IKコントローラ[Ctrl_L_Arm_IK] ➡ [Space_L_ArmRot_PV] の順で選択し、コンストレイント > エイム コンストレイント を実行します。

エイム コンストレイント オプションは、デフォルトの設定にしてください。
オフセットの保持:[OFF]
・エイム ベクトル:[X軸]
・アップ ベクトル:[Y軸]


ワールドアップタイプを「なし」にする

作成されたエイムコンストレイント ノード[Space_L_ArmRot_PV_aimConstranint] を選択し、「▼エイムコンストレイント アトリビュート」の「ワールド アップ タイプ」を「なし」に変更します。

エイム コンストレイントを削除する

[Space_L_ArmRot_PV] の向きがIKコントローラ[Ctrl_L_Arm_IK] の方向へ僅かですが変更できたので、トランスフォームの「回転」の値に数値が入ります。

作成したエイム コンストレイントノード [Space_L_ArmRot_PV_aimConstranint] は必要なくなったので削除します。

Shoulder_jt_Lにペアレントする

最上位のノード [Space_L_ArmRot_PV] をジョイント[Shoulder_jt_L]にペアレントします。

極ベクトルの「回転」(向き)制御用ノードをつくる

上腕から先 [UpArm_jt_L] が、常に極ベクトルの方向へ回転するように設定します。

「回転」制御用ノードの作成

最終的に常に極ベクトルコントローラの方向へ回転するノード [L_ArmRot_PV] を作成します。

UpArm_jt_L の位置へ移動する

作成した [L_ArmRot_PV] をジョイント[UpArm_jt_L] の位置へスナップ移動します。
移動したら[L_ArmRot_PV] のトランスフォームをフリーズします。

[Space_L_ArmRot_PV] にペアレントする

[L_ArmRot_PV] を先ほど作成した最上位のノード [Space_L_ArmRot_PV] にペアレントします。

IKコントロールでエイムコンストレイントする

IKコントローラ[Ctrl_L_Arm_IK] ➡ [L_ArmRot_PV] の順に選択し、コンストレイント > エイム コンストレイント を実行します。

極ベクトルの「位置」制御用ノードをつくる

極ベクトルコントローラが、ジョイント[UpArm_jt_L] と IKコントローラ[Ctrl_L_Arm_IK] を結ぶ直線上の中間付近に位置するように設定します。

「位置」制御用ノードを作成する

位置」制御用のノード [L_ArmPos_PV] を作成します。
このノードが常にジョイント[UpArm_jt_L] と IKコントローラ[Ctrl_L_Arm_IK] を結ぶ直線上の中間付近に位置するようにしていきます。

FarArm_jt_Lの位置に移動する

[L_ArmPos_PV] を前腕ジョイント [FarArm_jt_L] の位置にスナップ移動します。

L_ArmRot_PV にペアレントする

[L_ArmPos_PV] を「回転」制御用ノード [L_ArmRot_PV] にペアレントします。

トランスフォームをフリーズする

ペアレント後に、[L_ArmPos_PV] のトランスフォームをフリーズします。

ポイント コンストレイント する

[UpArm_jt_L] ➡ IKコントローラ[Ctrl_L_Arm_IK] ➡ [L_ArmPos_PV] の順に選択し、コンストレイント ポイント コンストレイント を実行します。
これで、ジョイント[UpArm_jt_L] と IKコントローラ[Ctrl_L_Arm_IK] の中間に [L_ArmPos_PV] が位置するようになります。

極ベクトルシェイプの設定

これが最後のプロセスになります。

同じような説明が続いたので、少しまとめて書きます。
極ベクトルコントローラとしてカーブオブジェクト[Ctrl_L_Arm_PV]を原点に用意し、親ノード[Space_L_Arm_PV] を作成してペアレントします。

[Ctrl_L_Arm_PV]: IKコントローラを複製してリサイズしたものを使っています。

ここからまたステップごとに書きます。

肘の位置へ移動する

親ノード[Space_L_Arm_PV] を肘の位置のジョイント [FarArm_jt_L] へスナップ移動します。

Zマイナス方向へ移動する

さらに、[Space_L_Arm_PV] を Z マイナス 方向へ適宜移動します。
移動する長さは上腕の長さ程度が適当です。

極ベクトル を作成する

極ベクトルコントローラ[Ctrl_L_Arm_PV] ➡ IKハンドル[L_Arm_IK] の順に選択し、コンストレイント極ベクトル を実行します。

「位置」制御ノードにペアレントする

極ベクトルコントローラの親ノード [Space_L_Arm_PV] を 「.4 極ベクトルの「位置」制御用ノードをつくる 」で作成した「位置」制御ノード [L_ArmPos_PV] に ペアレントして完成です。

下記BACKBONEさんのサイトが大変参考になりました。