Python の応用1 (岩石)

岩石を作る

これから Python の応用として、岩石を自動生成するスクリプトを作ってみましょう。
最初は簡単なスクリプトから始めて、すこしづつ違うバリエーションのものを作ってみます。
岩石のようなものを Python によって自動生成するためには様々な方法が考えられますが、 ここでは、なるべくシンプルな方法で作ってみます。

岩石を作る方法 1

適当なプリミティブを作って、それをスケール・頂点の移動などで変形して、 岩石らしく見せる方法を試してみましょう。

ここでは以下の方法で作ってみます。

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

Tips

上の説明にでている乱数とは、ある範囲内のでたらめな数値のことです。
Python では random.uniform() 関数を使用して乱数を得ることができます。
random.uniform() コマンドは下の使用例のように、 実行するたびにランダムで、違う数値を返してくれるので、 岩石を作るときのように不規則な形を作ったりする場合によく使用されます。

import random # random モジュールをインポート
random.uniform(1.0, 5.0) # 1.0 から 5.0 までの乱数を返す
# 結果: 3.307047 #
random.uniform(1.0, 5.0) ← 同じコマンドを実行すると違う数値を返す
# 結果: 4.70314 #
random.uniform(1.0, 5.0)
# 結果: 1.529152 #

岩石を作るプログラム 1

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

  1. 以下のプロシージャを makeRock1.py と言う名前でファイルに書き込みます。
    import maya.cmds
    import random
    
    def makeRock1():
        val = random.uniform(0.5, 2.0)
        poly = maya.cmds.polySphere(r=val)
        x = random.uniform(0.8, 1.5)
        y = random.uniform(0.8, 1.5)
        z = random.uniform(0.8, 1.5)
        maya.cmds.scale(x, y, z)
        ver = maya.cmds.polyListComponentConversion(poly[0], toVertex=True)
        verE = maya.cmds.filterExpand(ver, selectionMask=31)
        for obj in verE:
            x = random.uniform(-0.1, 0.1)
            y = random.uniform(-0.1, 0.1)
            z = random.uniform(-0.1, 0.1)
            maya.cmds.select(obj, r=True)
            maya.cmds.move(x, y, z, r=True)
    
  2. スクリプト エディタ の ファイル → スクリプトのロード によって makeRock1.py を読み込んで、テンキーの Enter キーなどで実行します。
  3. スクリプト エディタ で以下の関数を実行します。
    makeRock1()
    [makeRock1() の実行結果]

スクリプトの解説

import maya.cmds
maya.cmds モジュールをインポートします。
import random
random モジュールをインポートします。
uniform() 関数を使うために必要です。
def makeRock1():
makeRock1 という名前の関数を宣言します。
val = random.uniform(0.5, 2.0)
乱数を作る関数 random.uniform(0.5, 2.0) によって 0.5 から 2.0 までのランダムな値を作成し、 val に代入します。
poly = maya.cmds.polySphere(r=val)
半径 val のポリゴンの球体を作ります。
r フラグは球体の半径を指定するものです。 ここでは val が半径になります。
poly には、 poly[0]に球のトランスフォームノード、 poly[1]に球のインプットノードの名前が入ります。 例えば、pSphere1 (トランスフォームノード)、polySphere1 (インプットノード)などです。
x = random.uniform(0.8, 1.5)
0.8 から 1.5 の間の乱数の値を x に代入します。
y = random.uniform(0.8, 1.5)
0.8 から 1.5 の間の乱数の値を y に代入します。
z = random.uniform(0.8, 1.5)
0.8 から 1.5 の間の乱数の値を z に代入します。
maya.cmds.scale(x, y, z)
乱数の値でポリゴンの球にスケールをかけます。
ver = maya.cmds.polyListComponentConversion(poly[0], toVertex=True)
ポリゴンの球から頂点を取り出して ver[]に代入します。
polyListComponentConversion() 関数はポリゴンのオブジェクトから頂点・フェース・エッジ・UVなどを取り出すために使用します。
フラグ toVertex によって頂点が取り出されますが、 これを以下のフラグに変えることによって他のコンポーネントを取り出すことができます。
toEdge
エッジを取り出す
toFace
フェースを取り出す
toUV
UV を取り出す
(ver に入る返り値はコンポーネント(pSphere1.vtx[*] などという形)なので、 以下の filterExpand() 関数で各頂点に展開する必要があります。
verE = maya.cmds.filterExpand(ver, selectionMask=31)
コンポーネント ver を頂点(31 で表される)の配列に展開してverEに代入します。
このとき、例えば 'pSphere1.vtx[*]' が 'pSphere1.vtx[0]', 'pSphere1.vtx[1]', ... という文字列になって、 以下のように verE に代入されます。
verE[0] = 'pSphere1.vtx[0]'
verE[1] = 'pSphere1.vtx[1]'
verE[2] = 'pSphere1.vtx[2]'
.
.
.
selectionMask の数字(31)はコンポーネントの種類によって以下のものが使用できます。
32
エッジ
34
フェース
35
UV
for obj in verE:
verE から、1 つづつ頂点を取り出し obj に代入してループの中の処理を行ないます。
実際には、pSphere1 が球の名前だとして以下のように実行が進みます。
  1. obj = verE[0] が実行されて、 obj に 'pSphere1.vtx[0]' が代入され、 for 文を 1 回実行します。
  2. obj = verE[1]; が実行されて、 obj に 'pSphere1.vtx[1]' が代入され、 for 文を 1 回実行します。
  3. 以下、同様に頂点の個数だけ繰り返します。
以下は for 文の中の関数です。
x = random.uniform(-0.1, 0.1)
-0.1 から 0.1 の乱数の値を x に代入します。
y = random.uniform(-0.1, 0.1)
-0.1 から 0.1 の乱数の値を y に代入します。
z = random.uniform(-0.1, 0.1)
-0.1 から 0.1 の乱数の値を z に代入します。
ここの、-0.1 と 0.1 という数値は球の大きさから形が崩れすぎない程度の適当な値を選んでいます。 でこぼこの形を変えたければ、違う数値にしてもかまいません。
maya.cmds.select(obj, r=True)
obj だけをセレクトします。
maya.cmds.move(x, y, z, r=True)
セレクトされている頂点を、その位置から x, y, z だけ移動します。

練習

まとめ

参考


Prev | Next
Home | Contents
Mail