2016年9月4日日曜日

【MayaLT2017】HumanIKのポーズを反転するMEL

MayaLT2017で歩行など左右で同じポーズを使うモーションを作成する際、反転コピー機能が欲しくなったのでMELの勉強がてら作ってみました。(探せばありそうですが)
標準で入っている HumanIK のリグを前提としています。

●使い方
 ・シェルフ等にスクリプトを登録して反転コピーしたいリグを選択し、実行。

●仕様
 ・片側選択して実行すると片側のみの反転コピーになります。
 ・両側選択して実行で左右入れ替え状態となります。

●注意
 ・全身を反転させるときは IKリグ(関節部分の赤や青のボックス)と FKリグ(オレンジのボックスやライン) の両方を選択してください。範囲選択ではIKのみしか選択されないようです。
  (HumanIKのUIのなにもない所をクリックするとIKもFKも 全選択/解除 できます。)
 ・部分的に実行するときはIKブレンド率にも注意
 

●MEL



global proc MirrorPose()
{
    print( "\n------------ Start MirrorPose() ------------\n" );
    
    string  $allObjects[];
    string  $obj;

    $allObjects = `ls -sl`;               // 選択中のオブジェクトリスト
    int $nAllObjects = size($allObjects); // 要素数
    
    // 退避テーブル
    float $rotX[];
    float $transX[];
    float $rotY[];
    float $transY[];
    float $rotZ[];
    float $transZ[];
    
    // 選択対照の情報を退避
    if( $nAllObjects == 1 )        // 一つ
    {
        $transX[0] = `getAttr $allObjects.translateX`;
        $transY[0] = `getAttr $allObjects.translateY`;
        $transZ[0] = `getAttr $allObjects.translateZ`;
        
        $rotX[0] = `getAttr $allObjects.rotateX`;
        $rotY[0] = `getAttr $allObjects.rotateY`;
        $rotZ[0] = `getAttr $allObjects.rotateZ`;
    }
    else if( $nAllObjects > 1 )   // 複数
    {
        $transX = `getAttr $allObjects.translateX`;
        $transY = `getAttr $allObjects.translateY`;
        $transZ = `getAttr $allObjects.translateZ`;
        
        $rotX = `getAttr $allObjects.rotateX`;
        $rotY = `getAttr $allObjects.rotateY`;
        $rotZ = `getAttr $allObjects.rotateZ`;
    }
    
    // ポーズ反転処理
    for ( $cnt = 0; $cnt < $nAllObjects; $cnt++ ) 
    {
        $obj = $allObjects[$nAllObjects - $cnt - 1]; // 逆順で入ってるみたい?
        $isLR = false;
        print ($obj + " -> ");
        
        // 選択対象の名称置き換え
        if( `gmatch $obj "*Left*"` )
        {
            $obj  = substituteAllString( $obj, "Left", "Right" );
            $isLR = true;
        }
        else if( `gmatch $obj "*Right*"` )
        {
            $obj  = substituteAllString( $obj, "Right", "Left" );
            $isLR = true;
        }
        else if( `gmatch $obj "*_L"` )
        {
            $obj  = substituteAllString( $obj, "_L", "_R" );
            $isLR = true;
        }
        else if( `gmatch $obj "*_R"` )
        {
            $obj  = substituteAllString( $obj, "_R", "_L" );
            $isLR = true;
        }
        else if( `gmatch $obj "*_l"` )
        {
            $obj  = substituteAllString( $obj, "_l", "_r" );
            $isLR = true;
        }
        else if( `gmatch $obj "*_r"` )
        {
            $obj  = substituteAllString( $obj, "_r", "_l" );
            $isLR = true;
        }
        print ($obj + "\n");
         
        
        // 選択反転
        select -r $obj ;
        
        // 座標
        move ($transX[$cnt] * -1) $transY[$cnt] $transZ[$cnt];
        
        // 回転
        if( `gmatch $obj "*Effector"` ) // IK?
        {
            // IK
            rotate ($rotX[$cnt] * -1) ($rotY[$cnt] * -1) $rotZ[$cnt];
        }
        else
        {
            // FK
            
            if( $isLR ) // 対照リグ?
            {
                if( `gmatch $obj "*Arm"` )
                {
                    // 腕
                    rotate $rotX[$cnt] $rotY[$cnt] $rotZ[$cnt];
                }
                else if( `gmatch $obj "*Shoulder"` )
                {
                    // 肩
                    rotate $rotX[$cnt] ($rotY[$cnt] * -1) ($rotZ[$cnt] * -1);
                }
                else
                {
                    // その他
                    rotate ($rotX[$cnt] * -1) ($rotY[$cnt] * -1) $rotZ[$cnt];
                }
            }
            else
            {
                // その他(胴体など)
                rotate ($rotX[$cnt] * -1) ($rotY[$cnt] * -1) $rotZ[$cnt];
            }
        }
    };
    
    print( "------------ End MirrorPose() ------------\n" );
};

0 件のコメント:

コメントを投稿