個人的に、この計算によって出た座標へ poleVector を移動させることを「normalize(正規化)」って言っています。
正しいのかは知りませんが。
まず、ジョイント階層に Rotate-Plane Solver を設定して ikHandle と、PVコンストレイントをかけたロケータを、適当な位置へ移動させておきます。

これに前回のスクリプトを実行すると、こんな感じになります。

このPVの位置では、ikHandle が簡単に poleVector の線を越えてしまえて、フリップしてしまいます。

なので、PVの移動先はIKのスタートジョイントを中心にIKベクトルを90度回転させた位置へ移動させた方がアニメーションを作るときには都合が良いです。
こんな感じのスクリプト。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | global proc vector tryMovePV( string $HDL , ///< ikHandle 名 string $axis ) ///< 回転させる軸 /**************************************************************************/ /** @brief pole vector の位置を正規化する @return poleVector の座標を返す。 ******************************************************************************/ { // ジョイント名の取得 string $sj =`ikHandle -q -sj $HDL `; string $ee =`ikHandle -q -ee $HDL `; // 開始ジョイントの座標取得 float $m [] =`xform -q -ws -m $sj `; vector $sp =<< $m [12], $m [13], $m [14]>>; vector $ep =`xform -q -ws -t $ee `; //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ // // 骨格の長さを計算 //------------------------------------------------------------------------------ // 変数の初期化 float $length = 0.0; string $self = $ee ; // 階層分ループ while ( true ) { // 親のジョイント名 string $parent = firstParentOf( $self ); // 自分の座標と親の座標を取得 vector $p0 =`xform -q -ws -t $self `; vector $p1 =`xform -q -ws -t $parent `; // 骨の長さを計算 $length += mag( $p1 - $p0 ); // 終了判定 if (`plugNodeStripped $sj `==`plugNodeStripped $parent `) break ; // 切り替え $self = $parent ; } //------------------------------------------------------------------------------ // まず、ハンドルベクトルの延長線上のpv座標を計算 float $rate =( $length / mag( $ep - $sp )); vector $lenPos =((1.0 - $rate ) * $sp ) + ( $rate * $ep ); // 回転軸 $axis = tolower( $axis ); vector $rShaft ; switch ( $axis ) { case "x" : $rShaft = << $m [0], $m [1], $m [2]>> ; break ; case "y" : $rShaft = << $m [4], $m [5], $m [6]>> ; break ; case "z" : $rShaft = << $m [8], $m [9], $m [10]>>; break ; } // $sp を中心に $rShaft で $lenPos を -90度回転させた座標を計算 float $PI = 3.141592654; vector $mov =`rot ( $lenPos - $sp ) $rShaft (-( $PI /2))`; $mov += $sp ; return $mov ; } |
前回作ったスクリプトに、けっこう似ていますが、終わりの部分が少し複雑になっています。
これをこんな感じで使います。
{ vector $p = tryMovePV( "ikHandle1" , "x" ); move ( $p .x) ( $p .y) ( $p .z) "locator1" ; } |
引数の"x"は、このジョイントの Local Rotation Axis がこんな風になっているのためです。

ここは、作ったジョイントによって変わると思います。
実行すると poleVector は、こんな位置へ移動します。

これなら上と同じ位置へ ikHandle を移動させても、フリップはしません。

骨格の長さを計算する部分は結構使いまわせそうなので、リファクタリングしても良いかもしれないですね。
これをリグのサポート機能としてピッカーに追加しておくと、アニメータには結構喜ばれます。
リガーの仕事かは抜きにして・・・。
0 件のコメント:
コメントを投稿