水波演示程序:

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;y<H-1;y++)
for(int x=1;x<W-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<H-1;y++)
{
for(int x=1;x<W-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);
}

用虎克定理来近似模拟水波波动效果相关推荐

  1. canvas三角函数模拟水波效果

    原文:canvas三角函数模拟水波效果 最近项目中,ui设计了个水波效果的背景动画,然而并没有gif或svg动画,开始试着用css实现了一下,动画效果并不是很好,网上查了下基本都是用贝赛尔曲线实现,想 ...

  2. 3.4.3 Electric Fence电网 USACO(毕克定理) USACO

    题目描述 在这道题目中,"格点"指的是整点(整数坐标点). 为了管理他的牛们,FJ用几条通着电的铁丝建造了一个三角形的围栏,从原点(0,0)到整点(n,m),再到x正半轴上的点(p ...

  3. 【虎克对战平台】夏天到了!虎克来了!V2.3版本都来下载啊!

    服务端跟客户端直接打包 大家下载 NetHookClient2.3.rar (1,526 KB) 客户端 NetHookServer2.3.rar (521 KB)  服务端 feiq2.4.rar ...

  4. leetcode:365. 水壶问题【肥鼠定理,栈模拟dfs】

    分析:数学 显然最后的z是a和b的线性组合 也就是ax + by = z也就是说z是(a,b)的倍数 那就直接用gcd就好了 加个特判 ac code class Solution:def canMe ...

  5. android 说话水波动画,Android实用View——水波动画效果多种实现方式详解

    原标题:Android实用View--水波动画效果多种实现方式详解 这次给大家带来的是一篇关于自定义View实现水波动画效果的文章,其实在去年项目中使用过类似的动画,当时就自定义View也实现了预期的 ...

  6. xpath技术解析xml以及案例模拟用户登录效果

    问题:当使用dom4j查询比较深的层次结构的节点(标签,属性,文本),比较麻烦!!! xpath就在此情况下产生了--主要是用于快速获取所需的[节点对象]. 在dom4j中如何使用xPath技术 1) ...

  7. JS模拟模式窗口效果

    <html> <head>     <meta http-equiv="Content-Type" content="text/html; ...

  8. CSS模拟实现色阶效果

    CSS模拟实现色阶效果,对各种版本的浏览器兼容性考虑的挺周全,在兼容性方面出色,这个只是模拟色阶的效果,显示出不同的色块的深浅颜色,并标识出来英文的颜色名称,其实技术方面不太难,只是有些麻烦,非常感谢 ...

  9. Unity中使用模板测试模拟Mask组件效果

    本文分享Unity中使用模板测试模拟Mask组件效果 在上一篇文章中, 我们分享了模板测试的基础知识, 在今天的分享中, 我们会尝试使用模板测试来模拟遮罩效果. Unity中使用模板测试模拟Mask组 ...

最新文章

  1. linux C 学习
  2. 《啊哈!算法》笔记_Day02
  3. redis hash
  4. iOS的主要框架介绍
  5. 网关gateway解决跨域问题
  6. python常用内置方法_Python3 常用的几个内置方法
  7. 互联网和大数据是什么意思_互联网与大数据的区别是什么意思
  8. C++---map/multimap用法介绍
  9. Linux之lastb命令
  10. 如何增加虚拟机ubuntu的硬盘
  11. 静默文件安装安装WebLogic
  12. Ubuntu下设置Pycharm/unity的桌面快捷方式
  13. Java注解@PostConstruct使用及相关原理分析
  14. Django笔记09:一招解决使用regroup模板标签出现的重复分组问题
  15. Table is marked as crashed and should be repaire 解决方法
  16. 渗透测试-SQL注入之宽字节注入
  17. 一路(16)有你,一起(17)前行
  18. 常用类库-java.lang.String
  19. 随机,摇号、彩票,生成随机数或是随机字符串(万能的evaluate) 。如何找到随机中的规律
  20. PDO连接数据库及DSN详解

热门文章

  1. 使用progressbar显示进度条
  2. Chrome导出书签瘦身,去除ADD_DATE和ICON
  3. NBUT1457 Sona 莫队算法
  4. uniapp做直播+可拖动弹幕
  5. Android 编译IJKPlayer源码
  6. gitflow使用指南
  7. detectron2系列:安装
  8. MongoDB基本介绍及一些用法
  9. mysql修改100条数据_sql 修改前100条数据库
  10. Android高效开发(一)—合理使用图片资源