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

2009年5月19日火曜日

exercise: ロケータ位置をpvとするカーブを描く

任意の数と位置に存在する複数個のロケーターを選択し、各位置をpvとするnurbsカーブを作成するスクリプト。

まず大まかなアルゴリズムを考えてみた。
0)ロケータの作成、配置、選択 (マニュアル操作)
1)選択したロケータの各名称を取得し、配列に格納
2)配列のサイズを取得
3)for文、配列のサイズより1つ小さい数まで繰り返す。
4)それぞれのロケータのtx,ty,tzを取得。
5)nurbsカーブを作成、そのときにcvの位置が上記の場所を通るようにする。


この中でわからないのはnurbsカーブをコマンドで作成する方法。
オンラインヘルプで調べると、以下のようにポイントを指定できることがわかった。


-p(-point)はポイントの位置
curve -p 0 0 0 -p 3 5 6 -p 5 6 7 -p 9 9 9;

-d(degree)を使ってcurveの次数を指定できる。デフォルトでは次数3。
curve -p 13 13 13 -p 13 15 16 -degree 1;

-a(append)を使い、カーブ名を指定することで作成したカーブにポイントを追加できる。
curve -a -p 10 10 10 curve2;

ロケータの数だけこの-pフラグを増やしていけばよいのだと思う。

やり方としては二つ考えられる。
一つ目は、curveコマンドをすべてのポイント位置と共にまずテキストで作成し、evalで実行。
二つ目は、最初のポイントを使ってcurveを作成し、以後増えたpointの数だけappendしていく。

スクリプトとしては二つ目の方がすっきりとまとまりそうなので、-appendフラグを使う方法を使うことにする。

for文のロケータ位置の取得と共に、for文の中で実行することが出来そうだが、
これをfor文の中で以下のことを行う必要がある。
●ロケータ位置の取得
●curveコマンドで最初のpointをもったカーブ作成。
●pointをAppendしていく。

カウンタである$iはゼロから始まり1ずつ増加し、ロケータ総数に達したら終了する。
curve -p x y z;
これは最初に一度だけ実行。

curve -a -p x y z;
これを(総数-1)回、繰り返す。追加するカーブの名称が必要だが、この時点では選択されているので問題ないだろう。


これで出来そうだ。
あとはこれをfor文の中で使ってやれば良いだけだ。
まずここまでで座標が取得できるところまで作ってみた。

{
vector $position;
string $name[] = `ls -sl`;
int $total = size($name);
for ($i=0; $i<$total; $i++){
$position = `xform -q -t -ws $name[$i]`;
}
print $position;
}

最初に$positionを宣言しておかないと、for文の中で宣言してもprint文の時には「宣言されていない変数」になってしまう。
これはブロックの外にでてしまうからだろう。
また最初vectorでなくfloatで宣言していたため、xformの返り値を代入するときに
// エラー: float[] 型のデータを float 型に変換できません。 //
となってしまった。
それからxformの-qフラグを付け忘れていたため、// エラー: 無効なリニア単位: -ws // となってしまった。


これで座標の取得は出来たので、curveを作れるように以下のスクリプトを作ってみたが

{
vector $position;
string $name[] = `ls -sl`;
int $total = size($name);

for ($i=0; $i<1;>
$position = `xform -q -t -ws $name[$i]`;

if ($i=0) { eval ("curve -p " + $position); }
else { eval ("curve -a -p " + $position); }

}
print $position;
}

// エラー: "-r" または "-a" フラグでカーブを指定する必要があります。 //
となるので、ためしにelseの所を削除してためしてみたら、
Mayaがフリーズするようになってしまった。
elseの中身にprint$positionをおいてみると、繰り返し$positionを表示し続けて固まっている。
無限ループにはなっていないと思うのだが。

そのうち、何度か繰り返しているとフリーズはしなくなったが、エラーは無くならない。



どうしても行き詰まったのでチャットでシニアアーティストに聞いてみた。
彼からのアドバイスは以下の通り、

1)evalはloopの外で使う。
例:以下が教えてもらった物
  {$blah = ($blah + " -p ")}
   string $curve = ("curve -d " + $blah + ";");
2)if($i==0){}にすべき。


アドバイスのとおり実行してみたつもりだが、

どうやってもダメで、エラーは無くならない。
` `バッククォーテーション とevalはfor文の中ではちゃんと機能しないのか?
if分がfor文の中にあると、ちゃんと機能しないのか?

仕方がないので、-appendフラグを使わないで、全座標をふくむコマンド全体を作ってevalで処理するしかない。
これの解決方法を考えてみた。
必要なのは
AAA
AAA+BBB
AAA+BBB+CCC
AAA+BBB+CCC+DDD・・・
と言う風に新しい値が後ろに付け加わっていくようにして-pフラグ部分を作成し、
それをあとで、文字列「curve」と結合し、evalで実行すれば良い。

{
vector $pObj;
string $point;

string $name[] = `ls -sl`;
int $total = size($name);

for($i=0; $i<$total; $i++){
$pObj = `xform -q -t -ws $name[$i]`;
$point = $point + " -p " +$pObj;
}

eval ("curve" + $point);
}



やってみると、これでちゃんとカーブが作成された。


2 件のコメント:

  1. 以下のスクリプトでうまくいきました。
    elseの処理を少し変えました。

    {
    vector $pos[];
    $name=`ls -sl`;
    int $total=size($name);
    for($i=0;$i<$total;$i++)
    {
    $pos[$i] = `xform -q -t -ws $name[$i]`;
    if($i==0)
    {
    eval("curve -p "+$pos[$i]);
    }
    else
    {
    $curve=`ls -sl`;
    eval("curve -a -p "+$pos[$i]+" "+$curve[0]);
    }
    }
    }

    返信削除
  2. 匿名さん、コメントありがとうございます!
    elseの処理でもできるんですね。(イヤできるはずw)
    着想としては良かったけど詰めが甘かったんですね。
    いやできる事がわかってすっきりしました。ありがとうございます!!

    返信削除