MELの応用2 (岩石)

岩石を作る 2

前回の岩石を自動生成するスクリプトを少しだけ改良してみましょう。

岩石を作る方法 2

基本的な考え方は前回と同じですが、ポリゴンの分割数を変えて最後にスムースをかけることによって、全体がゆがんだ形になるようにしみます。

今回の作り方は以下の通りです。

  1. 分割数を少なめにしてポリゴンの球を作ります。
  2. 乱数を 3 つ発生させます。
  3. その乱数で X, Y, Z 方向にスケールをかけます。
  4. ポリゴンの各頂点に対して以下の処理を繰り返します。
    1. 乱数を 3 つ発生させます。
    2. その乱数で頂点を X, Y, Z 方向に移動させます。
  5. ポリゴンにスムースをかけます。

岩石を作るプログラム 2

まず、1 個だけ岩石を作るスクリプトを作ってみましょう。

  1. 以下のプロシージャを makeRock4.mel と言う名前でファイルに書き込みます。
    global proc makeRock4()
    {
    	string $poly[] = `polySphere -subdivisionsX 5 -subdivisionsY 5`;
    	float $x = rand(1.0, 2.0);
    	float $y = rand(1.0, 2.0);
    	float $z = rand(1.0, 2.0);
    	scale $x $y $z;
    	string $ver[] = `polyListComponentConversion -toVertex $poly[0]`;
    	string $verE[] = `filterExpand -selectionMask 31 $ver`;
    	for($obj in $verE)
    	{
    		$x = rand(-0.2, 0.2);
    		$y = rand(-0.2, 0.2);
    		$z = rand(-0.2, 0.2);
    		select -r $obj;
    		move -r $x $y $z;
    	}
    	string $polyS[] = `listRelatives -shapes $poly[0]`;
    	polySmooth -divisions 2 -continuity 0.5 $polyS[0];
    }
    
  2. File → Source Script で makeRock4.mel を読み込みます。
  3. Script Editor で以下のコマンドを実行してみます。
    makeRock4();
    [makeRock4() の実行例]

スクリプトの解説

global proc makeRock4()
makeRock4 という名前のプロシージャーを宣言します。
string $poly[] = `polySphere -subdivisionsX 5 -subdivisionsY 5`;
ポリゴンの球を作ります。
$poly には球の名前が代入されます。 (poly[0] にトランスフォームノード、poly[1] にインプットノード)
-subdivisionsX 5
横方向の分割数を 5 にします。
-subdivisionsY 5
縦方向の分割数を 5 にします。
float $x = rand(1.0, 2.0);
1.0 から 2.0 の乱数の値を$xに代入します。
float $y = rand(1.0, 2.0);
1.0 から 2.0 の乱数の値を$yに代入します。
float $z = rand(1.0, 2.0);
1.0 から 2.0 の乱数の値を$zに代入します。
scale $x $y $z;
3 つの乱数によってポリゴンの球にスケールをかけます。
string $ver[] = `polyListComponentConversion -toVertex $poly[0]`;
ポリゴンの球から頂点を取り出して $ver[] に代入します。
polyListComponentConversionコマンドはポリゴンのオブジェクトから頂点・フェース・エッジ・UVなどを取り出すために使用します。
$ver[] に入る返り値はコンポーネントなので以下の filterExpand コマンドで各頂点に展開する必要があります。
string $verE[] = `filterExpand -selectionMask 31 $ver`;
$ver の中から頂点(31 で表される)を配列に展開して $verE[] に代入します。
for($obj in $verE)
$verE[]から、1 つづつ頂点を取り出して $obj に代入してループの中の処理を行なう。
$x = rand(-0.2, 0.2);
-0.2 から 0.2 の乱数の値を $x に代入します。
$y = rand(-0.2, 0.2);
-0.2 から 0.2 の乱数の値を $y に代入します。
$z = rand(-0.2, 0.2);
-0.2 から 0.2 の乱数の値を $z に代入します。
select -r $obj;
ひとつの頂点 $obj だけをセレクトします。
move -r $x $y $z;
セレクトされている頂点を、その位置から$x, $y, $zだけ移動します。
string $polyS[] = `listRelatives -shapes $poly[0]`;
ポリゴンの球のトランスフォームノードからシェープノード(メッシュ)を得ます。
listRelatives コマンドによってトランスフォームノード($poly[0])の子ノードになっているシェープノードの名前を得て、$polyS に代入しています。
シェープノードの名前はポリゴンにスムースをかけるために必要です。
なぜ、わざわざこのようなコマンドを実行する必要があるかというと、 球の名前が入っている $poly にはトランスフォームノードとインプットノードの名前しか入っていないからです。
例えば、以下の図であれば、トランスフォームノード pSphere1 からシェープノード pSphereShape1 を求めることになります。
(polySphere1 はインプットノードです)
polySmooth -divisions 2 -continuity 0.5 $polyS[0];
ポリゴンメッシュにスムースをかけます。
スムースをかけるにはシェープノードが必要なので、 上の listRelatives コマンドによって得られたシェープノードが入っている $polyS[0] を使っています。
-divisions 2
何回再帰的にスムースをかけるかを決めます。
ここでは 2 回スムースをかけています。 (デフォールトは 1 です)
-continuity 0.5
スムースの度合を表します。
値が大きい程スムースになります。
この値は 0.0 〜 1.0 の範囲で指定します。
(デフォールトは 1.0 です)

練習

Tips (seed)

rand コマンドを使用すると、実行するたびに違う数値がかえってきますが、 常に同じ数値を返すようにしたい場合があります。 そのようなときには、以下のように seed コマンドを使用します。

seed 1;
rand 1 2;
// Result: 1.90019 //
rand 1 2;
// Result: 1.772618 //
seed 1;
rand 1 2;
// Result: 1.90019 //
rand 1 2;
// Result: 1.772618 //

参考

練習課題


Prev | Next
Home | Contents
Mail