パーティクルのインスタンス 3

インスタンスとフィールドの組み合わせ

インスタンスで作った羽根などのオブジェクトを、フィールドによってアニメーションさせてみましょう。

インスタンスの使用例 3

  1. 以下の MEL スクリプトを makeInstance7.mel という名前で作ります。
    proc string makeFeather()
    {
    	string $file;
    
    	string $cname = `curve -d 3 -p -0 -0 0 -p 0.2 0.2 0 -p 0.4 0.6 0 -p 0.6 0.4 0 -k 0 -k 0 -k 0 -k 1 -k 1 -k 1`;
    	if(`about -nt`)
    	{
    		$file = "C:/Program Files/AliasWavefront/Maya5.0/brushes/feathers/featherWhite.mel";
    	}
    	else if(`about -linux`)
    	{
    		$file = "/usr/aw/maya5.0/brushes/feathers/featherWhite.mel";
    	}
    	eval ("source \"" + $file + "\"");
    	string $fname = `getDefaultBrush`;
    	setAttr ($fname + ".globalScale") 5;
    	string $tname = `createNode transform`;
    	string $sname = `createNode stroke -p $tname`;
    	connectAttr ($fname + ".obr") ($sname + ".brs");
    	connectAttr ($cname + ".ws") ($sname + ".pcv[0].crv");
    	return $tname;
    }
    
    proc string [] makeParticle(int $num, float $min, float $max)
    {
    	int $i;
    	string $pos = "";
    	for($i = 0; $i < $num; $i++)
    	{
    		float $x = rand($min, $max);
    		float $y = rand($min, $max);
    		float $z = rand($min, $max);
    		$pos += ("-p " + $x + " " + $y + " " + $z + " ");
    	}
    	return `eval ("particle " + $pos)`;
    }
    
    global proc makeInstance7()
    {
    	string $pname[] = makeParticle(20, 0.0, 20.0);
    	string $oname = makeFeather();
    	select -tgl $pname[0] ;
    	particleInstancer  -addObject -object $oname $pname[1];
    	addAttr -ln myRotate -dt vectorArray  $pname[1];
    	dynExpression -s
    		("if(frame == 1)"
    		+ "{"
    		+ "	$rand = rand(0,180);"
    		+ "	myRotate = <<$rand, $rand, $rand>>;"
    		+ "}")
    		-creation $pname[1];
    	dynExpression -s 
    		("if(frame > 1)"
    		+ "{"
    		+ "	float $val = particleId % 5.0 / 20000.0 + 0.0001;"
    		+ "	myRotate += <<$val, ($val * 2),($val * 3)>>;"
    		+ "}")
    		-runtime $pname[1];
    	particleInstancer -e -name instancer1 -rotation myRotate $pname[1];
    
    	select $pname[0];
    	string $gname[] = `gravity -magnitude 0.1`;
    	connectDynamic -f $gname[0] $pname[0];
    }
    
  2. Script EditorFile → Source Script によって makeInstance7.mel を読み込みます。
  3. Script Editor のインプットウインドウで、makeInstance7() を実行します。
    [makeInstance7() 実行図]
    [makeInstance7() レンダリング図]
  4. アニメーションを実行します。
    アニメーション実行結果

スクリプトの解説

proc string makeFeather()
makeFeather というプロシージャーの宣言です。
global がついていないので、この MEL スクリプトの中だけで有効です。
このプロシージャーでペイントエフェクトによる羽を作り、 作った羽根のストロークの名前(トランスフォームノード)を返します。
string $file;
羽根を作る MEL スクリプトのファイル名を入れておく文字列変数です。
string $cname = `curve -d 3 -p -0 -0 0 -p 0.2 0.2 0 -p 0.4 0.6 0 -p 0.6 0.4 0 -k 0 -k 0 -k 0 -k 1 -k 1 -k 1`;
ペイントエフェクトのストロークを作るために NURBS カーブを作ります。
if(`about -nt`)
{
  $file = "C:/Program Files/AliasWavefront/Maya5.0/brushes/feathers/featherWhite.mel";
}
この MEL スクリプトを実行している OS が Windows かどうかを調べて、 そうであるならば、 featherWhite.mel の存在しているホルダー名とともに変数 $file に代入します。
else if(`about -linux`)
{
  $file = "/usr/aw/maya5.0/brushes/feathers/featherWhite.mel";
}
この MEL スクリプトを実行している OS が Linux かどうかを調べて、 そうであるならば、 featherWhite.mel の存在しているディレクトリ名とともに変数 $file に代入します。
eval ("source \"" + $file + "\"");
source コマンドによって変数 $file に入っている MEL スクリプトを読みこんで実行します。
source コマンドに変数を与えて実行する場合は、 eval コマンドによって実行しないとうまくいかないことに注意してください。 (Tips 参照)
string $fname = `getDefaultBrush`;
getDefaultBrush コマンドによって現在、有効になっているブラシの名前を得ます。
ここでは、 featherWhite.mel で作られた羽根です。
setAttr ($fname + ".globalScale") 5;
ブラシの .globalScale アトリビュートに 5 を設定して、 見やすいように羽の大きさを大きくしておきます。
string $tname = `createNode transform`;
ストロークの親になるトランスフォームノードを作ります。
string $sname = `createNode stroke -p $tname`;
ブラシのためにストロークを作ります。
トランスフォームノード($tname)を親ノードにします。
connectAttr ($fname + ".obr") ($sname + ".brs");
ブラシのデータ出力アトリビュート(obr)を、ストロークのアトリビュート(brs)にコネクトします。
これによって、ブラシがストロークに使われるようになります。
connectAttr ($cname + ".ws") ($sname + ".pcv[0].crv");
カーブ($cname)のアトリビュート(ws)を、ストローク($sname)のアトリビュート(pcv[0].crv)にコネクトします。
これによってカーブ($cname)がストロークに使われるようになります。
return $tname;
ストロークのトランスフォームノードの名前を、 プロシージャーの返り値として返します。
proc string [] makeParticle(int $num, float $min, float $max)
ある範囲中の、ランダムな位置にパーティクルを作る makeParticle というプロシージャの宣言です。
各引数の意味は以下のとおりです。
$num
作られるパーティクルの個数
$min
パーティクルが作られる範囲の下限
$max
パーティクルが作られる範囲の上限

X, Y, Z 方向の $min から $max の範囲にパーティクルが作られます。
返り値は、作られたパーティクルのトランスフォームノードとシェープノードの名前なので、 文字列の配列にしておきます。
int $i;
for 文で使用するカウンター用の変数です。
string $pos = "";
パーティクルの位置を指定するための文字列変数です。
for($i = 0; $i < $num; $i++)
for 文を $num 回くり返して実行し、 パーティクルを $num 個作ります。
float $x = rand($min, $max);
$min から $max までの乱数を $x に代入します。
float $y = rand($min, $max);
$min から $max までの乱数を $y に代入します。
float $z = rand($min, $max);
$min から $max までの乱数を $z に代入します。
$pos += ("-p " + $x + " " + $y + " " + $z + " ");
上で得た $x, $y, $z をパーティクルの座標値として文字列変数 $pos に代入しておきます。
return `eval ("particle " + $pos)`;
particle コマンドに、パーティクルの座標が入った $pos を与えて実行し、 パーティクルを作ります。
作られたパーティクルの名前が、return によってプロシージャーの返り値として返されます。 返されるパーティクルの名前は、 トランスフォームノードとシェープノードの名前です。
global proc makeInstance7()
makeInstance7 というプロシージャの宣言です。
string $pname[] = makeParticle(20, 0.0, 20.0);
上の makeParticle プロシージャによって、 (0.0, 0.0, 0.0) から (20.0, 20.0, 20.0) の範囲にパーティクルを 20 個作ります。
string $oname = makeFeather();
makeFeather プロシージャーによって羽を作ります。
$oname にはストロークの名前が入っています。
select -tgl $pname[0] ;
パーティクルを追加してセレクトしておきます。
この時、ストローク($oname)はすでにセレクトされています。
particleInstancer -addObject -object $oname $pname[1];
インスタンサーノードを作成して、パーティクルの点の位置にコーンを配置します。
このコマンドによってパーティクルインスタンサ−ノードが作られて、 その名前が文字列変数 $iname に代入されます。
各フラグの意味は以下のとおりです。
-addObject
インスタンスとしてオブジェクトを追加
-object $oname
追加するオブジェクトの指定
ここでは羽のブラシが付いたストローク($oname)
addAttr -ln myRotate -dt vectorArray $pname[1];
パーティクルに myRotate という名前のアトリビュートを追加します。
myRotate の型は vectorArray というベクトルの配列で、 一つ一つのベクトルがインスタンスの回転をコントロールします。
dynExpression -s
("if(frame == 1)"
+ "{"
+ "  $rand = rand(0,180);"
+ "  myRotate = <<$rand, $rand, $rand>>;"
+ "}")
-creation $pname[1];
パーティクル作成時(-creation)のダイナミックエクスプレッションを設定します。
内容は makeInstance4.mel と同じなので、そちらを参照してください。
dynExpression -s
("if(frame > 1)"
+ "{"
+ "  float $val = particleId % 100.0 / 100000.0 + 0.0002;"
+ "  myRotate += <<$val, ($val * 2),($val * 3)>>;"
+ "}")
-runtime $pname[1];
アニメーション実行時(-runtime)のダイナミックエクスプレッションを設定します。
内容は makeInstance4.mel とほぼ同じなので、そちらを参照してください。
particleInstancer -e -name instancer1 -rotation myRotate $pname[1];
インスタンサ−ノード $iname に、 インスタンスの回転をコントロールするアトリビュートとして myRotate を使用するように設定します。
各フラグの意味は以下のとおりです。
-e
エディットモード
-name $iname
設定を変更するインスタンサ−ノードの指定
-rotation myRotate
回転をコントロールするアトリビュートの指定
select $pname[0];
gravity フィールドのためにパーティクルをセレクトしておきます。
string $gname[] = `gravity -magnitude 0.1`;
gravity フィールドを作り、強さ(-magnitude)を 0.1 にしておきます。
なるべく強さの値は小さい方がアニメーションが見やすいでしょう。
connectDynamic -f $gname[0] $pname[0];
パーティクルと gravity フィールドをコネクトして、 フィールドがパーティクルに作用するようにします。

Tips (about)

about コマンドは OS を調べるだけでなく、 以下のようなフラグによって様々な情報を調べることができます。

-v
Maya のバージョン
-p
Maya の製品名
Maya が Complete か Unlimited かを調べることができます。
-env
環境ファイル Maya.env の場所

Tips (source)

source は他の MEL コマンドと違うので、 使用する場合には注意が必要です。
例えば、makeInstance7.mel の makeFeather プロシージャーの一部を以下のように書き変えると、 if 文で場合分けしているにもかかわらず、 2 つの source コマンドが両方とも実行されてしまいます。

	if(`about -nt`)
	{
		source "C:/Program Files/AliasWavefront/Maya5.0/brushes/feathers/featherWhite.mel";
	}
	else if(`about -linux`)
	{
		source "/usr/aw/maya5.0/brushes/feathers/featherWhite.mel";
	}

このような場合は、 makeInstance7.mel のように、 読みこむ MEL ファイルをいったん変数に代入しておいて、 eval コマンドによって source を実行する必要があります。

練習

練習課題

参考


Prev | Prev
Home | Contents
Mail