在實現粒子系統時,但願粒子能均勻分佈在某個範圍內,很容易想到C++標準的隨機數發生器(實際是產生的是僞隨機數,通常使用所謂的線型同餘法),但隨機數的「均勻分佈」須要無限多個樣本,才能表現出均勻分佈的特徵,在一段短的時間內,常常產生一些不均勻。(若是是均勻的,那麼買彩票就能根據之前出現的號碼推斷之後出現的號碼。)
若是用隨機數生成平面內的粒子座標,將會獲得不太均勻的分佈,這裏通過一番思考,想出來這個辦法:
1.若是須要的是一維空間的均勻分佈的位置,那麼但願是每2次產生的數字分別屬於2個象限,在一個象限內,數字某個1/2象限,在1/2象限裏,又輪流出如今1/4象限內,依此類推。
2.若是須要的是二維空間的均勻分佈的位置,那麼但願是每4次產生的數字分別屬於4個象限,在一個象限內,獲得的數字輪流屬因而此象限的某個1/4,依此類推。
在n維空間內,空間能夠逐級分紅2^n個象限,
很容易想到,在一維空間裏,用二進制數字來表示位置,若是是4位二進制數字,能夠表示32個數字,咱們能夠把空間分割成32份,數字是這樣變化的:
0000
0001
0010
0011
0100
0101
0110
0111
...
在最低位,數字在較小範圍內是均勻分佈的,第2位在4個數字的空間內均勻分佈,第3位在8個數字內是均勻分佈。。。
若是把生成的數字限制在0~15之間,那麼這樣連續的數字,每一個都會出現一次,是絕對均勻分佈的。但在一段時間內,數字分佈是不均勻的。那麼均勻分佈是什麼樣的呢,應該這樣,每次產生一個數字,數字落在左右兩邊的次數最多相差爲1,也就是說,數字輪流出如今左右兩邊,若是用最低位表示左右,那麼很顯然能知足要求。
若是咱們用數字直接表示位置,0~0111在左邊,1000~1111在右邊,既最高位決定左右,這樣問題解決了,把一個逐漸增大的數字(0~15)的各位翻轉,最高位變成最低位,次高位變成第2位。。。 那麼這個數字能夠均勻出如今左右,那麼是否在任意範圍內均勻呢?
咱們把結果的範圍0~15分紅任意多份,能夠看到,當產生了N個數字(按順序取0~255,而後翻轉)時,數字出如今任何兩個部分的的次數相差不超過1。
html
對於4位二進制數,輸入0~15,能夠獲得這樣的結果:
0
8
4
12
2
10
6
14
1
9
5
13
3
11
7
15
這種方法產生的數字能夠用在粒子系統發生器中,或許也能夠用在其餘須要均勻分佈資源的地方。
若是須要獲得二維空間內的隨機位置,能夠用除法和求餘的方法得到水平和垂直座標。
剛纔提到粒子系統,在粒子系統中,有時候須要在球面上產生均勻分佈的粒子,能夠用到上面的方法,可是還不夠,下次再把方法寫下來。
附:線型同餘法示例代碼:
int f()
{ static int r;
r = ( 25173*r+13849 ) % 65536;
return r;
}spa