2020年11月9日月曜日

Go to Bind Pose

  リグの組み方は色々あると思うんですが、どういった作り方をしていたとしても、基本的にはリグコントローラからバインドしているジョイントへは、コンストレイントを使ってアニメーションを転送するというのが簡単で広く知れ渡っているという感じでしょうか。

  ただ、scaleConstraint だけは上手くスケールを拘束できないようで、worldMatrix から decomposeMatrixを使ってアトリビュートを接続することがあったりします。


  スクリプトでリグを作成していると、頻繁にリグ階層の削除を行います。
  通常のコンストレイントを掛けているだけであれば、拘束しているジョイントのトランスフォーム値はゼロに戻ってくれたりするのですが、アトリビュートを直接接続していたり、コンストレインノードを別階層にまとめていたりした場合、ジョイントのトランスフォーム値はゼロに戻ってくれません。

コンストレインノードの階層変更なし

コンストレインノードを別階層にまとめている


  リグコントローラの座標を決めるとき、基準となるのは拘束するジョイントの座標だと思います。なので、リグを再構築する場合、元のポーズへ戻す必要があり、その時に使用する操作が [Rigging] Skin > Go to Bind Pose です。

  このバインドポーズへ戻すときに問題になってくるのが、decomposeMatrix などのユーティリティノードが接続されているジョイント。

  何かノードが接続されているジョイントがあった場合、Go to Bind Pose は、

Error: Pose not achieved. See diagnostics in Script Editor.

みたいなエラーで止まります。

  通常、maya の delete 処理は、できる限り source 側のノードを削除しようとしています。けれども、destination 側のノードは削除されずに残ってしまう可能性があるのです。
  なので、Go to Bind Pose を実行する前に、ユーティリティノードが接続されていないかジョイント階層をチェックして修正していかないといけません。
  こんな感じのスクリプトでどうでしょう。

proc _deleteSourceNode(
    string $jnt )                       ///< ジョイント名
/**************************************************************************//**
    @private
    @brief バインド骨の接続元を削除する
 ******************************************************************************/
{
    /// 接続元を調べる
    string $srcs[] =`listConnections -s 1 -d 0 -p 0 $jnt`;
    
    /// ジョイントとレイヤーは除く
    string $rems[];
    for($src in $srcs)
    {
        string $typ =`nodeType $src`;
        if( "displayLayer"==$typ
         || "joint"==$typ )
        {
            $rems[size($rems)] = $src;
            
        }
        
    }
    
    string $nodes[] = stringArrayRemove($rems, $srcs);
    $nodes = stringArrayRemoveDuplicates($nodes);
    
    /// 削除するノードが無かったら戻る
    if(!`size $nodes`) return;
    
    /// ノードの削除
    for($node in $nodes) catch(`evalEcho ("delete \""+$node+"\"")`);
    
}


proc _deleteSourceNodes(
    string $jntRoot )                   ///< ルートジョイント
/**************************************************************************//**
    @private
    @brief バインド骨の接続元を削除する
 ******************************************************************************/
{
    /// 接続元を調べる
    string $childs[] =`listRelatives -ad -f -typ "joint" $jntRoot`;
    
    /// 自身を追加
    $childs[size($childs)] = $jntRoot;
    
    /// 接続元ノードの削除
    _deleteSourceNode($jnt);
    
}


global proc recoverBindpose(
    string $jntRoot)                    ///< ルートジョイント名
/**************************************************************************//**
    @brief main procedure.
 ******************************************************************************/
{
    /// バインドポーズへ移行
    if( catch(`dagPose -r -g -bp $jntRoot`) )
    {
        /// ジョイントに接続されているノードの削除
        _deleteSourceNodes($jntRoot);
        
        /// 再度実行
        dagPose -r -g -bp $jntRoot
        
    }
    
}

  ただ、たまにバインドポーズを複数持っているジョイントに出くわすんですよねぇ・・・。
  複数のメッシュオブジェクトをバインドしてあるときによく見かけます。


{
    string $BPs[]=`dagPose -q -bp -n $jntRoot`;
    if(!`size $BPs`) error ("Not found Bind Pose.\""+$jntRoot+"\"");
    
}

  これでバインドポーズを数えられるので、複数見つけた場合は、オブジェクトの回数ぶん Go to Bind Pose するか、もしくはレギュレーション違反で修正するか、ですね。


0 件のコメント:

コメントを投稿