|
ボーンの用意
事前情報と便利ツールまずは、少し前 TIPS キャラクター・セットアップ、つまりボーンの設定ですが、Softimageで便利な機能の1つに、エンベロープ > リファレンスポーズの設定があります。 骨構造体(Rig)に対してエンベロープを設定した後に骨構造位置を変更させたり、エンベロープを骨に付け直したりする時に重宝する便利な機能です。 >> ヘルプで [リファレンスポーズの変更] を参照 作成 > スケルトンから作った、ボーンを選択した状態で プロパティー > 静止キネマティクス状態を実行すると Static_KineState というノードが出来、 ダブルクリックしてPPGを表示すると値がまだ0の状態です。 この状態で、エンベロープ > リファレンスポーズの設定を実行すると、この PPG にグローバルの値が代入されることが解ります。 つまり、ボーンにその”デフォルトの位置”としてグローパル値が設定されたことを意味しています。 ICE の IK設定時にこの Static_KineState をボーン位置として利用しています。 ![]() 既存の骨を ICE用に使うインプリシットのボーンに置き換えてくれる便利ツールを用意することが出来ました。
少しでも本番っぽさを考え、既存キャラの足ボーンをからインプリシットのボーンを用意してみます。 ![]() その位置と角度を保ったインプリシットのボーンが抽出できます。 ![]() これらすべて並列で置いてあり、階層構造的に親子ではありません。 ![]() ![]() |
2ボーンIK
2ボーンIKの設定方法2つのボーンを選択し、プロパティー > 静止キネマティクスの状態で Static_KineState というノードを付けて エンベロープ > リファレンスポーズの設定をしておきます。 ワールドのセンターの尖ったボックス形状の NULL ICETree を設定します。 ここではそのICEの設定されている Nul lを ICERig と命名しています。 名前とかはサンプルなどと同じにしておくと、そこで使われているツールとかがそのまま利用出来るケースが多いので、真似ッコがいいです ^_^;; 前頁にて記述したICEKinematicsをWorkgroup設定していれば、 タスクを ICEKimematics にするとIK Solvers > 2 BoneIK ノードがあるのでそれを取り出します。 上記で用意した、2つのボーン(LThigh , Shin )とエフェクターの位置にした Null1(LlegEff) を Exporer から D&D して ICEノードを作成します。 IK Solvers > 2 BoneIKノードを良く見ると、Target Position とは Eff の位置情報、Bone1と2は移動値と長さと解ります。 1) GetData ノードを取り出して、エフェクターからつないで、[Explorer]ボタンから、GlobalTransform のPos をクリックしてグローバルの位置データを設定します。 そしたらそれを 2BoneIK のTargetPosition に接続します。 ![]() Static_KineState というノードをクリックしてグローバルの位置データを設定します。 そしたらそれを 2BoneIK の Bone1Transform に接続します。 ![]() そしたらそれを 2BoneIK の Bone1Length に接続します。 ![]() そしたら、2つの骨位置が動き毎に計算された結果をグローバルの位置として設定するので SetDataノードを取り出し、Kine.global が設定している状態で 各骨からの入力と2BoneIK からの計算結果をつなぎ合わせます。 ![]() ![]() ![]() 2ボーンIKの高速化 さて、上記で動いているので完成・・・・とも思えるのですが・・・・、
実はキャラクター一体分、それぞれの全部の骨に SetData で Global 値を設定すると・・・良いパフォーマンスが得られません。 ICE で期待される高速化を目指すのであれば、ちょっとした工夫を施します。 それは、一旦バッファーのように位置データ(例は良く self.BoneTransforms という値名)を格納しておいて、 そのデータを元に Array ノードを使って配置する方法が取られます。 この方法を設定するには、またかなりの改造が必要です。それではいきますよ・・・・。 まずは、データ格納の箱を作成します。 Math > Matrix > 4x4Matrix と Array> BuildArrayfromConstant を用意してつなぎ、 それを SetData で self.BoneTransforms と新しいパラメータを作成して ICETree の最初のPort1に接続します。 BuildArrayfromConstant のSizeには、確保する配列のサイズを指定しますが、ここでは最低でも骨の数(つまり、2)を設定しておく必要があります。 実際には、今後の拡張に備え、人体全体に使われているであろう骨の数、例えば150とか設定しておくと良いでしょう。 ![]() ここで最初に宣言していますので、後はこのパラメータにそれ以下で計算される結果がどんどん代入されていきます。
さて、お次、 Array で位置を特定させるには ID値が必要です。
この部分の説明はは・じ・め・て・の ICE Kinematics その2の位置情報の選択で既に紹介しています。 そこでは、Index値(ID値)を変えると、コーンが置かれる Array上の位置が変化したあれです。 なので、ここでは各ボーンにユニークな ID番号を設定する為に、カスタムのプロパティーセットを利用します。 第1ボーン LThigh を選択して作成6 > パラメーター > 新規カスタムパラメーターセットを実行します。 その名前を ICEBoneParams とし、 BoneID とParentID は整数として-1~999範囲にし Length は浮動小数値として0~999とします。 ![]() 一度作成してしまえば、コピぺが出来るので、各骨に異なる BoneID値を入れておきます。
今はあとの2つの値はここでの説明に使用していません。
![]() 次は、一括でデータを取得しやすいようにグループを作成します。
足2つ(LThigh, LShin)を LegBone1 というグループを作成して入れ、それを Array に渡すようにします。
さて、最大の山場です。
このようにノードを組み上げて行きます。(ただし、これだけでは動きまんよ。) では始めます。(この作業中、Boneは下図のようにきちんとした位置に表示されません)
LegBone1 Groupノードを D&D し、新しいGetDataノードつないで、 ICEBoneParams 内の BoneID を取得します。 その値(Value)を Array > Set in Arrayの Index につなぎ、結果(Result)をSetDataの self.BoneTransforms に接続します。 それを IceTree の Port2 に接続します。この時点で、 Set in Array の前の部分を「値の表示」にて数値にすると、 BoneID の値がちゃんと取れてることを表示してくれます。 ![]() Array > Build Array をSet in Arrayの前に配置し、その Value に接続します。
前述の試し動きの時にあった SetData を削除して Bone1 の結果を Value1 に、 Bone2 の結果を Value2 に接続し、 3個目の Value3 にはエフェクトの位置情報を 2BoneIK を挟んで Matrix to SRT →SRT to Matrix から得た Matrix の結果を接続します。 そして、GetData で self.BoneTransforms を Set in Array の Array に接続します。 ![]() Build Array から Array 出力を「値の表示」にて Axes にするとその位置と方向が見れます。
![]() そして最後の仕上げです。
実は最後に各ボーン毎にも ICE を設定が存在します。どのボーンにも ICETree の内容は同じです。 己にカスタムパラメータで設定していたID値と格納した BoneTransformsから自分の位置を SelectArray で導き出し、 それを自分のグローバルの位置として SetData で設定しています。 ![]() 全部のボーンに付けるものなので、簡単なコンパウンド化しておきます。(名前を統一しておきます。)
Bind Deformer to ICE Rig と名前を付け、タスクを ICE Kinematics/Rig Binding にします。バージョンは 1.3 にしておいてください。 出来たら、コンパウンドの書き出しで保存しておきます。 ![]()
はい、全ての設定が終了しました。きちんと動くか遊んでみてください。
![]() うまく動作しましたら、お疲れ様でした!! OKです。
最初はなんでこんなに・・、と思うところなんですが、 一回動いてしまい、事情が解ってしまうと、おお♪、となるといいな・・と言ったところでしょうか・・・。 オフセットの考察 どこかの付属物としての骨構造体をくっつける場合の考察です。 は・じ・め・て・の ICE Kinematics その1の オフセットを付けるMatrix Offset use を利用すると簡単です。 オフセットの値を知る為に仮に作成したNullを HipPlate1の子供にして値を知ります。 ICETree 上に HipPlate のグローバルトランスレーションを持って来て、Matrix Offset use の InputMatrix につなぎます。 オフセットを付ける第1ボーンの LThigh のStaric_KineStateからのMatrixを MatrixtSRTで回転とスケール値 を Matrix Offset use にそれぞれつなぎます。 オフセット値仮Nullから得た値を記入します。 最後に、出た結果の Matrix を 2BoneIKの Bone1Trasform に接続します。 ![]() ![]() UpVector の考察 これも骨の方向を制御するもの、としての考察です。(中級レベルに”もってこい”のサンプルです。)
第1ボーンのオフセット値の後に差し込む形でボーンの方向を変えてみました。 UpVector用のピラミッド表示のNullはやはり並列に置いてあります。 ![]() サンプルとしているのは Kinematics > LookAt というコンパウンドを展開して中にある Point Pose at Position を編集したものです。
![]() 更にPoint Pose at Positionを展開すると、下図のようになっています。
入って来るUpVectorの位置から方向を導き、それを回転値として計算して第1ボーンのグローバル値にするということが想定できます。 ![]() ちょっとした改善が使い易すさと、ICE の機能の理解を深めることになります。
![]() 変更点は、入って来る UpVector の位置が骨の前か後ろかを If でつなぎ、Flipにチェックを入れると後ろになるようにしています。
これだけなのに、UpVectorのX軸移動方向とは逆方向に骨の向きがちゃんと回転します。前にある場合は位置を追従して回転します。 その下の BuildArray は、第1ボーン → UpVector → Effector の位置順にオレンジ色の線を描画しているだけのものです。 If ではなく Andですが、チェックを入れると線が描かれ、外すと消えます。 こうしたちょっとしたことがアニメーターに使いやすいツールになるでしょう。 思うような動きになっているかは、試してみてください。 もし、UpVectorの動きが他のオブジェクトと追従して動いて欲しいなら、HipPlate1 の子供にしてみたはいかがでしょうか。 ![]() 完成されたものではありませんが、試してもらって良いです。 少量の変更なので、V1.2としてコンパウンドを書き出しました。 > Point Pose at Position.1.2.xsicompound |
すでに多くのサンプルやコンパウンド、スクリプトが存在しますので、 先人達の知恵をうまく活用して自分の目的の動きになるように組み合わせる ・・・ というのが ICE のうまい使い方ではないでしょうか。 つまり、”うまく組み合わせられるように何をしているのかを理解すること”が ICE の使い方のくせとかこつになるのかも知れません。 |
という訳で、次回は ICE のスプリングとかコリジョンとか予定してるんですが・・・。 乞う、ご期待!!
|