Mayaの頂点カラーのUnsharedのチェック方法

クリーク・アンド・リバー社 COYOTE CG STUDIO テクニカルチームの最強の征夷大将軍といば足利義輝、戦国大好き人間の中林です。

今回は僕が不勉強で最近知ったのですが、情報も少なく解決に苦労した頂点カラーのUnsharedについてです。勘の良い人なら単語を見ただけでも分かるかもしれませんが。

そもそものキッカケは?

キャラモデラーから頂点カラーでエラーが無いかチェックするツールについての相談がキッカケでした。頂点カラーのエラーで有名なのは0以下の数値か1以上の数値が入っているもので、普通に相談は受けるしツールも作成済みです。
しかし、今回はそれに加えてUnsharedの頂点があったらチェックして欲しいとありました。
正直、僕はsceaneデータを貰って開くまでそんな頂点カラーがあるなんて半信半疑でしたが……

コンポーネントエディタで該当の頂点を選択するとRGBA部分にUnsharedと表示されてます。
それで、Melでカラー部分を取得すれば情報があるかと思ったら

polyColorPerVertex -q -r -g -b -a;
// 結果: 0 0 0.4375 1 //

普通に数値を取得してきます。

結論からいうと頂点フェース単位でカラーが違う


上図は分かりやすい例ですが、選択している頂点は青と色無しでハッキリと別れてます。これは頂点フェース単位で色を変えているからです。コンポーネントエディタの詳細ポリゴンを選択すると青の値が明らかに違います。
Unshared(非共有の)の言葉の通り、頂点カラーが非共有の場合に表示されます。
マップモデラーだとオブジェクトの際とかで頂点フェース単位で色を変えるのは馴染みがありますが、それ以外だと使う機会は少ないかもしれません。

しかし、上図のように一見、詳細ポリゴンの色が同じ値でもUnsharedになる場合もあります。これはMayaに良くある細かい数値が混ざってるからです。この場合は頂点フェースの青に0.9999という数値を忍ばせてあります。
これを最初に見ると、同じ値なのになんでUnsharedと表示されるのかと混乱の元になります。というか、なりました。

あくまでこれはスタート地点です

Unsharedの正体が分かって一安心でしたが、まだ問題はこれからです。選択した頂点がUnsharedか判別できてませんから……。
キッカケで書いた通りカラーを取得しても数値(頂点フェースのカラーの平均値)を取得するだけでUnsharedかはチェックしてくれません。なのでここからがスタートです。
では、どこを見ればUnsharedになる条件を満たすのか?
答えは単純で頂点フェースの毎のカラーを比較するだけです。全てのカラーを比較してRGBAの値が全て同じならUnsharedではないとなります。
ただし、単純にRGBAを1つつずつ比較してくとソースが長くて複雑になります。
僕個人としてはB(青)値だけが変わっても全てがUnsharedになっていることに注目しました。これは「RGBAの数値の1つでも違う=Unshared」「RGBAの全ての値が同じ=Unsharedではない」と成り立ちます。RGBAをまとめてから比較をすれば手間が1/4のになります。

チェック方法が分かればソースを作るだけ

チェック用のソースの一例です。
RGBAの数値をStringで結合して文字列が等しいかチェックしてます。

string $unList[];
string $vtxList[] = `polyListComponentConversion -tv`;
for($vtx in `ls -fl $vtxList`){
    string $vfList[] = `polyListComponentConversion -tvf $vtx`;
    $vfList = `ls -fl $vfList`;
    // gmatchコマンドで比較しやすいようにfloatArrayToStringでString化&結合 
    string $source = floatArrayToString(`polyColorPerVertex -q -r -g -b -a $vfList[0]`, ", ");
    for($vf in $vfList){
        string $taget = floatArrayToString(`polyColorPerVertex -q -r -g -b -a $vf`, ", ");
        if(!`gmatch  $source $taget`){
            $unList[size($unList)] = $vtx;
            break;
        }
    }
}
print($unList);

文字列が等しくなかったら、どこかの値が違っているので変数$unListに追加していってます。
試してみると分かりますがUnsharedの頂点がリスト化されています。
ちなみに今回は僕の趣味でMelソースになってるけど、頂点を全て検索かけると時間がかかるので慣れている人はPythonで作ることをお勧めします。

英語の意味を調べるのも重要

この件に関して僕の個人的な反省点があります。それは「Unshared」を英語で捉えないで半分記号的に見てました。しかも「Unshade」と読み間違えて、しばらくはシェーダー関連の言葉と勘違いしてました(ブログを校正したら6ヶ所も打ち間違えがあったのは内緒)
解決してみればUnshared(非共有の)の言葉の通りなのに、かなり遠回りして調べてしまいました。
あまりに当然だけどコマンドなどは翻訳できる言葉なので命令を言葉として理解する重要性を改めて知りました。

Author: 中林 伸和