|
特效天地——水波(2) a、b为待定系数,X0’为0点下一时刻的振幅 X0、X1、X2、X3、X4为当前时刻的振幅 下面我们来求解a和b。 假设水的阻尼为0。在这种理想条件下,水的总势能将保持不变。也就是说在任何时刻,所有点的振幅的和保持不变。那么可以得到下面这个公式: X0’+X1’+...+Xn’ = X0+X1+...+Xn 将每一个点都象公式1那样计算,然后代入上式,得到: (4a+b)X0+(4a+b)X1+...(4a+b)Xn = X0+X1+...+Xn =>4a+b=1 找出一个最简解:a = 1/2、b = -1 因为1/2可以用移位运算符“>>”来进行,不用进行乘除法,所以,这组解是最适用的而且是最快的。那么最后得到的公式就是: X0’=(X1+X2+X3+X4)/ 2- X0 好了,有了上面这个近似公式,你就可以推广到下面这个一般结论:已知某一时刻水面上任意一点的波幅,那么,在下一时刻,任意一点的波幅就等于与该点紧邻的前、后、左、右四点的波幅的和除以2、再减去该点的波幅。 应该注意到,水在实际中是存在阻尼的,否则,用上面这个公式,一旦你在水中增加一个波源,水面将永不停止的震荡下去。所以,还需要对波幅数据进行衰减处理,让每一个点在经过一次计算后,波幅都比理想值按一定的比例降低。这个衰减率经过测试,用1/32比较合适,也就是1/2^5。可以通过移位运算很快的获得。 到这里,水波特效制作中最艰难的部分已经度过了,下面是源程序中计算波幅数据的代码。 //******************************************************* //计算波能数据缓冲区 //******************************************************* void RippleSpread() { for (int i=BACKWIDTH; i<BACKWIDTH*BACKHEIGHT-BACKWIDTH; i++) { //波能扩散 buf2[i] = ((buf1[i-1]+ buf1[i+1]+ buf1[i-BACKWIDTH]+ buf1[i+BACKWIDTH]) >>1)
|