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

2009年3月17日火曜日

練習 (4) for文

<状況>
今、nClothを使ったリジッドボディーシミュレーションを行っている。
シーンの概要は、キャラクターが地面にあるデブリ(破片)を跳ね散らかしながらすすんでいくというもの。

バインドとラティスによりアニメーションされた、キャラクターのサーフェイスとデブリがコリジョンするようにしているが、コリジョン判定がうまくいかず、複数のデブリがからみあい、とんがった金平糖のような形になってしまう。

幸い、さほど厳密なコリジョンは必要とされないので、コリジョンにキャラクターのサーフェイスを使うのではなく、サーフェイスのコリジョン位置と同位置にシリンダをコンストレインしてシリンダをコリジョンさせることにした。

具体的には、キャラクタのメッシュにfollicleを作り。その各follicleへ一つづつポリゴンシリンダをpointコンストレインする方法を使うことにした。

余談だがfollicleは「毛根」と意味で、ヘア・システムを使用すると、一つの髪の毛の束をコントロールするためのノードとして、サーフェイス上に作られる赤い小さな○だ。真ん中に小さな棒が立っており、小さな押しピンのような形をしている。
通常はこのfollicleが複数作られて、髪の毛を作ることができる。
このfollicleは髪の毛を作るだけでなく、サーフェイス上にくっついて動くので、サーフェイス上のその位置と角度の情報をこのfollicleから得ることができる。
Melを使うことができない人には、サーフェイス上のある特定の場所の位置と回転情報を取得するには大変便利だ。
服についたボタンを作るなら、follicleをボタンを作りたい場所に作り、そのfollicleにボタンのジオメトリをペアレントコンストレインすれば、終わりだ。
あとは服がclothシミュレーションされていても、バインドされていたサーフェイスであってもしっかりくっついてまわる。(ただし、コリジョンはされない。)
今回はfollicleで得られる、サーフェイス上の特定の位置情報を利用することにした。

follicleの数が多い(今回は47個)ので、シリンダ作成とコンストレインを繰り返す必要がある。


--------------------
<練習>
繰り返しの処理といえば今、集中的にやっているfor文melなので、スクリプトでやることにした。
{ for ($i+1; $i<48;>
 { polyCylinder -name collision; select -clear;
  string $fName = ("fillecileo" + $i);
  string $cName = ("collision" + $i);
  select -add $fName;
  select -add $cName;

  pointConstraint -offset 0 0 0 -weight 1;
}}

このように入力し、実行したところ下記のエラーが発生。
// Error: {for ($i+1; $i<48;>
// Error: Line 1.23: "$i" is an undeclared variable. //
// Error: line 7: No object matches name: fillecile0 //
// Error: string $cName = ("collison" + $i); //
// Error: Line 5.33: "$i" is an undeclared variable. //

まず最初のエラーは、「$iは宣言されていない変数。(二回)」というものだ。
for文内で使用する変数は、
前もって宣言しなくても良かったはずだし、
そもそもMayaでは変数宣言しなくても、最初の代入時に自動的に型が割り当てられるはず。
何となく釈然としないまま、for・・・の前に
string $i;
を付けたところ、このエラーはでなくなった。

次の「fillecile0という名前のオブジェクトは見つからない。」というエラーはまだあるが、
これはスペルが間違っていることがすぐわかったので下記のように修正。
  string $fName = ("follicle" + $i);

しかしまだエラーが出る。
// Error: line 7: No object matches name: follicle0 //

よく見るとfollicleの番号がゼロから始まっている。
すでに作ってあるfollicleの関係上、「follicle1」から始まるように作ったつもりだったが...。

この数字は、for文のループ設定をしているエクスプレション部からとられているので、
その部分をよーくみると、
for ($i+1;
となっていた。
これではちゃんと動かないはず。
最初の変数宣言がされていないというエラーもここに問題があるとわかった。
for ($i=1;
と修正し、string $i; 不要なので削除したところ正常に動くようになった。

最終的にできたスクリプトは以下のようになる。

{ for ($i=1; $i<48;>
 { polyCylinder -name collision; select -clear;
  string $fName = ("follicle" + $i);
  string $cName = ("collision" + $i);
  select -add $fName;
  select -add $cName;

  pointConstraint -offset 0 0 0 -weight 1;
}}

<感想>
for文の変数部の入力間違いは意外と多い。
エラーは正確にバグの内容を示した物ではなく、あくまで実行した結果、なにが実行できなかったかを示すだけなので、その内容から原因を推測する必要がある。
今回もエラーの内容に矛盾を感じつつもそのエラーが意味することをそのまま修正しようとしていたため、不要な変数宣言を付け加えるという愚を犯した。
二つめのエラーの内容も注意深く考慮すれば良かった。
しかし、がエラーの量が多すぎると感じ多少圧倒されたので、ひとつづつ処理していくことにした。
それが今回のような回り道になった。

これはまだなれていないので仕方がないだろうが、そのうちより効率的なバグ処理が出来るようになりたいものだ。

 

0 件のコメント:

コメントを投稿