基于粒子系统的雪景模拟算法研究与实现.docx
《基于粒子系统的雪景模拟算法研究与实现.docx》由会员分享,可在线阅读,更多相关《基于粒子系统的雪景模拟算法研究与实现.docx(13页珍藏版)》请在冰豆网上搜索。
![基于粒子系统的雪景模拟算法研究与实现.docx](https://file1.bdocx.com/fileroot1/2022-11/27/9528b3da-3790-452a-bf43-452ec3bb3ae1/9528b3da-3790-452a-bf43-452ec3bb3ae11.gif)
基于粒子系统的雪景模拟算法研究与实现
基于粒子系统的雪景模拟算法研究与实现
自然景物的模拟一直是计算机图形学中最具挑战性的问题之一。
关于水、云、烟.雨、雪等自然景物的模拟,在计算机游戏、三维动画、影视及广告中有着广泛的应用。
自然景观中雨、雪的模拟,可以大大提高三维场景的逼真度,Reeves提出的粒子系统是模拟雨、雪的一种有效的方法。
文中在分析粒子系统建模方法的基础上,给出了一种雪粒子模型,该模型对雪的物理模型进行了适当简化:
通过控制雪粒子的大小、形状、密度(数量)来实现雪强度的模拟;通过控制雪粒子的运动来模拟风对雪的影响,并对雪粒子的产生域进行了讨论,使其满足视点运动的要求。
实践表明,该粒子系统模型可在复杂的三维场景中实时地模拟降雪现象,仿真效果逼真。
关键词 粒子系统,虚拟场景,雪景模拟,
Simulationofnaturalphenomenahasalwaysbeenoneofthemostchallengingtasksincomputergraphics.Simulatingnaturalphenomena,suchaswater,cloud,smoke,rain,snowandsoon,hasbeenwidelyusedincomputergame,3Danimation,movieproductionandadvertising,etc.Simulationofrainorsnowinnaturalphenomenacangreatlyimprovethefidelityof3DsceneparticlesystempresentedbyReevesisapowerfulwaytosimulatethem.
Inthispaper,presentamodeofsnowbasedonanalyzingparticle
systems.Thismodesimplifiedtheattributesofrealsnow,thismodeusesize,shapeanddensityofsnowsparticletosimulateintensityofsnow,andcontrolmovementofparticletosimulateactionofwind.Atthesametime。
Studythegenerationshapeofsnowparticlesandmakeitsettleforthesituationthattheviewismoved.Theresultsofexperimentationhaveprovedthatthismethodismoreeffectiveintherepresentationofsnowsinvirtualscene.
Keywords:
ParticleSystem,VirtualScene,Snowsimulation
0引言
自然景物的模拟一直是计算机图形学中最具挑战性的问题之一。
关于水、云、烟、雨、雪等自然景物的模拟,在计算机游戏、三维动画、影视及广告中有着广泛的应用。
自然景物中雪的模拟大大提高了三维场景的逼真度,利用Opengl【1-3】开发工具是模拟雪景的有效方法。
目前国内也有一些专家在搞这方面的研究,南京航空航天大学的王静秋在他的硕士论文中也重点阐述了基于粒子系统的动态自然景物模拟的方法,给出了基于粒子系统模拟雪景粒子数据结构以及算法【4】。
浙江大学CAD&CG国家重点实验室的一个以彭群生为主要负责人的研究小组在他们的《973项目进展汇报---虚拟景物的建模与绘制》中也谈到了雪景的模拟问题,他们也将风场的模拟引入了粒子系统中来【5】。
云南师范大学的袁霞和张玉啄对粒子系统的方法及应用作了较为详尽、系统的阐述【6】。
西安电子科技大学计算机学院的徐利明,姜昱明在他们的论文《基于粒子系统与OpenGL的实时雨雪模拟》中在分析粒子系统实现原理的基础上,基于OpenGI提出了一种在大型场景漫游系统中实时模拟雨、雪的方法[7]。
炮兵学院南京分院的张芹,张健,阕电平在他们的论文《提高粒子系统实时性的方法研究》中在剖析影响实时性的因素基础上,提出了提高粒子系统实时性的有效方法[8-9]。
另外,武汉理工大学的王长波教授研究的《飘雪场景的实时模拟》,不仅实现了雪景的模拟,而且利用流体力学的原理模拟风场,进而更加逼真的模拟出了风雪交互的景象,但是他没有将粒子系统用于模拟雪景【10】。
1雨雪粒子系统的基本原理
粒子系统是计算机动画技术的一个重要组成部分。
粒子系统(particlesystem)方法被认为是迄今为止模拟不规则物体最为成功的一种图形生成
算法。
粒子系统方法采用了一套完全不同于以往造型、绘制技术的方法来构造、绘制景物。
这里,景物被定义为由成千上万个不规则的、随机分布的粒子所组成,虽然每个粒子均有一定的生命周期,它们不断地改变形状,不断的地运动,但我们关心的只是景物的总体形态和特征变化,而不是各个粒子本身。
粒子系统的研究始于80年代初期,由ReevesW.T.于1983年首次提出粒子系统模型,并用其模拟了火焰、爆炸等效果。
他还成功的模拟了电影《StarTrekII:
TheWrathofKhan》中的一系列特技镜头;85年ReevesW.T.和Blau发展了粒子系统,他们用“Volumefilling”基本单元去生成随时间改变形状但又基本保持不变的实体,如随风飘动的花草树叶;FournierA.等在研究海浪模型中利用粒子系统方法模拟了浪花;KarlSims研究了粒子的动画和绘制算法,他利用粒子系统并行性的特点,提出了一个并行的粒子绘制系统。
该系统能绘制不同形状、大小、颜色、透明度的粒子;再如大家非常熟悉的三维动画制作的最新软件3DStudioMax就载有“snow”粒子系统来模拟飘舞的雪花。
现有的基于粒子系统的模拟算法,往往是针对某个特定的对象,而没有普遍性的研究。
基于粒子系统的模拟算法是应该有着普遍的共同规律的,总结出它的开发流程和规律是今后研究的重点方向之一。
另外,现有的基于粒子系统的模拟算法,几乎都没有考虑粒子之间的相互作用,粒子与其它物体的碰撞等等。
这也应该是今后的研究方向。
另外,粒子系统与物理运动学的结合目前也不够密切,只有与运动学结合才能使效果更加逼真。
粒子系统方法的基本思想是将许多简单形状的微小粒子作为基本元素聚集起来,形成一个不规则的模糊物体,从而构成一个封闭的系统——粒子系统。
粒子系统并不是一个简单的静态系统,随着时间的推移,系统中已有的粒子不仅不断改变形状,不断运动,而且不断有新的粒子加入,并有旧的粒子消失。
为模拟生长和死亡过程,每个粒子被赋予一定的生命周期,它将经历生长,成长,衰老和死亡的过程。
同时,为使粒子系统所表示的景物具有良好的随机性,与粒子有关的每一个参数均将受到一个随机过程的控制。
粒子系统方法的这一特征,使它充分体现了不规则模糊物体的动态性和随机性,很好地模拟了火、云、水、森林和原野等自然景物。
生成粒子系统某瞬间的画面的基本步骤是:
(1)生成新的粒子并将其加入系统中
(2)赋予每一新粒子以一定的属性
(3)删除那些已经超过其生命周期的粒子
(4)根据粒子的动态属性对粒子进行移动和变换
(5)绘制并显示由有生命的粒子组成的图形
显然,上述每个操作都是过程计算模型,因而它可以与任何描述物体运动和特征的模型结合起来,如粒子的运动、变换可用一个偏微分方程来描述。
对于粒子系统的随机性,可采用一些非常简化的随机过程来控制粒子的形状、特征及运动。
对每一粒子的参数均先确定其变化范围,然后在该范围内随机地确定它的值。
其变化范围则由给定的平均期望值和最大方差来确定,其基本表达式为:
Parameter:
=MeanParameter+Rand()VaLrParameter
其中Parameter代表粒子系统中的任一需随机确定的参数;Rand()为[一1,1]中的均匀随机函数;MeanParameter为该参数的均值;VarParameter为其方差。
2.雨雪模型的建立
2.1产生雪粒子
首先应该明确粒子产生的位置即粒子源的位置,由于考虑到场景的均匀、协调性,本系统设置了九个粒子源。
这九个粒子源均匀分布在屏幕的上方。
每个粒子源产生30个粒子。
其中X分别为:
-100,0,100;Y为500;Z分别为:
-50,-150,-250。
粒子源的分布图见附录中图3-1。
然后,每个粒子都有自己的生命周期,本系统粒子的生命周期为t=100。
接着设置粒子下落的初速度tempp->v=(float)(rand()%200)/100+1
其中rand()为随机函数,tempp为临时粒子变量。
而粒子的水平方向位移和前后方向位移设置为:
tempp->xd=cos(((r%15000)*3.14159)/180)*(p%1000)/9;
tempp->zd=sin(((r%17000)*3.14159)/180)*(q%1100)/8;
其中r,p,q均为随机数(r=(int)(rand());p=(int)(rand());q=(int)(rand());)。
粒子的水平方向速度和加速度初值均为0,粒子的淡化值初始为1,最后粒子的类型初始为运动状态即tempp->type=TRUE。
至此,粒子的初始属性已经设置完毕,雪粒子就由这九个粒子源产生了。
产生雪粒子的函数为:
voidCMySnowView:
:
AddParticles()。
2.2移动雪粒子
产生粒子以后,就要控制粒子的移动了。
首先控制粒子的生命周期,本系统设定粒子每移动一次,粒子生命周期值减1,当粒子生命周期减为小于0时,应改变粒子的状态为淡化状态。
1、如果粒子处于运动状态(tempp->type==TRUE)
那么根据物理运动学的原理,在这段时间内粒子的下落位移为:
0.5*g+v(当t=1时),取重力加速度g=10,则变为:
5+v,因此粒子新的Y轴坐标为:
tempp->y=tempp->y-5-tempp->v;
同样根据物理运动学的原理,粒子水平运动位移为:
xd=0.5*tempp->a+tempp->vx;
其中tempp->a为粒子水平运动加速度,tempp->vx为粒子水平运动初速度。
这里顺便讲一下风的效果的形成方法。
无风时,只要让tempp->a为0就可以实现;而西风时,tempp->a为正值,东风时其为负值。
粒子水平运动位移设置好后,再加上原来粒子初始的水平方向位移tempp->xd,就构成了整个粒子水平方向上的位移增量。
接下来进行粒子前后方向上的位移增量设置。
tempp->z+=tempp->zd/3;
最后,将粒子的淡化系数tempp->alpha减去0.01。
至此粒子处在运动状态下的移动已经完成。
2、如果粒子处于淡化状态
先使粒子的Y轴坐标为0即使粒子处于地面上。
然后只需将粒子的淡化系数减去0.01。
至此一个粒子的移动已经完成,最后将指针指向下一个粒子,继续重复上述步骤,直到最后一个粒子处理完毕。
tempp=tempp->next;
移动雪粒子的函数为:
voidCMySnowView:
:
MoveParticles()
2.3删除雪粒子
当粒子处于某种状态时,粒子就要从系统中删除。
本系统设定当粒子状态为淡化状态而且淡化系数已经减为负数的时候,粒子将从系统中删除。
为了使场景中的飘雪更加真实,而不至于出现雪花过大的现象,系统设定将那些Z轴坐标大于-50的粒子删除,也就是说要删除那些离屏幕过近的粒子。
具体代码如下:
while(tempp)
{
if((tempp->type==FALSE)&&(tempp->alpha<=0)||(tempp->z>=-50))
{
temp1=tempp->prev;
tempp->prev->next=tempp->next;
if(tempp->next)tempp->next->prev=temp1;
free(tempp);
tempp=temp1;
}
tempp=tempp->next;
}
删除雪粒子的函数为:
voidCMySnowView:
:
DeleteParticles()
2.4绘制雪粒子
产生粒子、移动粒子以及删除粒子的函数定义好后,就可以绘制飘雪了。
绘制雪粒子之前要分别调用前面定义好的产生粒子函数,移动粒子函数,删除粒子函数。
AddParticles();
MoveParticles();
DeleteParticles();
绘制雪粒子的函数为:
voidCMySnowView:
:
DrawSnow()
3.雪景模拟系统中纹理贴图的实现
3.1纹理贴图的提出
在OpenGL中,如果要使所模拟的物体更加逼真我们一般采用纹理贴图的方式。
纹理贴图也叫纹理映射(TextureMapping),在三维图形中,纹理映射(TextureMapping)的方法运用得很广,尤其描述具有真实感的物体。
比如绘制一面砖墙,就可以用一幅真实的砖墙图像或照片作为纹理贴到一个矩形上,这样,一面逼真的砖墙就画好了。
如果不用纹理映射的方法,则墙上的每一块砖都必须作为一个独立的多边形来画。
另外,纹理映射能够保证在变换多边形时,多边形上的纹理图案也随之变化。
例如,以透视投影方式观察墙面时,离视点远的砖块的尺寸就会缩小,而离视点较近的就会大些。
此外,纹理映射也常常运用在其他一些领域,如飞行仿真中常把一大片植被的图像映射到一些大多边形上用以表示地面,或用大理石、木材、布匹等自然物质的图像作为纹理映射到多边形上表示相应的物体。
纹理映射有许多种情况。
例如,任意一块纹理可以映射到平面或曲面上,且对光亮的物体进行纹理映射,其表面可以映射出周围环境的景象;纹理还可按不同的方式映射到曲面上,一是可以直接画上去(或称移画印花法),二是可以调整曲面颜色或把纹理颜色与曲面颜色混合;纹理不仅可以是二维的,也可以是一维或其它维的。
本系统的雪花、地面以及背景都是采用纹理贴图的方式进行绘制的。
3.2纹理贴图的方法
一、基本步骤
纹理映射是一个相当复杂的过程,这节只简单地叙述一下最基本的执行纹理映射所需的步骤。
基本步骤如下:
1)定义纹理、2)控制滤波、3)说明映射方式、4)绘制场景,给出顶点的纹理坐标和几何坐标。
注意:
纹理映射只能在RGBA方式下执行,不能运用于颜色表方式。
二、用到的主要函数
(1)voidglTexImage2D(GLenumtarget,GLintlevel,GLintcomponents,
GLsizeiwidth,glsizeiheight,GLintborder,GLenumformat,GLenumtype,constGLvoid*pixels);
定义一个二维纹理映射。
其中参数target是常数GL_TEXTURE_2D。
参数level表示多级分辨率的纹理图像的级数,若只有一种分辨率,则level设为0。
参数components是一个从1到4的整数,指出选择了R、G、B、A中的哪些分量用于调整和混合,1表示选择了R分量,2表示选择了R和A两个分量,3表示选择了R、G、B三个分量,4表示选择了R、G、B、A四个分量。
参数width和height给出了纹理图像的长度和宽度,参数border为纹理边界宽度,它通常为0,width和height必须是2m+2b,这里m是整数,长和宽可以有不同的值,b是border的值。
纹理映射的最大尺寸依赖于OpenGL,但它至少必须是使用64x64(若带边界为66x66),若width和height设置为0,则纹理映射有效地关闭。
参数format和type描述了纹理映射的格式和数据类型。
参数pixels包含了纹理图像数据,这个数据描述了纹理图像本身和它的边界。
(2)voidgltexCoord{1234}{sifd}[v](TYPEcoords);
在绘制纹理映射场景时,不仅要给每个顶点定义几何坐标,而且也要定义纹理坐标。
经过多种变换后,几何坐标决定顶点在屏幕上绘制的位置,而纹理坐标决定纹理图像中的哪一个纹素赋予该顶点。
并且顶点之间的纹理坐标插值与基础篇中所讲的平滑着色插值方法相同。
纹理图像是方形数组,纹理坐标通常可定义成一、二、三或四维形式,称为s,t,r和q坐标,以区别于物体坐标(x,y,z,w)和其他坐标。
一维纹理常用s坐标表示,二维纹理常用(s,t)坐标表示,目前忽略r坐标,q坐标象w一样,一半值为1,主要用于建立齐次坐标。
OpenGL坐标定义的函数是:
voidgltexCoord{1234}{sifd}[v](TYPEcoords);
设置当前纹理坐标,此后调用glVertex*()所产生的顶点都赋予当前的纹理坐标。
对于gltexCoord1*(),s坐标被设置成给定值,t和r设置为0,q设置为1;用gltexCoord2*()可以设置s和t坐标值,r设置为0,q设置为1;对于gltexCoord3*(),q设置为1,其它坐标按给定值设置;用gltexCoord4*()可以给定所有的坐标。
使用适当的后缀(s,i,f或d)和TYPE的相应值(GLshort、GLint、glfloat或GLdouble)来说明坐标的类型。
注意:
整型纹理坐标可以直接应用,而不是象普通坐标那样被映射到[-1,1]之间。
3.3系统的贴图
3.3.1飘雪贴图
雪花的绘制采用纹理贴图的方式。
以绘制一个雪粒子为例,首先要绑定一个要贴图的纹理图案,然后画一个四边形,再把雪粒子的图片的坐标对应的贴在这个四边形上,使得雪粒子在这个四边形的中心。
具体代码如下:
l=size;
glTexCoord2f(0,0);
glVertex3f((tempp->x-l/2),(tempp->y-l/2),tempp->z);
glTexCoord2f(1,0);
glVertex3f((tempp->x+l/2),(tempp->y-l/2),tempp->z);
glTexCoord2f(1,1);
glVertex3f((tempp->x+l/2),(tempp->y+l/2),tempp->z);
glTexCoord2f(0,1);
glVertex3f((tempp->x-l/2),(tempp->y+l/2),tempp->z);
其中,L为四边形的边长。
3.3.2地面绘制
地面的绘制也仍然采用纹理贴图的方法。
首先要绑定地面的纹理图片,之后设置静止摄像机(设置静止摄像机的方法将在视点转换技术中详细介绍)。
贴图时,X方向从-300贴到50,每次加5;Z方向从-50贴到50,每次加5。
Y始终为0,使得图片贴在XOZ平面内,具体代码如下:
glBegin(GL_QUADS);
for(intx=-300;x<50;x+=5)
for(intz=-50;z<50;z+=5)
{
glVertex3i(x,0.0,z);glTexCoord2f(0,0);
glVertex3i(x,0.0,z+5);glTexCoord2f(1,0);
glVertex3i(x+5,0.0,z+5);glTexCoord2f(1,1);
glVertex3i(x+5,0.0,z);glTexCoord2f(0,1);
}
glEnd();
3.3.3背景绘制
背景的绘制与地面的绘制有些类似。
贴图时,X方向从-300到100,每次加5;Y方向从0到40,每次加40,也就是说,在Y方向上只循环贴一次,因为要保证背景图只有一层。
Z方向上始终为-50,使得图片贴在竖直背景平面内。
具体代码如下:
glBegin(GL_QUADS);
for(intx1=-300;x1<100;x1+=20)
for(inty=0;y<40;y+=40)
{
glVertex3i(x1,y,-50.0);glTexCoord2f(0,0);
glVertex3i(x1+20.0,y,-50.0);glTexCoord2f(0,1);
glVertex3i(x1+20.0,y+30.0,-50.0);glTexCoord2f(1,1);
glVertex3i(x1,y+30.0,-50.0);glTexCoord2f(1,0);
}
glEnd();
至此,系统地贴图已经完成。
本系统所贴图片均为BMP图片,由CLoadBMP类负责读入。
4.雪景模拟系统中纹理切换的实现
4.1纹理切换的提出
当飘雪、地面以及背景都绘制好以后,系统已经有了它的雏形,接下来要考虑的问题就是怎样使系统功能更加完善,界面更加美观、友好。
由此想到,飘雪可以有很多种不同的形状,地面也可以有各种不同的类型,可不可以用一种方法来实现各种不同纹理之间的转换呢?
答案是肯定的。
设想通过菜单以及模态对话框,让用户根据自己的喜好来选择想要的纹理图案,然后由处理菜单消息的函数实现纹理参数的更新。
4.2纹理切换的基本方法
要想实现纹理切换,必须进行以下步骤:
1、将所需的纹理图片以链表的形式连在一起;
2、读入纹理文件;
3、添加菜单以及模态对话框以便用户自主选择纹理图案;
4、在处理菜单消息的函数中对纹理参数进行更新;
5、在进行纹理贴图时,绑定用户选择的纹理图案。
要说明一点的是供选择的纹理图片应该与场景配合、协调。
纹理切换的目的就是要使场景更加丰富多彩,富于变化,从而增加系统的观赏性和趣味性。
4.3系统中纹理切换的实现
4.3.1纹理图片的读入
纹理图片的读入主要是通过CLoadBMP类,它是专门负责BMP图片文件的读入的。
(1)设置图片枚举类型
为了使纹理文件的读入更加方便,可以按照文件的名字设置一些枚举类型的数据,这样可以避免在以后处理过程中把纹理文件弄混。
本系统中要读入八个纹理图片,它们的枚举类型的设置在CLoadBMP类头文件中设定具体如下:
enumTexture_Objects{snowstorm=0,circle,p1,spark,sand0,snow,water2,tree};
也就是用“snowstorm”代表0,“circle”代表1,“p1”代表2,等等依次类推。
(2)纹理图片串连读入
将要读入的纹理图片以链表的形式串连在一起,通过CLoadBMP:
:
GLLoadTextures(GLuint*ptList)函数读入。
具体操作如下:
glGenTextures(8,ptList);
glBindTexture(GL_TEXTURE_2D,ptList[snowstorm]);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
g