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>> //

0 件のコメント:

コメントを投稿