この、poleVector の方向は、ジョイントが3個以上のスケルトンでは、プリファードアングルとかで制御できるのですが、上のように2個のジョイントからなる骨では、向きを制御することが不可能のようです。
この骨も、Z軸に出てほしかったのですが、X軸の方を向いてしまっています。
この骨も、Z軸に出てほしかったのですが、X軸の方を向いてしまっています。
法則性が分かればよいのですが、なんかバラバラなんですよねー。
スクリプトで組んでいると、同じ角度のはずなのに、1個目と2個目で向きが違っている場合があったりして困ります。
目で見て確認するというのも効率が悪いので、poleVector の座標を計算して求めるのが良いでしょう。
汎用的に使えるよう複数の骨で構成されたIKにも対応させたいので、そこもふまえてスクリプトを作ります。
global proc vector tryCalcPV( string $HDL ) ///< ikHandle 名 /**************************************************************************//** @brief pole vector の位置を骨格の長さで計算する @return poleVector の座標を返す。 ******************************************************************************/ { // ジョイント名の取得 string $sj =`ikHandle -q -sj $HDL`; string $ee =`ikHandle -q -ee $HDL`; // 開始ジョイントの座標取得 vector $sp =`xform -q -ws -t $sj`; //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ // // 骨格の長さを計算 //------------------------------------------------------------------------------ // 変数の初期化 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; } //------------------------------------------------------------------------------ // poleVector の座標を取得 vector $pv =`getAttr ($HDL+".pv")`; // 計算用の要素を計算 vector $ep = $sp + $pv; float $rate = $length / mag($pv); return ((1.0 - $rate) * $sp + $rate * $ep); }
単に poleVector の方向を出しているのではなく、骨の長さを計算してpoleVector の方向へ加えています。
使い方としては、
使い方としては、
{ vector $p = tryCalcPV("ikHandle1"); move ($p.x) ($p.y) ($p.z) "locator1"; }
のように、ikHandle 名を渡すと座標が返ってくるので、何かオブジェクトをその座標へ移動さて poleVectorConstraint をします。
ikHandle の poleVector 座標を計算するスクリプトなので ikHandle を設定していないと計算できません。
poleVectorオブジェクトがコンストレイントされていたらIKを設定している骨の長さへ正規化できることになります。
ikHandle からは poleVector constraint も調べられるので、PVオブジェクトを見つけたら一気に移動までさせても良いのかな。
0 件のコメント:
コメントを投稿