在实现粒子系统时,但愿粒子能均匀分布在某个范围内,很容易想到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