チュートリアル / 読んで触ってよくわかる!Mayaを使いこなす為のAtoZ
第38回:ポリゴン数をリストアップしよう!(2/4)ポリゴン数順のリストを作ろう

2013.02.26

  • Maya
  • ゲーム
  • チュートリアル
  • モデリング
  • 中級者
  • 学生・初心者
  • 教育
  • 映画・TV

前回は選択したモデルもしくは選択がなければシーン全体のモデルのポリゴン数をつらつらと表示するツールまで完成しました。

今回はモデル名をポリゴン数の多い順でリスト表示するようにするのが目標です。どうやるか想像してみると、なんとなくパッと思いつきそうで思いつかない感じでしょうか…。

リストの扱いは、実のところMELが苦手としているところなので、余りキレイに解決出来ません。Pythonならもっとキレイにプログラムできるのですが、まあ、色々工夫しながらMELでやってみましょう。

ポリゴン数リストの順番を整える

MELには「sort」というコマンドがあります。実行すると渡した配列の中身が並び替えられます。例えば以下を実行してみましょう。

sort {10, -1, 5};





スクリプトエディタには「-1 5 10」という順番になって結果が表示されます。

ん、一応数字が気持よく整列してくれてますが、小さい順ですね。
ポリゴン数の多い順が知りたいのですが、MELではこれしかないので仕方ありません。forループを実行する時に、順序を逆から実行していくことで、「大きい順」に中身を辿ることにしましょう。

sortのルール

数字でも文字列でもなんでも配列になっていればソートして順番を整えられます。文字列はアルファベット順とかでソートします。例えば「polyA:500」「polyB:10」をソートすると「poly」までは差がありませんが、「A」と「B」の差でもって「A」の方が小さいということになります。

文字列で「1000」と「50」をソートすると、まず「1」と「5」を比べます。「1」と「5」では「1」の方が小さいので「1000」が先に来てしまいます。文字列では「50」より「1000」が小さいと判定されるのです。要注意です。

一方、数字の配列なら「50」が先に来ます。文字列の配列、数字の配列、どちらをsortするかで結果が異なりますので注意が必要です。

というわけで今回はポリゴン数を一旦intの配列にして、それをソートします。
前回作ったスクリプトのforループ内のコードを修正して、ポリゴン数をint配列にまとめるようにしましょう。

次のようなコードにしてみました。

proc getMeshList(){
string $meshes[] = `ls -sl`; // 選択したものをゲット
if ( size($meshes) == 0 ){ // もし選択が空なら
$meshes = `ls -type mesh`; // シーン内のmesh全てゲット
}

int $nums[];
for ( $mesh in $meshes ){
int $numTris[] = `polyEvaluate -t $mesh`;
$nums[ size($nums) ] = $numTris[0];

}
print $nums;
}
getMeshList();



実行すると以下の感じで、スクリプトエディタにポリゴン数がずらりと表示されます。



モデルのリスト順にポリゴン数が表示されています。

コードの中で、

$nums[ size($nums) ]



というところがあります。変数自身のサイズを添え字にすることで、順々に$nums配列が増えていきます。これはしょっちゅう使用する方法です。あんまりMEL以外では見かけない気もします。

これで$numsに三角ポリゴン数のリストが出来ました。ではソートしてみましょう。

「print $nums;」の行を次のスクリプトで置き換えてみましょう。

// ソート
$nums = sort($nums);
print $nums;



実行すると、スクリプトエディタに数字が小さい順に表示されましたか?



ポリゴン数リストを大きい順にする

ソートするとポリゴン数の少ない順になります。今回のツールはリダクションの補佐ツールなので、ポリゴン数の多いものからリスト表示されたほうが便利です。

これは単にforループを逆順に行えば良いだけです。例えば「print $nums;」をまた次のように変更してみましょう。

for ( $i = size($nums)-1; $i >= 0; $i-- ){
print ($nums[$i] + "¥n");
}





どうですか?ポリゴン数の多い順に結果が表示されましたか?

「size($nums)」は配列のサイズを返します。「$nums」の中身が「$nums[0]~$nums[9]」まであれば「10」を返します。「9」ではなく「10」を返します。でも「$nums」の最大要素は「$nums[9]」です。というわけで、添え字に使う「$i」から1を引かないといけませんので注意が必要です。

ポリゴン数リストとオブジェクト名のマッチング

ポリゴン数の多い順のリストが出せるようになりました。この結果に合わせてモデル名を表示すれば完成です! しかしどうしたものか…。

モデル名の配列を作り、それをどうにかソートした結果に合わせて順序を変えて…なんだかいろいろ考えるとややこしそうですね。

こういう時は余り複雑に考えないで、シンプルに行きましょう。単純な方法で考えれば「モデル名」と「ポリゴン数」を一つにまとめた文字列、例えば「pCube-12」という文字列を作り、リストにして、「$nums」のポリゴン数とくらべて同じ数字が入っているものを探せば良いわけです。

同じポリゴン数のものが複数あったら?同ポリゴン数なので順序も同位ですから問題ありません。

というわけで新たに「$data」という配列を作って「モデル名+”-“+ポリゴン数」を記録しておきます。モデル名とポリゴン数はハイフンで区切ることにします。Mayaはオブジェクト名にハイフンが使えないので、区切り文字として丁度良いのです。

スクリプトは以下のようになります。もうこの関数は完成を迎えているのでstringの配列を返すようにしましょう。そうすることで、別の関数からいつでもモデルのリストを取得できるようになります。

proc string[] getMeshList(){
string $meshes[] = `ls -sl`;
if ( size($meshes) == 0 ){
$meshes = `ls -type mesh`;
}
int $nums[];
string $data[]; // 追加
for ( $mesh in $meshes ){
int $numTris[] = `polyEvaluate -t $mesh`;
$nums[ size($nums) ] = $numTris[0]; // ポリゴン数のリスト
$data[ size($data) ] = $mesh + "-" + $numTris[0]; // 「モデル-ポリゴン数」のリスト
}
// ソート
$nums = sort($nums);

string $results[]; // ポリ数多い順モデルリスト
for ( $i = size($nums)-1; $i >= 0; $i-- ){ // 逆順に(ポリゴン数の大きい方から)辿っていく
string $num = $nums[$i];

// 該当のメッシュを探す。
// 見つかったら値を空""にして、二重に見つからないようにしておく。
//
for ( $j = 0; $j < size($data); $j++ ){
if ( `gmatch $data[$j] ( "*-" + $num )` ){ // "-" + ポリゴン数、が含まれているかどうか
$results[size($results)] = $data[$j];
$data[$j] = ""; // この$data[$j]のオブジェクト名は記録したので、空にしておく
}
}
}
return $results;
}
getMeshList();



ではスクリプトエディタに貼り付けて、実行してみましょう。実行するとこんな下の様な結果が表示されましたか?



ポリゴン数の多い順モデルリストが出来ました!

コード内でグルグルと何度も「$data」をチェックしていますので処理は重めです。本来ならもっと賢い方法で高速に処理できると良いのですが、それは費用対効果によります。

今回のように処理の多少無駄があっても、
・ 実装が単純
・ 大量のオブジェクトがあっても、数秒で終わる
・ 頻繁に実行しない
という感じなので問題にはなりません。気にしない、気にしない:P

もしこのツールを毎日、1分に1回は使うというのなら数秒の処理負荷が大きな問題になるので何か対処が必要でしょうけど、今回は大丈夫ですね。

gmatch

文字列の中に指定した文字が含まれているかチェックするのに「gmatch」を使用しています。便利だけどもちょっとわかりにくいかもしれないので「gmatch」コマンドについて説明します。
このコマンドは、1つ目に指定した文字列内に、2つ目で指定した文字列が入っていれば1を返します。なければ0を返します。

今回実行しているgmatch部分の変数の中身を書くとこんな感じです。

gmatch $data[$j] ( "*-" + $num )
→ gmatch "polyShape1-415" "*-415"


チェックしたい文字列パターン「*-415」を噛み砕いて説明すると、
・ 始めに
・ 「*」 =「何かしらの文字列」があって、
・ 「-415」 = 「-415という文字列」があって
・ 終わる
文字があるかどうかをチェックせよ、という事になります。

「-415」だけにして「*」がないと、「-415という文字で始まって、終わる」文字あるかどうかをチェックせよ、となり0が返ってきてしまいます。初めのアスタリスクが重要です。

「*415」にしてしまうと、「polyShape415」など自然と入っていしまった数字とマッチングして1を返してしまうのでダメです。

おしりにもアスタリスクをつけて「*-415*」にすると、「polyShape-4158」の様に「-415」のあとに数字があった場合にマッチングして1を返してしまうので、これもダメです。



まとめ

これでツールの基礎はほとんど出来ました!…なんか理論ばかりで記事の見た目が退屈ですけど。

次回はGUIを用意してリストを表示してみましょう。ツールとして完成度が一気に上るところですのでお楽しみに。

Maya Learning Channel
製品購入に関するお問い合わせ
オートデスク メディア&エンターテインメント 製品のご購入に関してご連絡を希望される場合は、こちらからお問い合わせください。