コンストレイン

コンストレインとは

コンストレインとは、リジッドボディの運動を制限するものです。
これによって、振り子・蝶番(ちょうつがい)など、 空間中の点や他のリジッドボディに、動きを拘束されたアニメーションを作成することができます。
オブジェクトにコンストレインを設定すると、 そのオブジェクトは自動的にリジッドボディになります。

コンストレインは pymel.core.constrain() によって作られます。

コンストレインの種類

各コンストレンは作成した後、 オブジェクトやコンストレインを移動すると コンストレンの長さや位置を変化させることができます。

ネイル(Nail) コンストレイン
1 つのアクティブリジッドボディーから作られるコンストレインです。
一方を空間中の点に固定された、棒によってつながれたような動きを表現できます。
ピン(Pin) コンストレイン
2 つのリジッドボディーから作られるコンストレインです。
2 つのリジッドボディの間を、ピンでとめたようになります。
ヒンジ(Hinge) コンストレイン
1 つまたは 2 つのリジッドボディーから作られるコンストレインです。
空間の 1 点、または他のリジッドボディにとめられた、 蝶番(ちょうつがい)のような動きを作ることができます。
壁につけたドアや、窓などを作ることができます。
バリア(Barrier) コンストレイン
1 つのリジッドボディーから作られるコンストレインです。
バリア(Barrier) コンストレインは大きなプレーンがオブジェクトのバリアとなって、 それ以上オブジェクトが進めなくなります。
スプリング(Spring) コンストレイン
1 つまたは 2 つのリジッドボディーから作られるコンストレインです。
オブジェクトが、バネにつながれたような状態になります。

constrain コマンドのフラグ

nail=True
1 つのリジッドボディーから ネイル(Nail) コンストレインを作成します。
pinConstraint=True
2 つのリジッドボディーから ピン(Pin) コンストレインを作成します。
hinge=True
1 つまたは 2 つのリジッドボディーから ヒンジ(Hinge) コンストレインを作成します。
directionalHinge=True
2 つのリジッドボディーから一方向の ヒンジ(Hinge) コンストレインを作成します。
barrier=True
1 つのリジッドボディーから バリア(Barrier) コンストレインを作成します。
spring=True
1 つまたは 2 つのリジッドボディーから スプリング(Spring) コンストレインを作成します。
stiffness=float
スプリングの固さの定数を設定します。デフォルト値は 5.0 です。
damping=float
ダンピング定数を設定します。
値を大きくすると、動きに対して抵抗力が大きくなります。 負の値にすると、動きを増すような力が働きます。
デフォルト値は 0.1、 範囲は -1000.0 〜 1000.0 です。
restLength=float
休止の長さを設定します。デフォルト値: 1.0 です。
position=(float, float, float)
コンストレインの位置を設定します。
デフォルト値は、 1 つのリジッドボディから作られるコンストレインでは、オブジェクトの重心、 2 つのリジッドボディから作られるコンストレインでは、リジッドボディの中間点になります。
orientation=(float, float, float)
コンストレインの向きを設定します。
ヒンジ(Hinge) および バリア(Barrier) のみについて有効です。 デフォルト値は (0.0, 0.0, 0.0) です。
interpenetrate=boolean
リジッドボディーが貫通するかどうかを設定します。
True で貫通、False で貫通しません。

鎖を作る

ここでは、 ピン コンストレインを使用して鎖を作ってみましょう。
コンストレインを使用して鎖を作ると、物理的には正確な動きにはなりません。 その代わり、リジッドボディのコリジョンだけを使用した場合に比べて、計算が軽くなるし、 リジッドボディ同士が貫入するというトラブルを避けることができます。

作り方

  1. 鎖の輪を作ります。
    輪はプリミティブのトーラスでも、独自のオブジェクトでもかまいません。
    [1 つ目の鎖の輪]
  2. 次の輪を前の輪と重ならないように、適当に回転・移動させて作ります。
    [2 つの鎖の輪]
  3. 2 つ輪の間を ピン コンストレインでとめます。
    [鎖の輪と輪をつなぐ ピン コンンストレイン]
  4. 2, 3 を繰り返します。

constrain コマンドの使用例

上の作り方を参考にして、以下のように鎖を作るスクリプトを作ってみましょう。

  1. 以下の MEL スクリプトをPyMELスクリプトに書き換えて makeChain1.py という名前で作ります。
    global proc makeChain1()
    {
    	int $i;
    	string $tname[];
    	string $ptname;
    
    	string $gname[] = `gravity`;
    	for($i = 1; $i <= 10; $i++)
    	{
    		$tname = `torus -hr 0.2`;
    		scale 2 3 2;
    		rotate 0 ($i % 2 * 90) 90;
    		move ($i * 4) 0 0;
    		if($i == 1)
    		{
    			constrain -nail -p 0 5 0 $tname[0];
    		}
    		else
    		{
    			constrain -pin $ptname $tname[0];
    		}
    		connectDynamic -f $gname[0] $tname[0];
    		$ptname = $tname[0];
    	}
    }
    
  2. 以下の Python スクリプトを makeChain1.py という名前で作ります。
     
    import pymel.core
    
    def makeChain1():
        gname = pymel.core.gravity()
        for i in range(1,11):
            tname = pymel.core.torus(hr=0.2)
            pymel.core.scale((2, 3, 2))
            pymel.core.rotate((0, (i % 2 * 90), 90))
            pymel.core.move(((i * 4), 0, 0))
            if i == 1:
                pymel.core.constrain(tname[0], nail=True, p=(0, 5, 0))
            else:
                pymel.core.constrain(ptname, tname[0], pin=True)
            pymel.core.connectDynamic(tname[0], f=gname)
            ptname = tname[0]
    
  3. スクリプト エディタファイル → ソース スクリプト によって makeChain1.py を読み込みます。
  4. スクリプト エディタ のインプット ウインドウから makeChain1() と打ち込んで実行します。
    [makeChain1() の実行図]
  5. プレイバックしてアニメーションを実行します。
    [makeChain1() のアニメーション実行図]

MEL スクリプトの解説

global proc makeChain1()
makeChain1() というプロシージャの宣言です。
int $i;
for ループ用の変数です。
string $tname[];
鎖の輪になる、トーラスの名前を入れておく配列変数です。
string $ptname;
次の鎖の輪と ピン コンストレインでつなぐために、 一時的にトーラスのトランスフォームノードの名前を入れておく変数です。
string $gname[] = `gravity`;
重力 フィールドを作って名前を $gname に代入します。
for($i = 1; $i <= 10; $i++)
$i を 1 から 10 まで、 10 回ループさせて鎖の輪を 10 個作ります。
$tname = `torus -hr 0.2`;
NURBS のトーラスを作成します。
輪の半径は、-hr フラグによってトーラスの半径の 0.2 倍で作り、 名前を $tname に代入します。
トーラスの半径は、デフォールトで 1.0 なので、輪の半径は 0.2 になります。
torus コマンドの返り値は、 トランスフォームノード名とインプットノード名の 2 つです。 $tname[0] にトランスフォームノード、 $tname[1] にインプットノードの名前が入ります。
scale 2 3 2;
トーラスに適当にスケールをかけておきます。
同時に、輪の半径もスケールされることに注意してください。
rotate 0 ($i % 2 * 90) 90;
トーラスを、1 つおきに Y 軸方向に 90 度回転させます。
輪が X 軸方向に並ぶように、 Z 軸にも 90 度回転させます。
move ($i * 4) 0 0;
となりの輪が重ならない程度に X 軸方向に移動させます。
if($i == 1)
  constrain -nail -p 0 5 0 $tname[0];
1 個目の輪だけは、 ネイル コンストレイン(-nail)を使って 0 5 0 の位置にとめておきます。
else
  constrain -pin $ptname $tname[0];
2 個目以降の輪($tname)は、 1 個前に作られた輪($ptname)と ピン コンストレイン(-pin)でとめてゆきます。
costrainコマンドを使用することによって、 2 つのトーラス $tname$ptname は、 自動的にリジッドボディになります。
connectDynamic -f $gname[0] $tname[0];
輪に 重力 フィールド($gname)を作用させます。
$ptname = $tname[0];
次の輪とコンストレインするために、 現在の輪のトランスフォームノードの名前 $tname[0]$ptname に代入しておきます。

Tips(torus)

トーラスにおける全体の半径と、輪の半径との関係は、以下のようになっています。

NURBS
r フラグで表される、 全体の半径に hr フラグで表される数値を乗算した値が、輪の半径になります。
(例)
全体の半径が 4 、輪の半径が 2 ( = 4 * 0.5) の NURBS トーラス
pymel.core.torus(r=4, hr=0.5)
ポリゴン
r フラグの値が全体の半径、 sr フラグの値が輪の半径になります。
(例)
全体の半径が 4 、輪の半径が 2 の ポリゴントーラス
ppymel.core.polyTorus(r=4, sr=2)

Tips(ベイク)

鎖の個数が多くなった場合には、 ベイク処理をしてアニメーションをキーフレームに変換しておくと、 アニメーションの表示が軽くなります。
GUI のメニューでは 編集 → キー → ベイク シミュレーション □ 、 MEL では bakeResults コマンドを使用します。
以下のコマンドは、nurbsTorus1 〜 nurbsTorus10 に対して 1 フレームから 300 フレームまで アトリビュートの tx, ty, tz, rx, ry, rz をベイク処理する関数です。
pymel.core.bakeResults(nurbsTorus1, nurbsTorus2, nurbsTorus3, nurbsTorus4, nurbsTorus5, nurbsTorus6, nurbsTorus7, nurbsTorus8, nurbsTorus9, nurbsTorus10, simulation=True, t="1:300", sampleBy=1, at=("tx", "ty", "tz", "rx", "ry", "rz"))
ダイナミクスのベイク処理をする場合には、上のように simulation=True が必要です。

練習

参考


Prev | Next
Home | Contents
Mail