2012年6月28日木曜日

ランダム ストリーム

再現性のある乱数処理の方法

まずは例、

//seed宣言
seed 2;
rand 0 5;
// Result: 2.064494 //
rand 0 5;
// Result: 1.76712 //
rand 0 5;
// Result: 2.612228 //
rand 0 5;
// Result: 0.615584 // 
//seed宣言し直し
seed 2;
rand 0 5;
// Result: 2.064494 //
rand 0 5;
// Result: 1.76712 //
rand 0 5;
// Result: 2.612228 //
rand 0 5;
// Result: 0.615584 // 


rand関数はデフォルトではメインストリームが使われている為、seed値を設定しなおせば、ストリーム配列の初めからrand値を出しなおす。よって、rand結果は再現性のあるものである。
また配列はrand関数が実行される度に1つ進むと解釈してよさそう。。
では、たとえばオブジェクト「a」、オブジェクト「b」に毎フレーム同じrand結果を出させたい場合。
このままだと配列はrand 実行毎に進んでいくので、


//seed宣言
seed 2;

//frame1
setAttr a.ty `rand 0 5`;
// Result: 2.064494 //
setAttr b.ty `rand 0 5`;
// Result: 1.76712 // 

 //frame2
setAttr a.ty `rand 0 5`;
// Result: 2.612228 //
setAttr b.ty `rand 0 5`;
// Result: 0.615584 //


となり、1フレーム目では「a」に配列1、「b」に配列2、が返され同じ結果にはならない。
そこで、任意のstringにてオブジェクト個々に独自のランドストリームを持たせる事で、結果を同調させます。


//seed宣言
seed st_a 2;
seed st_b 2;

//frame1
setAttr a.ty `rand st_a 0 5`;
// Result: 2.064494 //
setAttr b.ty `rand st_b 0 5`;
// Result: 2.064494 // 

//frame2
setAttr a.ty `rand st_a 0 5`;
// Result: 1.76712 //
setAttr b.ty `rand st_b 0 5`;
// Result: 1.76712 // 

//frame3
setAttr a.ty `rand st_a 0 5`;
// Result: 2.612228 //
setAttr b.ty `rand st_b 0 5`;
// Result: 2.612228 // 

//frame4 
setAttr a.ty `rand st_a 0 5`;
// Result: 0.615584 //
setAttr b.ty `rand st_b 0 5`;
// Result: 0.615584 // 
 

毎フレーム同じ結果になりました。
ストリームはrand実行毎に進むので、「b」が1コマ遅れでついていくなんて事も出来ます。


//seed宣言
seed st_a 2;
seed st_b 2;

//frame1
setAttr a.ty `rand st_a 0 5`;

// Result: 2.064494 //
//frame2
setAttr a.ty `rand st_a 0 5`;
// Result: 1.76712 //
setAttr b.ty `rand st_b 0 5`;
// Result: 2.064494 // 

//frame3
setAttr a.ty `rand st_a 0 5`;
// Result: 2.612228 //
setAttr b.ty `rand st_b 0 5`;
// Result: 1.76712 // 

//frame4 

setAttr a.ty `rand st_a 0 5`;
// Result: 0.615584 //
setAttr b.ty `rand st_b 0 5`;
// Result: 2.612228 //


エクスプレッションの場合、seedの宣言は1フレームに一度だけ、
パーパーティクルエクスプレッションの場合はcreationにて行なう。


以下、perParticleでの例 (書籍 テクニカルアーティストスタートキット Chapter6 .p266)
同じ数のパーティクル数ならば、完全に同調した動きをします。

particleShape1
creation :
seed pShape1 2;
runtime before dynamics :
particleShape1.velocity = `rand pShape1 <<-1,0,-1>><<1,0,1>>`;

particleShape2
creation :
seed pShape2 2;
runtime before dynamics :
particleShape2.velocity = `rand pShape2 <<-1,0,-1>><<1,0,1>>`;

関連コマンド

randstate:ストリームの状態を調べる。

例)
randstate st_a;
// Result: <<63847, 14317, 25624>> //

2012年6月26日火曜日

luminance depth

レンダーレイヤーを使用したluminance depth の出し方。

デプス出力したいオブジェクトを新規レンダーレイヤーに登録する。
レイヤーを右クリックでアトリビュートを出す。
アトリビュートエディタのプリセットからluminance depthを選択。

出来たset rengeユーティリティでカメラ深度を設定し、十分なビット数でレンダリング!

2012年6月19日火曜日

イメージプレーンの誤レンダリング防止

レンダリングが遅いと思ったら、いらないイメージプレーンを消し忘れてた、という凡ミスをなくすためのMEL

string $list[] = `lsType imagePlane`;
for ($node in $list)
    if ($node != "<done>"){
    setAttr ($node+".displayMode") 0;
}

で全てのイメージプレーンをNONEに出来ます。
これをpre render mel に入れればいいのだけど、長いのでプロシージャにして呼び出します。

global proc WB_IPhyde()
{
    string $list[] = `lsType imagePlane`;
    for ($node in $list)
        if ($node != "<done>"){
            setAttr ($node+".displayMode") 0;
        }
}

これをWB_IPhyde.melとして保存すれば、レンダーセッティングのpre render mel にWB_IPhydeと入れるだけで、レンダリング前に全てのイメージプレーンをNONEにしてくれます。

ただ、このままではMAYA GUIからのRender Current Frameの時も同様にNONEに設定されてしまいます。それでは困る場合の方が多いので、BatchRenderの時のみpre render melが適用されるように「about -b」を使ってif文を足します。

global proc WB_IPhyde()
{
    if(`about -b`==1){
        string $list[] = `lsType imagePlane`;
        for ($node in $list)
            if ($node != "<done>"){
                setAttr ($node+".displayMode") 0;
            }
    }
}

for in

変数の配列の数だけループできる便利なfor文!

[例]選択したオブジェクトのx値を0に

$sel = `ls -sl`;
for($node in $sel){
    setAttr ($node+".tx") 0;
}