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

2010年2月21日日曜日

オブジェクトの軌跡をNurbsカーブで描く。

移動するアニメーションがついたオブジェクトの軌跡をNurbsカーブで描くスクリプト

アニメートされたオブジェクトにパーティクルをからめるために、その軌跡をみて、どこで急旋回しているかを見る必要があったので、その軌跡をカーブにすることにしました。

MotionTrailを使う手もあるのですが、アニメーション変更時に重い時があったのと、後でパスカーブ・アニメーションに使う事も考えて、スクリプトでNurbsカーブを作成することにしました。


内容的には以下のようなスクリプトになります。
★フレーム毎にオブジェクトの位置情報を取得し格納
★最後にその情報をもとにカーブを描く


以前作ったスクリプトが応用できそうなので、そちらをベースに作る事にしました。
参照1:「exercise: ロケータ位置をpvとするカーブを描く
参照2:「1フレーム毎にオブジェクトをデュプリケートし、表示を切り替えるスクリプト



----------------------------------------
まず各フレームのロケータの位置情報を取得するスクリプト。
最初、テスト用にPrint文をforループの中に入れていたので、毎フレーム$pointの中身を表示して、すべてのフレームを終了するのに時間がかかりました。
これをfor文の外に出して、すべてのフレームが終了した後にprintを実行するようになりました。
currentTimeは、現在のフレーム位置を指定するコマンドです。
一フレームずつ進めるにはfor文でループを作りその中で、このコマンドを使います。
フレーム数はfor文の条件でつかう変数で指定すると簡単です。

{
vector $pointLoc;
string $point;

int $startFrame = 1;
int $endFrame = 10;

string $name[] = `ls -sl`;


for ($i=$startFrame; $i<$endFrame; $i++){
currentTime $i;
$pointLoc = `xform -q -t -ws $name[0]`;
$point = $point + " -p " +$pointLoc;
}
print $point;
}


実行結果:
-p 0 0 0 -p -0.5776165648 0.7466481419 0.0007793744514 -p -1.225671132 1.524006415 0.00294898415 -p -1.92303246 2.32286197 0.006256059731 -p -2.648568749 3.134001317 0.01044782912 -p -3.381149095 3.948211975 0.0152715252 -p -4.099641563 4.756280305 0.02047437456 -p -4.78291548 5.548994105 0.0258036127 -p -5.40983845 6.317139182 0.03100646194

-----------------------------------------
次にこのデータを使ってNurbsカーブを作成するように変更。

{
vector $pointLoc;
string $point;

int $startFrame = 1;
int $endFrame = 10;

string $name[] = `ls -sl`;

for ($i=$startFrame; $i<$endFrame; $i++){
currentTime $i;


$pointLoc = `xform -q -t -ws $name[0]`;
$point = $point + " -p " +$pointLoc;

}
eval ("curve" + $point);
}


実行結果:
10フレームまでのNurbsカーブが作成されました。


---------------------------
実際のシーンは合計2000フレームほどあるので、1フレーム毎だとPVの感覚がせますぎます。
このため、5フレーム毎に位置情報を取得するように変更しました。
二つのループを入れ子にすることで、内部のFor文はフレームを一つづつ進めて、外部のForを5フレーム毎に動作するものにしました。

{
vector $pointLoc;
string $point;

int $startFrame = 1;
int $endFrame = 10;

// string $name[] = `ls -sl`;

for ($i=$startFrame; $i<$endFrame; $i+=5){

for ($k=$i; $k<$i+5; $k++){
print ("$K="+$k+"\n");
};
print ("$i="+$i+"\n");
};
}

実行結果:
$K=1
$K=2
$K=3
$K=4
$K=5
$i=1
$K=6
$K=7
$K=8
$K=9
$K=10
$i=6


$kが現在のフレームを意味しています。
$iは位置情報を取得することを意味していますが数字にはいみはありません。
$i=1は$k=5の後にあります、これは5フレーム目に到達した後が、位置情報を取得することを意味しています。
$i=6は$k=10なので、この場合は10フレーム目に到達した後に位置情報を取得します。

これでは、位置情報を取得するフレーム。すなわちカーブの始まるフレームが毎回5フレーム目からになってしまいます。


----------------------------------------
フレームを進める前、すなわちFor文の前にスタートフレームの位置を取得する行を追加します。
以下は、その行を書く位置を確認するためにprint文を使っています。

{
vector $pointLoc;
string $point;

int $startFrame = 1;
int $endFrame = 10;

// string $name[] = `ls -sl`;

print ("GetStartFrame"+"\n");

for ($i=$startFrame; $i<$endFrame; $i+=5){
for ($k=$i; $k<$i+5; $k++){
print ("$K="+$k+"\n");
};
print ("$i="+$i+"\n");
};
}


実行結果:
GetStartFrame
$K=1
$K=2
$K=3
$K=4
$K=5
$i=1
$K=6
$K=7
$K=8
$K=9
$K=10
$i=6

これで"GetStartFrame”と$iのprintコマンドがあるところへ、位置情報を取得する行すなわち「$point」へ代入する式を配置すればよいことがわかります。


----------------------------------------
上記では5フレーム毎ですが、設定を自由に変えられるように変数を使いました。
また、タイムラインで途中のフレーム位置にいると、スタート・フレーム位置を取得すべきタイミングで、現在位置を取得してしまうので、(たとえばスタート・フレームが1に設定しても、現在のシーンファイルでフレーム5にいたら、フレーム5の現在位置を一番最初の位置情報として取得してしまう。)
最初の位置情報取得前にcurrentTimeを使ってスタートフレームにリセットするようしました。


{
vector $pointLoc;
string $point;

int $startFrame = 1;
int $endFrame = 30;
int $perFrame =5;

string $name[] = `ls -sl`;

currentTime $startFrame; //reset TimeLine

$pointLoc = `xform -q -t -ws $name[0]`;
$point = $point + " -p " +$pointLoc;

for ($i=$startFrame; $i<$endFrame; $i+=$perFrame){

for ($k=$i; $k<$i+$perFrame; $k++){
currentTime $k;
};

$pointLoc = `xform -q -t -ws $name[0]`;
$point = $point + " -p " +$pointLoc;
};
eval ("curve" + $point);
rename "pathCurve";
}


これで目的を達成出来ました。

0 件のコメント:

コメントを投稿