火焰非均匀冷却的改进模型
根据上述近似模型可对火焰进行一定程度上的仿真,但由于没有引入随机分布火焰往往看上去相当单调规则,而且火焰总呈线性上升,冷却速度也严格地保持统一速率。要消除以上问题,可通过引入随机非均匀因素来解决。一种途径是随机布置各点冷却值使火焰冷却过程非均匀化。但由于火焰的模拟过程是实时进行的,为确保动态模拟过程中能顺畅进行,最好用预先创建的冷却位图(见右图)来代替。一般采用在屏幕上随机撒布几千个亮度不同的点并对其应用平滑处理等方法对冷却位图加以填充。通过冷却图中获取的数值来代替原来固定的冷却衰减值效果要好的多,此时的冷却过程改进为Pixel(x,y)=Pixel(x,y)-Coolingmap(x,y) 这样的衰减结果将使火焰的冷却衰减效果更加真实:
p = lightBuf2+imgWidth*2; pp = coolMap + coolMapWidth*2; p1 = lightBuf1+imgWidth*2; p2 = p1 - imgWidth; p3 = p1 - 1; p4 = p1 + 1; p5 = p1 + imgWidth; for(i=0;i //计算某点及其四邻像素均值 c1=(unsigned char)(((UINT)*p1+(UINT)*p2+(UINT)*p3+(UINT)*p4+(UINT)*p5)/5); c2 = *pp; if(c1>c2) c1 -= c2; *p = c1; pp++,p++,p1++,p2++,p3++,p4++,p5++; //内存指针修正 } | 由于火焰在进行冷却衰减的同时也在进行着火焰的扩散与对流因此必须使这几种效果保持同步,这需要以同对流速度相同的速度向上滚动冷却位图来实现。为减少不必要的操作,滚动是在内存中通过改变冷却位图的垂直偏移量来加以实现:
memcpy(lightBuf1,lightBuf1+imgWidth*3,imgWidth*(imgHeight-3)); | 经过以上几步处理虽有一定程度的改善,但仍存在一些缺陷,比如生存期、火焰上升速度恒定、在整个空间燃烧等。为使仿真效果更加逼真,可通过设置种子点来对上述缺陷加以改进。同样出于处理速度的考虑,最好将种子点也以位图的形式预先设定,在仿真时直接在内存中通过移动指针来完成对种子点的访问,其主要代码大致如下:
int t = RAND_MAX/5; topX = (imgWidth - seedMapWidth)/2; //seedMapWidth种子位图宽度 topY = (imgHeight - seedMapHeight)/2; //seedMapHeight种子位图高度 p = lightBuf1 + (topY+2)*imgWidth + topX; //p, unsigned char型指针 ps = seedMap + seedMapWidth*2; //ps, unsigned char型指针 for(j=0;j<(seedMapHeight-4);j++) { p1 = p; //p1, unsigned char型指针 for(k=0;k if(*ps != 0){ //ps, unsigned char型指针 if(rand() < t) *p1 = 255; } p1++,ps++; //指针修正 } p += imgW查看本文来源idth; //指针修正 } | |