jointOrient は、Orient Joint
ツールで設定できるとはいえ、全てのジョイントがワールド軸に沿って配置されているわけではありません。
そんな場合、orientJoint の値を決めるのは、なかなか面倒な作業になります。
MELで計算するのは大変なので、代替案的な値の取得方法なんかを紹介しようと思います。
まず、問題になる現象を確認します。
HumanIk ツールなんかでスケルトンを作り、Orient Joint を実行します。
とりあえず "LeftHandIndex1"
の階層を複製(Ctrl+D)して、階層を解除します。
そして、複製したジョイント "LeftHandIndex5(?)" の Joint
Orientを確認してみます。
階層化を解除することで、Joint Orient の値が変わっています。
これは、親のジョイントが無くなったため Joint Orient
に、親の回転分が加わった感じになっています。
これを回避するには、トランスフォームノードを作成し、複製したジョイントの元の親ジョイントのワールド回転をセットしてから、複製したジョイントを回転させたトランスフォームノードへ階層化します。
以上のことをスクリプトで書くと、こんな感じでしょうか。
{ string $self ="LeftHandIndex1"; string $parent = firstParentOf($self); vector $p =`xform -q -ws -t $self`; vector $r =`xform -q -ws -ro $parent`; string $dp[]=`duplicate $self`; string $grp =`group -em`; move ($p.x) ($p.y) ($p.z) $grp; rotate ($r.x) ($r.y) ($r.z) $grp; parent $dp[0] $grp; }
このスクリプトを実行すると、下のような階層構造になり、複製したジョイント LeftHandIndex5 の Joint Orient は、複製元 LeftHandIndex1 と同じ値になっているはずです。
このことから、Joint Orient を正しく計測するためには、親のワールド回転値を持ったノードが必要だということが分かります。
そして、Orient Joint ツールの Primary Axis や Secondary Axis を再現するために、Aim Object、Aim Target、Aim Vector を Locator で作成し、Aim Constraint を掛けて(主にAim Vectorを)操作します。
{ // ジョイントの名称取得 string $self ="LeftHandIndex1"; string $parent = firstParentOf($self); string $childs[]=`listRelatives -c -typ "joint" $self`; // 座標 vector $p0 =`xform -q -ws -t $self`; vector $p1 =`xform -q -ws -t $childs[0]`; vector $ro =`xform -q -ws -ro $parent`; //------------------------------------------------------------------------------ // ノード作成 string $axis =`group -em -name "axis"`; string $lct0[] =`spaceLocator -name "aimObject"`; string $lct1[] =`spaceLocator -name "aimTarget"`; string $lct2[] =`spaceLocator -name "aimVector"`; // 階層化 parent $lct0[0] $axis; parent $lct1[0] $axis; parent $lct2[0] $axis; // 移動 move ($p0.x) ($p0.y) ($p0.z) $axis; rotate ($ro.x) ($ro.y) ($ro.z) $axis; move ($p1.x) ($p1.y) ($p1.z) $lct1[0]; //------------------------------------------------------------------------------ // コンストレイント aimConstraint -aim 1 0 0 -u 0 0 1 -wut "object" -wuo $lct2[0] $lct1[0] $lct0[0]; }
これは、こんな感じのスカートや髪の毛みたいな、軸に沿っていないようなものに特に有効です。
希望の軸の角度になったかなと思ったところで、下のスクリプトを実行。
{ float $ro[]=`getAttr "aimObject.r"`; setAttr ($joint+".jo") $ro[0] $ro[1] $ro[2]; }
こんな感じで、aimObjectノードの回転値を編集したいジョイントの jointOrient へセットします。
ただ、子階層がある場合、いったん子ジョイントの階層化を解除してから Joint Orientを編集しないと子階層が変な方向を向いてしまうので、面倒ではあります。
階層構造に対応できるようツール化するのも手ですかね。
0 件のコメント:
コメントを投稿