水波演示程序:

自己收集整理的
错误在所难免
仅供参考交流
如有错误
请指正!谢谢
用虎克定理来模拟水波效果
ScreenShot

关于水波和火焰的效果的模拟算法有很多
其中有很多都已经被实现也被证明是非常有效的
本文提出的水波模拟程序和其它常见的算法不太一样
这是从虎克定理来近似导出水波波动的物理模型
一般的水波模拟通常从能量的观点出发、而本文则从受力和速度之间的关系入手
引入一种新的水波模型

我们知道
当水面是平静的是时候
也就是说水面各点处于平衡位置时候
水面上的任何点的受力都是平衡的
但是有任何的扰动发生
就会有点偏离平衡位置
受力也就会不平衡
即会产生加速度
由于这些点受力是遵守虎克定理的
如果知道某一刻水面的状态
理论上
我们可以精确的计算出任何时候的水面状态(外干扰为0)

当然在我们的程序里
计算是不需要精确的
否则我们得建立复杂的微分方程......
我们在这里做如下的假设:一)水面上的点是离散的
二)一个点在dt的时间里受力是相同的
三)一个点受力只和周围的8个点有关
有了这样的三个假设
我们就可以建立我们的物理近似模型了

首先
我们来计算一个点的受力和他们周围点的位置的关系
设某个时刻S点的位移为S,速度为Vs

S点的受力 Fs = k * b * [(B1+B2+B3+B4) - 4 * S ] + k * a * [(A1+A2+A3+A4)-4*S]
k为虎克系数
a,b分别是两种距离点上的权系数
(距离不一样
效果当然不一样了

所以在这一刻
S 点的加速度就是 a = Fs * dm (dm是水的质量
)
下个时刻S点的速度就是Vs2 = Vs - a * dt (dt为时间间隔)
下个时刻的惟一为 S2 = S + Vs2 * dt (dt为时间间隔)

一切都准备好了
现在该是我们实现程序的时候了
水面上的点的位移可以由一个数组来保存起来
我们需要两个数组来保存位移
一个保存当前的位移
一个用来计算下一刻的位移(计算的时候要用到当前的位移)
同时还要有一个数组来保存当前的速度
在程序里
我们计算加速度的时候
可以把dt假设成1
这样可以提高速度
同时可以把dm*k当成一个数就可以了
注意的是
如果这些常数取的不好
就得不到你想要的结果
在我的程序里
dm*k=1
b=1
a=3
dt=1
其次我们还要对水波进行衰减
不然你的水波就停不下来了:-)
水波的扩散具体的代码如下:
void RippleSpread()
{
for(int y=1;yfor(int x=1;x{
int a =( 16*pBack[y][x]-
(3*pBack[y-1][x]+
3*pBack[y+1][x]+
3*pBack[y][x-1]+
3*pBack[y][x+1]+
1*pBack[

y-1][x-1]+
1*pBack[y-1][x+1]+
1*pBack[y+1][x+1]+
1*pBack[y+1][x-1])
)/16;
pV[y][x] -= a;//计算下一刻的速度
pV[y][x] -= pV[y][x]>>6;//速度的自动衰减
pFront[y][x] =pBack[y][x] + pV[y][x];//下一刻的位移
pFront[y][x]-= pFront[y][x]>>8;//位移的衰减
}
//交换缓冲区
int (*pTemp)[W]=pFront;
pFront=pBack;
pBack=pTemp;
}
最后
我们要根据水面位移的数据来渲染水波
我们知道水面波动后
是有坡度的
我们真正好可以用坡度扭曲图象来产生水波的效果
做法如下
对水面上的任何一个点(X,Y)
算出offsetX和offsetY
然后把图象中(X+offsetX,Y+offsetY)里的数据拷贝到该位置就可以了
这里给出了渲染的代码:
void RenderRipple()
{
int xoff,yoff,nx,ny;
COLOR cl;
DRAWSTRUCT ds;
DRAWSTRUCT dst;
BeginDraw(&dst,lpDDS_Texture);
BeginDraw(&ds,lpDDS_Back);
for(int y=1;y{
for(int x=1;x{
xoff=pFront[y][x+1]-pFront[y][x-1];
yoff=pFront[y-1][x]-pFront[y+1][x];
nx=x+xoff/10;
ny=y+yoff/10;
if(nx>=W) continue;
if(nx<0) continue;
if(ny>=H) continue;
if(ny<0) continue;
GetColor(dst,nx,ny,&cl);
SetColor(ds,x,y,&cl);
}
}
EndDraw(lpDDS_Texture);
EndDraw(lpDDS_Back);
}
我这里采用的水波许染方法比较简单
大家自己可以通过水面的坡度来计算对应的亮度
这样可以让水波看上去更加有立体感


潘李亮 2002 - 7 - 21日
2003-8-25日更新
Emial : xheartblue@https://www.360docs.net/doc/f58690990.html, QQ:81496744
Homepage : https://www.360docs.net/doc/f58690990.html,/xpertsoft/

相关文档
最新文档