日本でハリウッドVFXを制作! 「経産省アイディアボックス」 結果:  
●まとめエントリはこちら ●FAQ ●お問い合わせは左のメールフォームから

2010年10月2日土曜日

(Mel)デュプリケートされたオブジェクトの同一フェイスにシェーダーをアサインする

結論から言うと、スクリプトとして理論的には動きますが、仕事の効率化という目的においては失敗でした。

仕事で、約2000個デュプリケートされたモデルに、一部の面だけ異なるシェーダーをアサインする必要が発生し、スクリプトでできないかと思い作ってみました。

わかりにくいので図で説明しますと、右端にあるようなオブジェクトをデュプリケートして左のような大きな面積を覆うようにしてあります。
そして下半分がピンク色になっているようにそこだけ異なるシェーダーをアサインします。
ただし、この図と違い、現時点ではすべてひとつのシェーダーしかアサインされていないと考えてください。



今回限りのスクリプトなので、無理をしないで汎用性を犠牲にして、早くつくれるよう心がけました。


-------------
まず、ひとつのポリゴン・オブジェクトの色を変えたいフェイスを選択します。
他のオブジェクトは、すべてデュプリケートして配置を換えただけなので、フェイスのIDは同じパターンになります。

さてこれを、スクリプトエディターでみると
select -r newPanel01.f[3] pCube1.f[6] pCube1.f[36:53] ;
という感じでオブジェクト名(newPanel01)とフェイスのID(例:f[3])が表示されています。
今回は、このフェイスIDを手作業で抜き出し、配列に代入しました。
(これが半自動という所以です)

またオブジェクトは通し番号がついており
newPanel01~newPanel01989まで存在します。

今回のスクリプトは基本的にループの二重構造になっており、手順は以下の通りです。
1)ID情報を配列にいれてデータベースとする。(ループ1でサーフェイスを一つづつ選択するために使用)
2)選択したサーフェイスに指定したシェーダー(lambert3)をアサインする。
3)一つのオブジェクトに必要なすべてのサーフェイスに対して1~2を繰り返す。ループの回数は上記配列からsizeで抽出。フェイスIDの追加を容易にした。(ループ1)
4)次のオブジェクトに対して1~3を繰り返す。
ループの回数は指定したオブジェクトの開始番号から終了番号までを変数で指定して、それをループの値として使用している(ループ2)

今回、手順を考えていく中で、以前のエントリ「ポリゴン・プレーンにシェーダーを市松模様にアサインする (2)」で@Atsushiさんからいただいたアドバイス(コメント欄参照)を思い出して、それに従って考えをまとめていきました。


そのアドバイスとは
1) プログラムは総当たりで単純化
です。

いまだにスクリプト初心者の自分には、まだまだまとめるのは大変だったのですが、
できるだけ一度に一つの処理をさせ、それを繰り返す方向で考えをまとめていくと、意外と早く手順を考え出すことが出来ました。

実行してみたら異常に遅く、固まっているのかそれとも実行中なのかわからなかったので進行状況を表示する機能もつけました。

さて実際のスクリプトは以下のようになりました。

{
int $face[] = {
3,6,11,14,15,18,23,24,29,30,31,32,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,59,64,66,69,74,75,79,
80,81,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,104,105,106,107,108,109,118,123,125,128,133,134,
138,139,140,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,162,163,164,165,166,176,179,184,187,188,191,196,197,
202,203,204,205,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226};
int $fNum = (size ($face));
//print $fNum;
string $fSel;

// loop; pick object number
int $start = 645;  // <<<<<< First number of the panel, usualy it is "1".
int $end = 826;  // <<<<<< Last number of the Panel.


for ($j=$start; $j<$end+1; $j++){
string $pName = ("newPanel0" + $j);

// loop ; pick face ID / command
select -cl;
for ($i =0; $i<$fNum; $i++){
string $fSel = ("select " + $pName + ".f[" + $face[$i] + "]");
eval $fSel;

// face progress
print ("Done:"+ $i + "/" + $fNum + "\n");  

// set Shader
sets -e -forceElement lambert3SG;

}; // end pick face loop

// message
print ("finished:" + $pName + " (Start:" + $start + "- End:" + $end + ")" + "\n"+"\n");
select -cl;
}; // end pick obj loop
}



さて先ほども書きましたが、これを実行してみると遅い遅い
時間を計ってみると一つのオブジェクトの処理に約20秒かかりました。
計算すると作業が終わるまで
20秒×2000個=40000秒=約667分=約11時間
かかることになります。

これではとてもじゃないがスクリプトを使用する意味がありません
幸い今回はオブジェクトは四角のパネルで、規則正しく並んでいるだけなので、一部だけこのスクリプトを使い。
あとはそのオブジェクトをグループ化したものをデュプリケートして、他の場所へ移動して古い物は削除して置き換えという方法に切り替えました。

しかし!!
とんでもないことが起きてしまいました。
どうも調子が悪いのです。
オブジェクトを選択すると、10秒ぐらい固まる。
削除すると、1~2分ぐらい待たされる。
一度にたくさん選択するとそれが何倍にもふくれあがり10分ぐらい返ってこないことも。
それほど大きなオブジェクトじゃなく、少し前まではさくさく作業できたものが、突然これです。
デュプリケートしようとしても同じく待たされます。
しかもセーブしようとしたら30分ぐらいかかってしまう(ファイルサイズは170mbぐらい)

これはどうにも作業できず、いろいろとためしてみましたが原因はわからず。
おそらく何かへんなゴミのような物がオブジェクトに追加されてしまったのかもしれません。
ハイパーグラフでみてもとくに何かつながっている様子もないのでわからずじまい。
(何がおかしかったんでしょうね~????)

実は、スクリプトを書くだけで、すでに2時間近く費やしていたので、かなり焦っていました。
結局はスクリプトを使用する前のシーンファイルに戻り、
スクリプトを使用しないで手作業で10個ほどのオブジェクトにシェーダーを適用。
あとはデュプリケートとグループ化を繰り返して古い物と新しい物を置き換えました。
その時間は、約1時間。最初からそうしておけば良かったと思いました。

結局、効率を上げるも的でスクリプトを使ったにもかかわらず、問題が増え、さらに時間が失われるという本末転倒な結果に終わりました。、
手作業でやって、スクリプトを書くのに費やした時間よりもはるかに短い時間で目的の作業は完了してしまいました。

この程度の物なら10分程度で書けて、10分程度で使い物になるかどうかの結論がだせるようでないとだめですね。

0 件のコメント:

コメントを投稿