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

2010年1月31日日曜日

1フレーム毎にオブジェクトをデュプリケートし、表示を切り替えるスクリプト

Maya2010の中でなぜか、自分が現在使用しているシーンファイルでブーリアンが効かない。
スフィアを二つ作ってもブーリアンを実行するとオブジェクトが消えてしまう

Maya2010を新たに起動すればその中では正常に動作するのだが、そこへオリジナルのキャラクタをインポートするととたんに駄目になる。

どうしてもオリジナルのシーンファイルにあるキャラクターのマスクを一緒にレンダリングする必要がある。
そしてアニメーション付のオブジェクトでブーリアンをするため、ブーリアンの計算が1フレーム毎でおこなわれる必要がる。
また、ブーリアンで作られる形状がフレーム毎に違うのでジオメトリキャッシュは役に立たない。
OBJのシーケンスとしてはき出してインポートできればと思い、プラグインやMelスクリプトをさがしたがちゃんと動作するものを見つけることが出来なかった。


そこで考えたのが、以下の手順。
1)アニメーション付のブーリアンを1フレームごとにデュプリケートする。
2)各ジオメトリのVisibilityを1フレームごとにオン/オフしてアニメートするようにみせかけるということ。
モーションブラーは必要無いので、今回はこれで十分しのげそうだ。


良い機会なので、これをMelで作る事にした。


----------------------------------------
まず1フレームづつ時間軸を移動する必要がある。
そこで役に立つのがCurrentTime。

currentTime :現在のフレーム・時間を決定する。

これを使ってフレームが進むかどうかを確認。
まずSphereを一つ作成し、選択された状態で以下のスクリプトを実行してみる。
{
for($i=0; $i<24; $i++)
{
currentTime$i;
move -relative 1 0 0;
}
}

これはちゃんと動作してくれ、Sphereがフレームが進む毎に1つ移動する。
ちなみにこのスクリプトではフレームゼロから始まりフレーム23、SphereはX方向へ「24」移動して停止する。


----------------------------------------

これをデュプリケートしてやれば良いだけなので、「dupulicate」コマンドを使い以下のようになる。
ちなみにこの例では、Sphereに手作業でキーフレームアニメーションをつけ、moveコマンドは使わずに確認した。

ちなみにこのコマンドを実行すると最初にDuplicate作られたスフィアが選択されたままで、後に続くスフィアは、選択状態にならなかった。
{
string $obj[] = `ls -sl`;

for($i=0; $i<24; $i++)


{
currentTime$i;
duplicate $obj[0];

}
}


----------------------------------------
つぎにこれにキーフレームを打ってやる必要がある。
オブジェクトが存在するフレームはVisibilityの値が「1」でその前後のフレームで「0」になる必要がある。
setKeyframe

指定したオブジェクト(コマンド ラインでオブジェクトが指定されていない場合は、アクティブなオブジェクト)にキーフレームを作成します。
新しいキーフレームのデフォルトの時間はカレント タイムです。この動作は、コマンド ラインで "-t(-time)" フラグを使用するとオーバーライドされます。
キーフレームのデフォルト値はキーフレームを設定するアトリビュートのカレント値です。この動作は、コマンド ラインで "-v(-value)" フラグを使用するとオーバーライドされます。

必要そうなフラグは以下の通り:
-at(attribute):
キーフレームを設定するアトリビュート名
-t(-time):
キーフレームを設定する時間。
-v(-value)
:キーフレームの値

ためしにSphereを選択し、以下のスクリプトを実行してみた.
ちゃんと、フレーム「3」でTranslateXに値「12」のキーが打たれた。

{
setKeyframe -at translateX -value 12 -t 3;
}


あとはこれを応用することになるが、少し工夫が必要なのは、
フレーム前後にもキーを打つ必要があるということだ。

{
string $obj[] = `ls -sl`;

for($i=0; $i<24; $i++)


{
currentTime$i;
duplicate $obj[0];

setKeyframe -at visibility -value 0 -t ($i-1);
setKeyframe -at visibility -value 1 -t $i;
setKeyframe -at visibility -value 0 -t ($i+1);
}
}

しかしこれではうまくいかない。
先ほどのDuplicateのテストでわかっているように現在選択されているオブジェクトが最初にDuplicateで作られたオブジェクトだけなので、
キーフレームはそのオブジェクトにしか付かない。

----------------------------------------
そこでduplicateコマンドを実行すしてオブジェクトを作ると同時にその名を変数へ代入する方法を使う事にした。
参照エントリ(メモ:一行でオブジェクトを作り、その名称を配列へ代入する。
参照エントリ(その他のコントロール(2): checkBox」のアサインの箇所)
これにより名称を変数に代入できるので、その変数をsetKeyframeの対象オブジェクト名として使用すればよい。これにより現在の選択されたオブジェクトに関係なく、キーの設定が可能になる。


{
string $obj[] = `ls -sl`;
for($i=0; $i<24; $i++)

{
currentTime$i;
string $name[]= `duplicate $obj[0]`;

setKeyframe -at visibility -value 0 -t ($i-1) $name;
setKeyframe -at visibility -value 1 -t $i $name;
setKeyframe -at visibility -value 0 -t ($i+1) $name;

}
}



----------------------------------------
ついでにこれらを一つのグループノードにまとめることにします。

group:
-n: 
グループ名
-em: 
空のグループが作成される。


これだけではグループは作成できるが、新たに作られるオブジェクトを逐次グループへ入れていくことは出来ない。そこで必要なのが「parent」。

parent:新しいグループのオブジェクトの移動、既存グループからのオブジェクトの削除、親の追加や削除が行われます。
使い方は以下の通り

parent 移動したいオブジェクト名 親となるオブジェクト名

これらを使って作成したのが以下のスクリプト

{
string $obj[] = `ls -sl`;
group -n DupGroup -em;

for($i=0; $i<24; $i++)

{
currentTime$i;
string $name[]= `duplicate $obj[0]`;

setKeyframe -at visibility -value 0 -t ($i-1) $name;
setKeyframe -at visibility -value 1 -t $i $name;
setKeyframe -at visibility -value 0 -t ($i+1) $name;

parent $name[0] DupGroup;
}
}

----------------------------------------
ついでに最後に、元オブジェクトのVisibilityをオフにします。
setAttr:
使い方は以下の通り

setAttr ノード名.アトリビュート名 アトリビュート値

以下のような行を追加すれば良さそうですが、これではエラーになります。
setAttr $obj[0].visibility 0;
実際には以下のようにする必要があります。
setAttr ($obj[0] + ".visibility") 0;
このあたりの詳細はDigitalMatrixに書かれています。
(DigitalMatrix:「アトリビュートの値の設定」)


{
string $obj[] = `ls -sl`;
group -n DupGroup -em;

for($i=0; $i<24; $i++)
{
currentTime$i;
string $name[]= `duplicate $obj[0]`;

setKeyframe -at visibility -value 0 -t ($i-1) $name;
setKeyframe -at visibility -value 1 -t $i $name;
setKeyframe -at visibility -value 0 -t ($i+1) $name;

parent $name[0] DupGroup;
}

setAttr ($obj[0] + ".visibility") 0;
}


これで狙い通りの動作をしてくれるMelができあがりました。


0 件のコメント:

コメントを投稿