jointOrient は、Orient Joint
ツールで設定できるとはいえ、全てのジョイントがワールド軸に沿って配置されているわけではありません。
そんな場合、orientJoint の値を決めるのは、なかなか面倒な作業になります。
MELで計算するのは大変なので、代替案的な値の取得方法なんかを紹介しようと思います。
まず、問題になる現象を確認します。
HumanIk ツールなんかでスケルトンを作り、Orient Joint を実行します。
とりあえず "LeftHandIndex1"
の階層を複製(Ctrl+D)して、階層を解除します。
そして、複製したジョイント "LeftHandIndex5(?)" の Joint
Orientを確認してみます。
階層化を解除することで、Joint Orient の値が変わっています。
これは、親のジョイントが無くなったため Joint Orient
に、親の回転分が加わった感じになっています。
これを回避するには、トランスフォームノードを作成し、複製したジョイントの元の親ジョイントのワールド回転をセットしてから、複製したジョイントを回転させたトランスフォームノードへ階層化します。
以上のことをスクリプトで書くと、こんな感じでしょうか。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | { 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を)操作します。
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 | { // ジョイントの名称取得 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]; } |
これは、こんな感じのスカートや髪の毛みたいな、軸に沿っていないようなものに特に有効です。
希望の軸の角度になったかなと思ったところで、下のスクリプトを実行。
1 2 3 4 5 | { float $ro []=`getAttr "aimObject.r" `; setAttr ( $joint + ".jo" ) $ro [0] $ro [1] $ro [2]; } |
こんな感じで、aimObjectノードの回転値を編集したいジョイントの jointOrient へセットします。
ただ、子階層がある場合、いったん子ジョイントの階層化を解除してから Joint Orientを編集しないと子階層が変な方向を向いてしまうので、面倒ではあります。
階層構造に対応できるようツール化するのも手ですかね。
0 件のコメント:
コメントを投稿