粒子系统原理.docx_第1页
粒子系统原理.docx_第2页
粒子系统原理.docx_第3页
粒子系统原理.docx_第4页
粒子系统原理.docx_第5页
已阅读5页,还剩18页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

粒子系统原理粒子系统几乎是每个引擎中比不可少的部分,它主要用来解决由大量按一定规则运动(变化)的微小物质组成的大物质,在计算机上的生成与显示的问题。经常使用粒子系统模拟的现象有火、爆炸、烟、 水流、火花、落叶、云、雾、雪、尘、流星尾迹或者象发光轨迹这样的抽象视觉 效果等等。如图8-1,8-2他们都是由粒子系统来完成的。图8-1 SimplePhysicsParticles1.0中的截图图8-2 由粒子系统完成的爆炸等效果通过上面的两幅图我们可以看出,其实粒子系统是一种特效发生器,它可以制造大量的小粒子来达到某种特殊的效果,比如烟雾、火焰或者爆炸。好的粒子效果甚至比渲染好的动画都出色,正因为如此,当前几乎所有的游戏中都使用了粒子系统。为了制造真实的粒子效果,粒子发生器必须在不影响帧率的情况下控制成千上万的粒子运动。简单的粒子系统只允许设置粒子的一些属性,比如生存时间、重力或者颜色;复杂的粒子系统允许为每个粒子的运动函数编写代码。一些粒子系统也包含了光线生成器来创建光线或者轨迹。粒子系统基本原理粒子系统是采用大量的、具有一定生命和属性的微小粒子图元作为基本元素来描述不规则的模糊物体。在粒子系统中,每一个粒子图元均具有:形状、大小、颜色、透明度、运动速度和运动方向、生命周期等属性。而一个粒子究竟有什么样的属性,主要取决于粒子系统用来模拟什么。粒子系统是动态变化的,粒子系统的所有属性都是时间t的函数,随着时间的推移,系统中不断有新粒子的加入,旧的粒子死亡,系统中“存活”的粒子其位置及生命值亦随时间变化而变化。随着虚拟世界时间的流逝,每个粒子都要在虚拟世界经历“产生”、“活动”和“消亡”三个阶段。一般而言,粒子系统的绘制基本可按照以下步骤进行。产生新的粒子加入系统中;赋予每个粒子一定的属性;删除超过生命值上限的粒子;根据粒子属性的动态变化对粒子进行移动和变换;绘制并显示由有生命的粒子组成的图形。其中第、步循环形成了物体的动态变化过程。粒子系统的组成通过前面的学习,我们知道了粒子系统中每一颗粒子他都具有自己的各种属性,因此这每一颗粒子就是一个粒子对象,所以我们的例子系统首先需要一个代表粒子的类Particle。由于我们每一种特效都需要很多粒子来实现,这些粒子的运动方式以及发射的频率都是我们能够控制的,所以我们还需要一个用于控制粒子特效的类ParticleSystem。综上所诉,粒子系统将由粒子(Particle)和发射器(ParticleSystem)组成。粒子(Particle)这里我们的粒子类Particle主要就用于表示粒子特效中的每一颗粒子,他将包括每一颗粒子的各种属性,如代码清单8-1是我们用于表示粒子对象的类Particle的实现。代码清单8-1:Particleview plaincopy to clipboardprint?1. /粒子类 2. publicclassParticle 3. /位置 4. YFSPointpos=YFSPoint.makeZero(); 5. /开始位置 6. YFSPointstartPos=YFSPoint.makeZero(); 7. /颜色 8. YFSColor4Fcolor=newYFSColor4F(); 9. /辅助颜色变化 10. YFSColor4FdeltaColor=newYFSColor4F(); 11. /尺寸和辅助尺寸变化 12. floatsize; 13. floatdeltaSize; 14. /自转速度,辅助自转速度 15. floatrotation; 16. floatdeltaRotation; 17. /生命周期 18. floattimeToLive; 19. /方向 20. YFSPointdirection=YFSPoint.makeZero(); 21. /径向加速度,逃离发射原点的速度 22. floatradialAccel; 23. /切线加速度,围绕发射原点旋转速度 24. floattangentialAccel; 25. /弧度. 26. floatradian; 27. floatradianPerSecond; 28. /半径. 29. floatradius; 30. floatdeltaRadius; 31. /粒子类 public class Particle /位置 YFSPoint pos = YFSPoint.makeZero(); /开始位置 YFSPoint startPos = YFSPoint.makeZero(); /颜色 YFSColor4F color = new YFSColor4F(); /辅助颜色变化 YFSColor4F deltaColor = new YFSColor4F(); /尺寸和辅助尺寸变化 float size; float deltaSize; /自转速度,辅助自转速度 float rotation; float deltaRotation; /生命周期 float timeToLive; /方向 YFSPoint direction = YFSPoint.makeZero(); /径向加速度,逃离发射原点的速度 float radialAccel; /切线加速度,围绕发射原点旋转速度 float tangentialAccel; /弧度. float radian; float radianPerSecond; /半径. float radius; float deltaRadius; 从代码清单8-1我们可以看出,这些成员变量实际上都是每一颗粒子所共同拥有的一些通用的属性,其中我们给每一个变量都加入了注解,这里所要说明的就是,粒子特效都是需要运动的,所以大多数数据需要一个初始值,然后还需要指定一个该值的变化范围,比如上面的radius表示粒子的半径,而deltaRadius则表示该半径可以在一个什么样的范围之内变化。timeToLive则表示该粒子的生命周期,即粒子从激活之后到消亡这段时间,因为我们的每颗粒子都会消亡,这里我们说一下,通常一个粒子消亡之后,我们不会去释放他,而是将其标记为为激活状态,用来作为下一个将要产生的例子(去修改其属性值即可),这样就避免了重复的分配内存空间。当然如果你确实需要释放也是可以的。发射器(ParticleSystem)上面我们介绍了单独的一刻粒子对象,这里我们来分析一下如何实现一个发射器,来控制每一颗粒子的发射情况,在分析这个发射器之前,我们首先看一下粒子系统一般包括哪几种?粒子系统一般可以按照其特性分为两类: 模拟重力效果 以半径来进行扩散 重力效果相信不用过多的介绍了,就是通过程序来模拟物理重力效果,那么另外一种是以一个中心点,来根据所设定的半径进行扩散的粒子,因此我们首先将这两种不同的粒子通过一个enum分区开来,起定义如代码清单8-2所示。代码清单8-2:Modeview plaincopy to clipboardprint?1. /粒子系统模式 2. publicstaticenumMode 3. GRAVITY,/模拟重力 4. RADIUS;/以半径来扩散 5. /粒子系统模式 public static enum Mode GRAVITY,/模拟重力 RADIUS;/以半径来扩散 稍后我们会在程序中实现这样两种粒子效果,现在大家可以思考一个问题,在我们的粒子系统中,这些微粒他们应该如何运动呢?实际上运动就是改变这些微粒的坐标位置,那么我们可以按照坐标的位置来将粒子系统分为两种,他们分别是:自由运动,成组运动。每一颗粒子他可以按照自己的属性来自由的运动,当然在某些特殊需求时,我们可以将粒子分成很多组,然后对这每一组的所有粒子采用一种运动方式,那么就是我们所说的成组运动的方式,我们同样也先通过一个enum将其分别定义出来,如代码清单8-3所示。代码青岛那8-3:PositionTypeview plaincopy to clipboardprint?1. /位置类型 2. publicstaticenumPositionType 3. FREE,/自由 4. GROUPED;/组 5. /位置类型 public static enum PositionType FREE,/自由 GROUPED;/组 其中FREE代表自由运动,GROUPED代表成组的运动。好的,我们已经对粒子系统,也就是发射器进行了分类,下面我们来分析如何实现这个发射器呢?这里我们将以一个通用的发射器来作为基类进行实现,具体的特殊的特效,我们可以继承自该发射器来完善,首先看一下我们这个发射器他需要包括哪些属性呢?如代码清单8-4所示。代码清单8-4:ParticleSystem成员view plaincopy to clipboardprint?1. /粒子系统基类 2. publicclassParticleSystemextendsNodeimplementsNode.IBlendableTextureOwner 3. publicstaticfinalintPARTICLE_DURATION_INFINITY=-1; 4. publicstaticfinalintPARTICLE_START_SIZE_EQUAL_TO_END_SIZE=-1; 5. publicstaticfinalintPARTICLE_START_RADIUS_EQUAL_TO_END_RADIUS=-1; 6. /是否要更新 7. privatebooleanmUpdating; 8. /是否激活 9. privatebooleanmActive; 10. /运行时间 11. protectedfloatmDuration; 12. /流失的时间 13. privatefloatmElapsed; 14. /所有粒子重心,(变化范围) 15. protectedYFSPointmCenterOfGravity; 16. protectedYFSPointmCenterOfGravityVar; 17. /角度,(变化范围) 18. protectedfloatmAngle; 19. protectedfloatmAngleVar; 20. /开始结束尺寸,(变化范围) 21. protectedfloatmStartSize; 22. protectedfloatmStartSizeVar; 23. protectedfloatmEndSize; 24. protectedfloatmEndSizeVar; 25. /生命,(变化范围) 26. protectedfloatmLife; 27. protectedfloatmLifeVar; 28. /开始结束颜色,(变化范围) 29. protectedYFSColor4FmStartColor; 30. protectedYFSColor4FmStartColorVar; 31. protectedYFSColor4FmEndColor; 32. protectedYFSColor4FmEndColorVar; 33. /开始结束自旋角度,(变化范围) 34. protectedfloatmStartSpin; 35. protectedfloatmStartSpinVar; 36. protectedfloatmEndSpin; 37. protectedfloatmEndSpinVar; 38. /所有粒子列表 39. protectedListmParticles; 40. /最大粒子数目 41. protectedintmMaxParticles; 42. /粒子计数 43. protectedintmParticleCount; 44. /粒子排放速率 45. protectedfloatmEmissionRate; 46. /粒子排放计数器 47. protectedfloatmEmitCounter; 48. /纹理贴图 49. protectedTexture2DmTexture; 50. /混合方式 51. protectedYFSBlendFuncmBlendFunc; 52. /位置类型,运动方式 53. protectedPositionTypemPositionType; 54. /完成之后是否自动释放 55. protectedbooleanmAutoRemoveOnFinish; 56. /索引 57. protectedintmParticleIdx; 58. /排放模式 59. protectedModemEmitterMode; 60. /重心 61. protectedYFSPointmGravity; 62. /速度,(变化范围) 63. protectedfloatmSpeed; 64. protectedfloatmSpeedVar; 65. /切向加速度,(变化范围) 66. protectedfloatmTangentialAccel; 67. protectedfloatmTangentialAccelVar; 68. /径向加速度,(变化范围) 69. protectedfloatmRadialAccel; 70. protectedfloatmRadialAccelVar; 71. /开始结束的半径,(变化范围) 72. protectedfloatmStartRadius; 73. protectedfloatmStartRadiusVar; 74. protectedfloatmEndRadius; 75. protectedfloatmEndRadiusVar; 76. /旋转角度,(变化范围) 77. publicfloatmRotationDegree; 78. publicfloatmRotationDegreeVar; 79. /之前的位置 80. privatebooleanmPendingPosition; 81. /之前的x,y 82. privatefloatmPendingX; 83. privatefloatmPendingY; 84. /. 85. /粒子系统基类 public class ParticleSystem extends Node implements Node.IBlendableTextureOwner public static final int PARTICLE_DURATION_INFINITY = -1; public static final int PARTICLE_START_SIZE_EQUAL_TO_END_SIZE = -1; public static final int PARTICLE_START_RADIUS_EQUAL_TO_END_RADIUS = -1; /是否要更新 private boolean mUpdating; /是否激活 private boolean mActive; /运行时间 protected float mDuration; /流失的时间 private float mElapsed; /所有粒子重心,(变化范围) protected YFSPoint mCenterOfGravity; protected YFSPoint mCenterOfGravityVar; /角度,(变化范围) protected float mAngle; protected float mAngleVar; /开始结束尺寸,(变化范围) protected float mStartSize; protected float mStartSizeVar; protected float mEndSize; protected float mEndSizeVar; /生命,(变化范围) protected float mLife; protected float mLifeVar; /开始结束颜色,(变化范围) protected YFSColor4F mStartColor; protected YFSColor4F mStartColorVar; protected YFSColor4F mEndColor; protected YFSColor4F mEndColorVar; /开始结束自旋角度,(变化范围) protected float mStartSpin; protected float mStartSpinVar; protected float mEndSpin; protected float mEndSpinVar; /所有粒子列表 protected List mParticles; /最大粒子数目 protected int mMaxParticles; /粒子计数 protected int mParticleCount; /粒子排放速率 protected float mEmissionRate; /粒子排放计数器 protected float mEmitCounter; /纹理贴图 protected Texture2D mTexture; /混合方式 protected YFSBlendFunc mBlendFunc; /位置类型,运动方式 protected PositionType mPositionType; /完成之后是否自动释放 protected boolean mAutoRemoveOnFinish; /索引 protected int mParticleIdx; /排放模式 protected Mode mEmitterMode; /重心 protected YFSPoint mGravity; /速度,(变化范围) protected float mSpeed; protected float mSpeedVar; /切向加速度,(变化范围) protected float mTangentialAccel; protected float mTangentialAccelVar; /径向加速度,(变化范围) protected float mRadialAccel; protected float mRadialAccelVar; / 开始结束的半径,(变化范围) protected float mStartRadius; protected float mStartRadiusVar; protected float mEndRadius; protected float mEndRadiusVar; /旋转角度,(变化范围) public float mRotationDegree; public float mRotationDegreeVar; /之前的位置 private boolean mPendingPosition; /之前的x,y private float mPendingX; private float mPendingY; /. 代码清单8-4中“/.”表示我们省略了不分具体的操作内容,后面再分析,首先我们可以看到该类继承自Node,而同时实现了Node.IBlendableTextureOwner接口,说明我们的粒子系统也是一个节点node,这里就方便我们统一使用引擎来管理场景中的所有节点,及其操作。由于我们的发射器是由很多个小的微粒组成的,所以我们使用了mParticles来存放这些所有的微粒,其中mAutoRemoveOnFinish就用于判断当一个粒子消亡之后是否需要释放其空间,其他的都是粒子所需要一些基本特性的定义,这里我们就不多说了,整个类的实现也是非常简单,还包括一些set/get函数来对这些属性进行设置,很简单,所以我们就不一一贴出代码了,下面我们看看几个具体的操作,比如:粒子系统的初始化,更新,等,如代码清单8-5所示。代码清单8-5:ParticleSystem实现view plaincopy to clipboardprint?1. publicParticleSystem(intnumberOfParticles) 2. /最大粒子数量 3. this.mMaxParticles=numberOfParticles; 4. 5. this.mParticles=newArrayList(this.mMaxParticles); 6. 7. this.mActive=true; 8. /设置默认混合方式 9. this.mBlendFunc=newYFSBlendFunc(GL10.GL_SRC_ALPHA,GL10.GL_ONE_MINUS_SRC_ALPHA); 10. /类型默认为自由运动方式 11. this.mPositionType=PositionType.FREE; 12. /重力模式13. this.mEmitterMode=Mode.GRAVITY; 14. /完成之后不自动释放 15. this.mAutoRemoveOnFinish=false; 16. 17. this.mCenterOfGravity=YFSPoint.makeZero(); 18. this.mGravity=YFSPoint.makeZero(); 19. this.mCenterOfGravityVar=YFSPoint.makeZero(); 20. this.mStartColor=newYFSColor4F(); 21. this.mStartColorVar=newYFSColor4F(); 22. this.mEndColor=newYFSColor4F(); 23. this.mEndColorVar=newYFSColor4F(); 24. /更新函数回调 25. schedule(update); 26. 27. /添加粒子 28. privatebooleanaddParticle() 29. if(isFull() 30. returnfalse; 31. 32. Particleparticle=newParticle(); 33. /初始化一个粒子 34. initParticle(particle); 35. /添加,计数+1 36. this.mParticles.add(particle); 37. this.mParticleCount+=1; 38. returntrue; 39. 40. /设置,得到时间 41. publicvoidsetDuration(floatduration) 42. this.mDuration=duration; 43. 44. publicfloatgetDuration() 45. returnthis.mDuration; 46. 47. 48. publicYFSPointgetCenterOfGravity() 49. returnthis.mCenterOfGravity; 50. 51. /设置粒子重心位置 52. publicvoidsetParticlePositionVariance(YFSPointbase,YFSPointvariance) 53. if(base!=null) 54. this.mCenterOfGravity=base; 55. if(variance!=null) 56. this.mCenterOfGravityVar=variance; 57. 58. /初始化粒子 59. privatevoidinitParticle(Particleparticle) 60. particle.timeToLive=Math.max(0.0F,this.mLife+this.mLifeVar 61. *Utilities.randMinusOneToOne(); 62. 63. particle.pos.x=(this.mCenterOfGravity.x+this.mCenterOfGravityVar.x 64. *Utilities.randMinusOneToOne(); 65. particle.pos.y=(this.mCenterOfGravity.y+this.mCenterOfGravityVar.y 66. *Utilities.randMinusOneToOne(); 67. 68. YFSColor4Fstart=newYFSColor4F(); 69. start.r=Math.min( 70. 1.0F, 71. Math.max(0.0F,this.mStartColor.r+this.mStartColorVar.r 72. *Utilities.randMinusOneToOne(); 73. start.g=Math.min( 74. 1.0F, 75. Math.max(0.0F,this.mStartColor.g+this.mStartColorVar.g 76. *Utilities.randMinusOneToOne(); 77. start.b=Math.min( 78. 1.0F, 79. Math.max(0.0F,this.mStartColor.b+this.mStartColorVar.b 80. *Utilities.randMinusOneToOne(); 81. start.a=Math.min( 82. 1.0F, 83. Math.max(0.0F,this.mStartColor.a+this.mStartColorVar.a 84. *Utilities.randMinusOneToOne(); 85. 86. YFSColor4Fend=newYFSColor4F(); 87. end.r=Math.min( 88. 1.0F, 89. Math.max(0.0F,this.mEndColor.r+this.mEndColorVar.r 90. *Utilities.randMinusOneToOne(); 91. end.g=Math.min( 92. 1.0F, 93. Math.max(0.0F,this.mEndColor.g+this.mEndColorVar.g 94. *Utilities.randMinusOneToOne(); 95. end.b=Math.min( 96. 1.0F, 97. Math.max(0.0F,this.mEndColor.b+this.mEndColorVar.b 98. *Utilities.randMinusOneToOne(); 99. end.a=Math.min( 100. 1.0F, 101. Math.max(0.0F,this.mEndColor.a+this.mEndColorVar.a 102. *Utilities.randMinusOneToOne(); 103. 104. particle.color=start; 105. particle.deltaColor.r=(end.r-start.r)/particle.timeToLive); 106. particle.deltaColor.g=(end.g-start.g)/particle.timeToLive); 107. particle.deltaColor.b=(end.b-start.b)/particle.timeToLive); 108. particle.deltaColor.a=(end.a-start.a)/particle.timeToLive); 109. 110. floatstartS=Math.max(0.0F,this.mStartSize+this.mStartSizeVar 111. *Utilities.randMinusOneToOne(); 112. 113. particle.size=startS; 114. if(this.mEndSize=-1.0F) 115. particle.deltaSize=0.0F; 116. else 117. floatendS=this.mEndSize+this.mEndSizeVar 118. *Utilities.randMinusOneToOne(); 119. endS=Math.max(0.0F,endS); 120. particle.deltaSize=(endS-startS)/particle.timeToLive); 121. 122. 123. floatstartA=this.mStartSpin+this.mStartSpinVar 124. *Utilities.randMinusOneToOne(); 125. floatendA=this.mEndSpin+this.mEndSpinVar 126. *Utilities.randMinusOneToOne(); 127. particle.rotation=startA; 128. particle.deltaRotation=(endA-startA)/particle.timeToLive); 129. 130. if(this.mPositionType=PositionType.FREE) 131. particle.startPos=convertToWorldSpace(0.0F,0.0F); 132. 133. 134. floata=Utilities.d2r(this.mAngle+this.mAngleVar 135. *Utilities.randMinusOneToOne(); 136. 137. if(this.mEmitterMode=Mode.GRAVITY) 138. YFSPointv=YFSPoint.makeZero(); 139. v.y=(float)Math.sin(a); 140. v.x=(float)Math.cos(a); 141. floats=this.mSpeed+this.mSpeedVar 142. *Utilities.randMinusOneToOne(); 143. 144. particle.direction=YFSPoint.mul(v,s); 145. 146. particle.radialAccel=(this.mRadialAccel+this.mRadialAccelVar 147. *Utilities.randMinusOneToOne(); 148. 149. particle.tangentialAccel=(this.mTangentialAccel+this.mTangentialAccelVar 150. *Utilities.randMinusOneToOne(); 151. else 152. floatsRadius=this.mStartRadius+this.mStartRadiusVar 153. *Utilities.randMinusOneToOne(); 154. floateRadius=this.mEndRadius+this.mEndRadiusVar 155. *Utilities.randMinusOneToOne(); 156. 157. particle.radius=sRadius; 158. 159. if(this.mEndRadius=-1.0F) 160. particle.deltaRadius=0.0F; 161. else 162. particle.deltaRadius=(eRadius-sRadius)/particle.timeToLive); 163. 164. particle.radian=a; 165. particle.radianPerSecond=Utilit

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论