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

2009年3月27日金曜日

練習 (9) lsコマンド:コンポーネントの選択

今回は、lsコマンドについて調べてみた。
きっかけはnClothでデブリのシミュレーションを行ったときに、どうしても小さな振動を繰り返す部分やコリジョン判定がうまくいかずいびつな形で、一箇所で回転を繰り返すもの、シミュレーションに関係なく平面を滑り続ける物などがでてきてしまう。
Dumpを上げればあるていどおさえることはできるが、ごまかさない限りは実用できない。

こららはひとつのポリゴン・オブジェクトなので、バーテックスレベルで各デブリをグループとして制御することができればなんとかなるかもしれないと思ったのがきっかけだ。

実際にそのようなレベルのスクリプトを書くことは今はできないが、
そういったスクリプトに関係ありそうなコマンドを一つづつ勉強していこうと思ったのがきっかけだ。

--------------------
さて、MayaにおいてGUIを使った作業は、
1.メニューから何かを作成
2.選択した対象に対して何かの操作をする。
の二つとなる。

とくに選択した対象に行う作業は、全体の作業からみて大きな割合をしめていると思う。

Melを使う目的でもある、「作業の自動化」においてもこの「選択」の手順は避けて通ることはできない。

しかしながら、この作業はGUIでやるとさほど意識する必要がないのだが、
Melでやるとなると、初心者には非常に取っつきづらい。
なにより以下の事を常に意識して操作する必要がでてくる。
1)選択対象の名前
2)選択対象が複数ある場合のID番号
スクリプト作業がめんどくさく感じる点でもある。

ただ、この操作をするためのMelのパターンを一度おぼえてしまえば、
選択対象に、メニューには無い思い通りの操作を手軽に適用できるようになる。
これは、とくに「デブリ」、「パーティクル」といった、
大量のものをコントロールする機会の多い
エフェクツ・アニメーションには役に立つのではないかと思う。

オブジェクトを選択して、その内容を表示するには、
「ls」コマンドを使うのは以前に使ったことがあるのでなんとなく知っていた。
それにLinuxのシェルコマンドと同じなので、Linux側で使う機会も多かったので親しみもある。

エフェクツ作業では、オブジェクトの選択も使うが、
バーテックスやパーティクルIDといったコンポーネントレベルで操作が必要なことが多い。

このコンポーネント・レベルで選択をしたものをリスト化し、
変数に代入することができればいろいろと使い道があるのではないかと思う。


よって今回はコンポーネント(ポリゴン頂点)を選択した状態で、どうなるかを調べてみた。

--------------------
まずポリゴン頂点を複数選択し、
ls -sl
を実行してみたところちゃんと答えが返ってきた。
// Result: polySurface1.vtx[255:257] //

Linuxのシェル・コマンドと同じなので、このあたりは問題ない。
-slを含めていくつか、必要になりそうなスイッチをヘルプで調べてみた。

-sl(-selection) :「選択」、現在選択しているオブジェクト/コンポーネントがリストされる。
例:// Result: polySurface1.vtx[255:257] //

-hl(-highlight) :「強調」、コンポーネントが選択されハイライトされているオブジェクト名がリストされる。(注:オブジェクトが選択されている場合は値はかえってこない。)
例: // Result: polySurface1 //

-g(-geometry):ジオメトリ DAG オブジェクトがリストされる。
例: // Result: dc polySurfaceShape1 //

これで、コンポーネントの番号と、そのノード名は取得できることが分かった。

この操作ではただ、値を表示するだけなので、
ちゃんとこの値を使うにはもっとやるべき操作がある。


一番よく使われると思われるのがこの値を変数へ代入する作業だと思う。

--------------------
まず作ってみたのが次のスクリプトだが、これはエラーになった
{
string $art;
$art = (ls -sl);
print $art;
}

// Error: $art = (ls -sl); //
// Error: Line 3.12: Invalid use of Maya object "ls". //

ls -slをエクスプレッションとして扱うために括弧で囲めばよいとおもったのだが、
うまく行かなかった。

--------------------
それでは、文字列変数に代入するということだから、" "で囲んだ方がよいのかと思いつけてみた。
( )内の結果が” ”で文字列として扱われるだろうと読んだのだが...。
{
string $art;
$art = "(ls -sl)";
print $art;
};

少し考えればわかることだが、” ”で挟まれたその間にあるものはすべて文字列で扱われる。
当然、エラーは出ないが、
(ls -sl)
と表示されただけだ。

--------------------
それでは、と記憶をたどって以下のようにしてみた。
{
string $art;
$art = `ls -sl`;
print $art;
}
// Error: line 3: Cannot convert data of type string[] to type string. //

そこで、変数になにか問題があるのかと思い変数名を変えてみたり、
最初の変数宣言を消してみたりしたが、うまくいかない。
やはりこのやり方もダメなのか...。
お手上げになってきた。

--------------------
ここで諦めるは、壁を突破できず、Melをマスターすることはできない。

そこで、もういちどエラーをよく見直してみた。
「string[]タイプをstringタイプには変換できない」といっている。

変数のタイプが異なるものをある変数へ代入しようとするとき、
Mayaは自動的に変換を行うことがある。
ヘルプのインプリシット変換がそうだと思うのだが、
「Maya は数値と文字列が混在していて、意図が明白である場合、
自動的に数値を文字列に、または文字列を数値に自動的に変換します。」

しかし、今回は文字列を文字列に代入しようとしているので、そのような変換は行われないはずだが...。

たしかに、よくエラーをみると「string[]」となっている。
これは配列型で、ひとつの変数ではない。
なぜこのようなエラーがでるのかを考えてると、
lsコマンドで返ってくる値が配列型になっているということだ。

たしかにデータの「代入」においてエラーがでている。
「`ls -sl`」の部分に関してはエラーはない。

ヘルプで、lsコマンドのところを見直してみた。

すると、いままで、ちゃんと見ていなかったが、大きく
戻り値
string[]
と表記してあった。
ヘルプはこのようなところもちゃんと読まないといけいないなと思った。

このコマンドが返してくるのは配列なのだ。


そこで変数を配列に変えてみた。
これでうまくいくはずだが。
{
string $art[];
$art[] = `ls -sl`;
print $art[0];
}

しかしエラーになる。
// Error: $art[] = `ls -sl`; //
// Error: Line 3.6: Syntax error //

さっきとエラーが違うので、さっきの問題は解決したらしい。

しかし同じ行にエラーがでている。

--------------------
今回、「配列」には時間を割きたくないので、適当にやってみることにした。

まず、記憶にある配列に関する決まり事をおさらいしてみる。
配列は宣言時には[ ]を使い「配列」であることを明確にする。
[]内は配列の初期サイズを明記することもできるし、空欄にしておくこともできる。
代入には[]に数字(配列のインデックス)を入れて特定の番号に値を代入する。

しかしここでは特定のインデックスに入れたいわけではない。

結論から言うと以下のようにしてうまくいった。
代入時の[]を省略した。

{
string $art[];
$art = `ls -sl`;
print $art[0];
}

これでちゃんと値を表示できた。

--------------------
あとでヘルプを見直すと、配列のリテラル表現のところにある説明がこれに該当するのだと思われる。

「配列型変数にリテラル値を代入する際に、明示的な宣言を使用してもしなくても構いません。」

最初に、この文章をよんだだけではおそらく理解できなかったと思うが
おそらく、こういう理由で代入時には[]を省略できたのだと思う。

しかしながら、この説明には、すこし矛盾を感じる部分があった。

--------------------
それを説明する前にまず、「リテラル」をはっきりさせておきたい。
「リテラル」とは、変数に対し、実際の変化しない値である「定数」を意味する。
元々、この言葉は「文字通り」という意味である。

「255」「fujiyama」など、いわゆる単なる数字や文字列がリテラルの代表例である。e-words

しかし、「配列リテラル」となると少し違ってくる。
配列のリテラル表現は、値(すべて同じ型)をカンマで区切って並べ、中カッコ({ })で囲みます。

これはFlashスクリプトでも似ているので、Melに限った決まりではないようだ。
配列リテラルは、角カッコ ( [] ) で囲まれ、カンマ ( , ) を使用して配列エレメントが区切られます。


ここで本題に戻るが、実は、lsコマンドで返ってくる値は、カンマではなく、スペースで区切られている。
ls -sl;
// 結果: pSphere1.vtx[67:70] pSphere1.vtx[87:91] pSphere1.vtx[107:112] //

スペースがカンマの代りと考えれば、それでいいのかもしれないが、なんとなく釈然としない。


<課題>
「配列」はもっとあとになって扱おうとおもっていたが今回、思いがけず配列を使うことになってしまった。
配列については、また今度くわしく調べたいと思っているので、その機会にこのリテラルのこともはっきりさせたい。


それから今回は頂点を選択したが、
複数の頂点を選んだ時、その番号が連続していると、ひとつの配列インデックスに代入されてしまう。
例:polySurface1.vtx[191:195]
これも将来的には原因をつきとめ、ひとつの配列インデックスにひとつの頂点の値が入るようにしたい。

 

0 件のコメント:

コメントを投稿