我对经典的水波算法略微做了些扩展

效果图

这是效果图注意荷叶边的效果。

经典的水波算法:

//能量的扩散
  t=waterB[a-mWidth];
  b=waterB[a+mWidth];
  r=waterB[a+1];
  l=waterB[a-1];
  waterA[a]=((t+b+l+r)>>1)-waterA[a];
  //能量的衰减
   waterA[a]-=(waterA[a]>>6);

一个非常重要的依据--能量守恒。

在无阻尼前提下,一个时间内的所有水分子的能量之和是不变的

上面的能量的扩散就是按照这个原则实现的,感兴趣的话看一下

http://tech.163.com/05/0624/10/1N0LUJM600091589.html
http://www.chinaitpower.com/A/2001-12-20/8376.html

这里就不再重复了。

waterA,waterB是两个int 数组,用来保存和推演波的能量。

什么样的波会反射?

      简单的来说我打了老婆十下,老婆也打了我十下这样就相当与有十下被反射回来了。

      当一个水分子给左边的水分子的能量被原样返回时便使得水波想右反射了。

     当我们计算waterB到A的变换(也就是上一个时间点和下一个时间点的波的变换)时,如果该点的波的能量被忽略过去时,该点会保留原来的能量,并把它保存到了下一个时间段,然后把自身的能量想周围扩散。

下面是关键部分的代码:

 for(int a=mWidth;a<mArrayLen-mWidth;a++)
 {

//边缘反射
  if(a%mWidth==0)
   continue;

//根据障碍物计算波的反射
  if(this->mBarrier!=NULL&&this->mBarrier[a*mBarrierBytesPerPix]!=0)
   continue;
  int t,b,l,r;
  //能量的扩散
  t=waterB[a-mWidth];
  b=waterB[a+mWidth];
  r=waterB[a+1];
  l=waterB[a-1];
  waterA[a]=((t+b+l+r)>>1)-waterA[a];
  //能量的衰减
  if(m_decayFactor>0)
   waterA[a]-=(waterA[a]>>m_decayFactor);
  
 }
 COLOR_INT *temp=waterA;
 waterA=waterB;
 waterB=temp;
 
 int xoff,yoff;
 for(int u=1;u<mWidth-1;u++)
 {
  for(int v=1;v<mHeight-1;v++)
  { 
   //判断坐标是否在窗口范围内   
   xoff=waterA[u-1+v*mWidth]-waterA[u+1+v*mWidth];
   yoff=waterA[u+(v-1)*mWidth]-waterA[u+1+(v+1)*mWidth];
   if ((v+yoff )< 0 ) {continue;}
   if ((v+yoff )>mHeight) {continue;}
   if ((u+xoff )< 0 ) {continue;}
   if ((u+xoff )>mWidth ) {continue;}
   //计算出偏移象素和原始象素的内存地址偏移量
   int Color;
   int BackIndex=(u+xoff+(v+yoff)*mWidth)*mBarrierBytesPerPix;
   if(this->mBarrier!=NULL&&this->mBarrier[BackIndex]!=0){
    Color=(mBarrier[BackIndex]);
    for(int i=1;i<mBarrierBytesPerPix;i++)
     Color+=mBarrier[BackIndex+i]<<(8*i);    
   }
   else
   {
    Color=(mBackImage[BackIndex]);
    for(int i=1;i<mBackImageBytesPerPix;i++)
     Color+=mBackImage[BackIndex+i]<<(8*i);    
   }
   //result[u+mWidth*v]=RGB(yoff,xoff,0);
   result[u+mWidth*v]=Color;
  }
  
 }

mBackImage:

背景水草图

mBarrier:

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值