Cocos2d-x2.0 粒子系统深入分析三部曲(二)

前端之家收集整理的这篇文章主要介绍了Cocos2d-x2.0 粒子系统深入分析三部曲(二)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

Cocos2d-x2.0 粒子系统深入分析三部曲(二)

分类Cocos2d-x学习 10604人阅读 评论(6) 收藏 举报

目录(?)[+]

[Cocos2d-x相关教程来源于红孩儿的游戏编程之路CSDN博客地址:http://blog.csdn.net/honghaier]

红孩儿Cocos2d-X学习园地QQ2群:44208467加群写:Cocos2d-x
红孩儿Cocos2d-X学习园地QQ群:249941957加群写:Cocos2d-x

Cocos2d-x2.0 粒子系统深入分析三部曲(二)


上一节我们了解了粒子系统的原理,也学习了Cocos2d-x中的两个有关粒子系统的类:

(1)CCParticleSystem :粒子系统的基类,提供对粒子的创建和更新管理。

(2)CCParticleBatchNode:粒子系统的批次结点,用于将使用相同纹理的粒子系统进行同批次渲染优化处理。

在学习CCParticleSystem时,我们留下了一些疑问,什么时候调用setBatchNode?以及做为基类,CCParticleSystem提供了两个供子类重载的纯虚函数postStep()和updateQuadWithParticle,它们的具体用法是什么?我们仍然有一些迷茫。

我们今天来了解一下CCParticleSystemQuad,这个类是CCParticleSystem的子类。它将解开我们的这些疑惑。

打开CCParticleSystemQuad.h:

  1. classCC_DLLCCParticleSystemQuad:publicCCParticleSystem@H_502_141@
  2. {@H_502_141@
  3. protected:@H_502_141@
  4. //如果当前粒子系统未使用批次结点,则需要为粒子系统创建单独的顶点缓冲及索引缓冲以及OPENGL进行渲染的一些相关物件。@H_502_141@
  5. ccV3F_C4B_T2F_Quad*m_pQuads;//OPENGL渲染图形所用的四边形顶点缓冲。@H_502_141@
  6. GLushort*m_pIndices;//OPENGL渲染图形所用的索引缓冲。@H_502_141@
  7. //这里有宏判断当前OPENGL版本是否支持使用VAO处理顶点缓冲(VAO是什么?这个问题问的好,VAO是OPENGL3.X以上引入的新特性,VBO是VertexBufferObject,VAO是VertexArrayObject。VAO是OpenGL3.0以后才引入的新东西,但是在2.0版本中做为扩展接口。VBO其实就是显卡中的显存,为了提高渲染速度,可以将要绘制的顶点数据缓存在显存中,这样就不需要将要绘制的顶点数据重复从cpu发送到GPU,浪费带宽资源。而VAO则是一个容器,可以包括多个VBO,它类似于以前的calllist,由于它进一步将VBO容于其中,所以绘制效率将在VBO的基础上更进一步。)@H_502_141@
  8. #ifCC_TEXTURE_ATLAS_USE_VAO@H_502_141@
  9. GLuintm_uVAOname;//VAO的句柄。@H_502_141@
  10. #endif@H_502_141@
  11. GLuintm_pBuffersVBO[2];//VBO的两个句柄,第一个句柄对应顶点缓冲,第二个句柄对应索引缓冲。@H_502_141@
  12. public:@H_502_141@
  13. //构造函数@H_502_141@
  14. CCParticleSystemQuad();@H_502_141@
  15. //析构函数@H_502_141@
  16. virtual~CCParticleSystemQuad();@H_502_141@
  17. @H_502_141@
  18. //创建函数,参为为PLIST,内部调用create实现。@H_502_141@
  19. CC_DEPRECATED_ATTRIBUTEstaticCCParticleSystemQuad*particleWithFile(constchar*plistFile);@H_502_141@
  20. @H_502_141@
  21. //上面函数的create实现。@H_502_141@
  22. staticCCParticleSystemQuad*create(char*plistFile);@H_502_141@
  23. //初始化索引缓冲。@H_502_141@
  24. voidsetupIndices();@H_502_141@
  25. //初始化方理坐标。@H_502_141@
  26. voidinitTexCoordsWithRect(constCCRect&rect);@H_502_141@
  27. //设置显示一个精灵帧。@H_502_141@
  28. voidsetDisplayFrame(CCSpriteFrame*spriteFrame);@H_502_141@
  29. //设置使用纹理对象上指定的矩形图像区域做为粒子系统的贴图。@H_502_141@
  30. voidsetTextureWithRect(CCTexture2D*texture,//重载基类粒子系统的相应函数@H_502_141@
  31. //初始化粒子数量@H_502_141@
  32. virtualboolinitWithTotalParticles(unsignedintnumberOfParticles);@H_502_141@
  33. //设置所用的纹理对象指针@H_502_141@
  34. virtualvoidsetTexture(CCTexture2D*texture);@H_502_141@
  35. //上一篇留下的疑问,虽然明显是更新粒子顶点缓冲中的位置数据。但上一篇为什么没有实现?@H_502_141@
  36. voidupdateQuadWithParticle(tCCParticle*particle,153); font-weight:bold; background-color:inherit">constCCPoint&newPosition);@H_502_141@
  37. //上一篇留下的疑问,不知道是做什么,咱们到CPP中看吧。@H_502_141@
  38. voidpostStep();@H_502_141@
  39. //渲染处理。@H_502_141@
  40. voiddraw();@H_502_141@
  41. //设置批次结点。@H_502_141@
  42. voidsetBatchNode(CCParticleBatchNode*batchNode);@H_502_141@
  43. //设置总的粒子数量@H_502_141@
  44. voidsetTotalParticles(unsignedinttp);@H_502_141@
  45. //监听响应当前结点的EVNET_COME_TO_FOREGROUND事件的回调函数@H_502_141@
  46. voidlistenBackToForeground(CCObject*obj);@H_502_141@
  47. //创建一个当前实例结点,内部调用create实现。@H_502_141@
  48. CC_DEPRECATED_ATTRIBUTEstaticCCParticleSystemQuad*node();@H_502_141@
  49. //上面的create实现。@H_502_141@
  50. staticCCParticleSystemQuad*create();@H_502_141@
  51. private:@H_502_141@
  52. //如果使用VAO@H_502_141@
  53. #ifCC_TEXTURE_ATLAS_USE_VAO@H_502_141@
  54. //初始化VAO和VBO@H_502_141@
  55. voidsetupVBOandVAO();@H_502_141@
  56. #else@H_502_141@
  57. //初始化VBO@H_502_141@
  58. voidsetupVBO();@H_502_141@
  59. #endif@H_502_141@
  60. //申请内存。@H_502_141@
  61. boolallocMemory();@H_502_141@
  62. };@H_502_141@

对应的实现:


copy
    //重载粒子系统基类的初始化函数,创建相应数量的粒子。@H_502_141@
  1. boolCCParticleSystemQuad::initWithTotalParticles(unsignedintnumberOfParticles)@H_502_141@
  2. {@H_502_141@
  3. //调用基类的相应函数@H_502_141@
  4. if(CCParticleSystem::initWithTotalParticles(numberOfParticles))@H_502_141@
  5. //创建顶点和索引缓冲,如果失败释放并返回。@H_502_141@
  6. if(!this->allocMemory()){@H_502_141@
  7. this->release();@H_502_141@
  8. returnfalse;@H_502_141@
  9. }@H_502_141@
  10. //填充索引缓冲。@H_502_141@
  11. setupIndices();@H_502_141@
  12. //如果当前OPENGL版本支持VAO,就创建VAO,如果不支持,只创建VBO。@H_502_141@
  13. setupVBOandVAO();@H_502_141@
  14. #else@H_502_141@
  15. setupVBO();@H_502_141@
  16. //设置使用顶点格式为“位置+纹理+顶点色”的顶点格式组合。@H_502_141@
  17. setShaderProgram(CCShaderCache::sharedShaderCache()->programForKey(kCCShader_PositionTextureColor));@H_502_141@
  18. //告诉通知中心,注册函数listenBackToForeground用来响应当前结点的EVNET_COME_TO_FOREGROUND事件。这个事件的意义是程序将由后面返回到前台。这个事件响应时可做资源的重新载入。@H_502_141@
  19. CCNotificationCenter::sharedNotificationCenter()->addObserver(this,@H_502_141@
  20. callfuncO_selector(CCParticleSystemQuad::listenBackToForeground),@H_502_141@
  21. EVNET_COME_TO_FOREGROUND,@H_502_141@
  22. NULL);@H_502_141@
  23. true;@H_502_141@
  24. //构造函数@H_502_141@
  25. CCParticleSystemQuad::CCParticleSystemQuad()@H_502_141@
  26. :m_pQuads(NULL)@H_502_141@
  27. ,m_pIndices(NULL)@H_502_141@
  28. 502_141@
  29. memset(m_pBuffersVBO,sizeof(m_pBuffersVBO));@H_502_141@
  30. //析构函数@H_502_141@
  31. CCParticleSystemQuad::~CCParticleSystemQuad()@H_502_141@
  32. //对所创建的顶点缓冲,索引缓冲,以及VBO,VA0进行释放。@H_502_141@
  33. if(NULL==m_pBatchNode)@H_502_141@
  34. CC_SAFE_FREE(m_pQuads);@H_502_141@
  35. CC_SAFE_FREE(m_pIndices);@H_502_141@
  36. glDeleteBuffers(2,&m_pBuffersVBO[0]);@H_502_141@
  37. glDeleteVertexArrays(1,&m_uVAOname);@H_502_141@
  38. }@H_502_141@
  39. //注销对通知管理器注册的相应事件的响应处理函数@H_502_141@
  40. CCNotificationCenter::sharedNotificationCenter()->removeObserver(502_141@
  41. //静态创建函数。由PLIST文件创建相应的当前实例对象,内部调用create实现。@H_502_141@
  42. CCParticleSystemQuad*CCParticleSystemQuad::particleWithFile(char*plistFile)@H_502_141@
  43. returnCCParticleSystemQuad::create(plistFile);@H_502_141@
  44. CCParticleSystemQuad*CCParticleSystemQuad::create(char*plistFile)@H_502_141@
  45. //创建一个CCParticleSystemQuad实例对象,进行初始化后交由内存管理器进行引用计数器的管理。@H_502_141@
  46. CCParticleSystemQuad*pRet=newCCParticleSystemQuad();@H_502_141@
  47. if(pRet&&pRet->initWithFile(plistFile))@H_502_141@
  48. pRet->autorelease();@H_502_141@
  49. returnpRet;@H_502_141@
  50. //如果失败,删除并置空,返回NULL。@H_502_141@
  51. CC_SAFE_DELETE(pRet);@H_502_141@
  52. //初始化纹理坐标。@H_502_141@
  53. voidCCParticleSystemQuad::initTexCoordsWithRect(constCCRect&pointRect)@H_502_141@
  54. //创建出相应的矩形。@H_502_141@
  55. CCRectrect=CCRectMake(@H_502_141@
  56. pointRect.origin.x*CC_CONTENT_SCALE_FACTOR(),248)"> pointRect.origin.y*CC_CONTENT_SCALE_FACTOR(),108); list-style:decimal-leading-zero outside; color:inherit; line-height:18.9473686218262px; margin:0px!important; padding:0px 3px 0px 10px!important"> pointRect.size.width*CC_CONTENT_SCALE_FACTOR(),248)"> pointRect.size.height*CC_CONTENT_SCALE_FACTOR());@H_502_141@
  57. //默认使用的是批次结点,以批次结点的纹理对设置所用的图像区域矩形宽高。@H_502_141@
  58. GLfloatwide=(GLfloat)pointRect.size.width;@H_502_141@
  59. GLfloathigh=(GLfloat)pointRect.size.height;@H_502_141@
  60. //如果使用单纹理对象,取得纹理的宽高。@H_502_141@
  61. if(m_pTexture)@H_502_141@
  62. wide=(GLfloat)m_pTexture->getPixelsWide();@H_502_141@
  63. high=(GLfloat)m_pTexture->getPixelsHigh();@H_502_141@
  64. //此宏是为了解决精灵边缘黑线而做的纹理坐标的微调。@H_502_141@
  65. #ifCC_FIX_ARTIFACTS_BY_STRECHING_TEXEL@H_502_141@
  66. GLfloatleft=(rect.origin.x*2+1)/(wide*2);@H_502_141@
  67. GLfloatbottom=(rect.origin.y*2+1)/(high*2);@H_502_141@
  68. GLfloatright=left+(rect.size.width*2-2)/(wide*2);@H_502_141@
  69. GLfloattop=bottom+(rect.size.height*2-2)/(high*2);@H_502_141@
  70. GLfloatleft=rect.origin.x/wide;@H_502_141@
  71. GLfloatbottom=rect.origin.y/high;@H_502_141@
  72. GLfloatright=left+rect.size.width/wide;@H_502_141@
  73. GLfloattop=bottom+rect.size.height/high;@H_502_141@
  74. //将top与bottom交换一下,因为在Cococs2d-x中坐标系Y轴是向上为正,这里处理一下后面可以做为顶点位置数据。@H_502_141@
  75. CC_SWAP(top,bottom,float);@H_502_141@
  76. //根据是否使用批次结点来取得相应的矩形顶点缓冲数组。@H_502_141@
  77. ccV3F_C4B_T2F_Quad*quads=NULL;@H_502_141@
  78. unsignedintstart=0,end=0;@H_502_141@
  79. if(m_pBatchNode)@H_502_141@
  80. {//如果使用批次结点,这里取得批次结点中所有粒子所对应的矩形顶点数组。@H_502_141@
  81. quads=m_pBatchNode->getTextureAtlas()->getQuads();@H_502_141@
  82. //取得起始和结束的粒子所对应的矩形索引。@H_502_141@
  83. start=m_uAtlasIndex;@H_502_141@
  84. end=m_uAtlasIndex+m_uTotalParticles;@H_502_141@
  85. else@H_502_141@
  86. {//如果使用单纹理对象,则起始矩形索引就是0,结束矩形索引就是最大粒子数量@H_502_141@
  87. quads=m_pQuads;@H_502_141@
  88. start=0;@H_502_141@
  89. end=m_uTotalParticles;@H_502_141@
  90. //遍历所有的矩形顶点。@H_502_141@
  91. for(unsignedinti=start;i<end;i++)@H_502_141@
  92. //设置四个顶点的纹理坐标。@H_502_141@
  93. quads[i].bl.texCoords.u=left;@H_502_141@
  94. quads[i].bl.texCoords.v=bottom;@H_502_141@
  95. quads[i].br.texCoords.u=right;@H_502_141@
  96. quads[i].br.texCoords.v=bottom;@H_502_141@
  97. quads[i].tl.texCoords.u=left;@H_502_141@
  98. quads[i].tl.texCoords.v=top;@H_502_141@
  99. quads[i].tr.texCoords.u=right;@H_502_141@
  100. quads[i].tr.texCoords.v=top;@H_502_141@
  101. voidCCParticleSystemQuad::setTextureWithRect(CCTexture2D*texture,153); font-weight:bold; background-color:inherit">constCCRect&rect)@H_502_141@
  102. //如果当前尚无纹理对或者使用的纹理与参数指定的纹理不同。则设置使用参数指定的纹理。@H_502_141@
  103. if(!m_pTexture||texture->getName()!=m_pTexture->getName())@H_502_141@
  104. CCParticleSystem::setTexture(texture);@H_502_141@
  105. //设置指定的矩形图像区域做为贴图计算粒子系统的纹理坐标.@H_502_141@
  106. this->initTexCoordsWithRect(rect);@H_502_141@
  107. //设置使用的纹理对象。@H_502_141@
  108. voidCCParticleSystemQuad::setTexture(CCTexture2D*texture)@H_502_141@
  109. //取得纹理的大小。@H_502_141@
  110. constCCSize&s=texture->getContentSize();@H_502_141@
  111. this->setTextureWithRect(texture,CCRectMake(0,s.width,s.height));@H_502_141@
  112. //设置使用精灵帧中的纹理。@H_502_141@
  113. voidCCParticleSystemQuad::setDisplayFrame(CCSpriteFrame*spriteFrame)@H_502_141@
  114. //有效性判断。@H_502_141@
  115. CCAssert(spriteFrame->getOffsetInPixels().equals(CCPointZero),108); list-style:decimal-leading-zero outside; color:inherit; line-height:18.9473686218262px; margin:0px!important; padding:0px 3px 0px 10px!important"> "QuadParticleonlysupportsSpriteFrameswithnooffsets");@H_502_141@
  116. //如果当前尚无纹理对或者使用的纹理与参数指定的纹理不同。则设置使用参数指定的纹理。@H_502_141@
  117. if(!m_pTexture||spriteFrame->getTexture()->getName()!=m_pTexture->getName())@H_502_141@
  118. //设置使用精灵帧中的纹理.@H_502_141@
  119. this->setTexture(spriteFrame->getTexture());@H_502_141@
  120. voidCCParticleSystemQuad::setupIndices()@H_502_141@
  121. //遍历粒子数目计算索引缓冲值。@H_502_141@
  122. inti=0;i<m_uTotalParticles;++i)@H_502_141@
  123. constunsignedinti6=i*6;@H_502_141@
  124. inti4=i*4;@H_502_141@
  125. m_pIndices[i6+0]=(GLushort)i4+0;@H_502_141@
  126. m_pIndices[i6+1]=(GLushort)i4+1;@H_502_141@
  127. m_pIndices[i6+2]=(GLushort)i4+2;@H_502_141@
  128. m_pIndices[i6+5]=(GLushort)i4+1;@H_502_141@
  129. m_pIndices[i6+4]=(GLushort)i4+2;@H_502_141@
  130. m_pIndices[i6+3]=(GLushort)i4+3;@H_502_141@
  131. //更新指定粒子的顶点缓冲中的位置数据。@H_502_141@
  132. voidCCParticleSystemQuad::updateQuadWithParticle(tCCParticle*particle,153); font-weight:bold; background-color:inherit">constCCPoint&newPosition)@H_502_141@
  133. //定义临时指针变量用于取得相应的粒子所对应的矩形顶点缓冲。@H_502_141@
  134. ccV3F_C4B_T2F_Quad*quad;@H_502_141@
  135. //如果使用了批次结点。@H_502_141@
  136. if(m_pBatchNode)@H_502_141@
  137. //取得批次结点中对应的矩形顶点缓冲数组指针。@H_502_141@
  138. ccV3F_C4B_T2F_Quad*batchQuads=m_pBatchNode->getTextureAtlas()->getQuads();@H_502_141@
  139. //通过索引取得相应的矩形顶点缓冲。@H_502_141@
  140. quad=&(batchQuads[m_uAtlasIndex+particle->atlasIndex]);@H_502_141@
  141. else@H_502_141@
  142. //如果没有使用批次结点,直接取得相应的粒子的矩形顶点缓冲。@H_502_141@
  143. quad=&(m_pQuads[m_uParticleIdx]);@H_502_141@
  144. //根据是否由ALPHA值来设定RGB取得相应的颜色值。@H_502_141@
  145. ccColor4Bcolor=(m_bOpacityModifyRGB)@H_502_141@
  146. ?ccc4(particle->color.r*particle->color.a*255,particle->color.g*particle->color.a*255,particle->color.b*particle->color.a*255,particle->color.a*255)@H_502_141@
  147. :ccc4(particle->color.r*255,particle->color.g*255,particle->color.b*255,particle->color.a*255);@H_502_141@
  148. //填真顶点缓冲中的颜色信息。@H_502_141@
  149. quad->bl.colors=color;@H_502_141@
  150. quad->br.colors=color;@H_502_141@
  151. quad->tl.colors=color;@H_502_141@
  152. quad->tr.colors=color;@H_502_141@
  153. //设置顶点的位置信息@H_502_141@
  154. GLfloatsize_2=particle->size/2;@H_502_141@
  155. //判断是否进行旋转。@H_502_141@
  156. if(particle->rotation)@H_502_141@
  157. //定义临时变量来存放以size_2为半径的矩形外圆上的四个顶点。@H_502_141@
  158. GLfloatx1=-size_2;@H_502_141@
  159. GLfloaty1=-size_2;@H_502_141@
  160. GLfloatx2=size_2;@H_502_141@
  161. GLfloaty2=size_2;@H_502_141@
  162. //定义临时变量来存放圆心。@H_502_141@
  163. GLfloatx=newPosition.x;@H_502_141@
  164. GLfloaty=newPosition.y;@H_502_141@
  165. //求得旋转角度。@H_502_141@
  166. GLfloatr=(GLfloat)-CC_DEGREES_TO_RADIANS(particle->rotation);@H_502_141@
  167. //通过sin,cos来计算旋转后的矩形外圆上的四个角的顶点位置。@H_502_141@
  168. GLfloatcr=cosf(r);@H_502_141@
  169. GLfloatsr=sinf(r);@H_502_141@
  170. GLfloatax=x1*cr-y1*sr+x;@H_502_141@
  171. GLfloatay=x1*sr+y1*cr+y;@H_502_141@
  172. GLfloatbx=x2*cr-y1*sr+x;@H_502_141@
  173. GLfloatby=x2*sr+y1*cr+y;@H_502_141@
  174. GLfloatcx=x2*cr-y2*sr+x;@H_502_141@
  175. GLfloatcy=x2*sr+y2*cr+y;@H_502_141@
  176. GLfloatdx=x1*cr-y2*sr+x;@H_502_141@
  177. GLfloatdy=x1*sr+y2*cr+y;@H_502_141@
  178. //填充计算旋转后的顶点位置信息。@H_502_141@
  179. quad->bl.vertices.x=ax;@H_502_141@
  180. quad->bl.vertices.y=ay;@H_502_141@
  181. quad->br.vertices.x=bx;@H_502_141@
  182. quad->br.vertices.y=by;@H_502_141@
  183. quad->tl.vertices.x=dx;@H_502_141@
  184. quad->tl.vertices.y=dy;@H_502_141@
  185. quad->tr.vertices.x=cx;@H_502_141@
  186. quad->tr.vertices.y=cy;@H_502_141@
  187. //如果不旋转,直接填充位置信息。@H_502_141@
  188. quad->bl.vertices.x=newPosition.x-size_2;@H_502_141@
  189. quad->bl.vertices.y=newPosition.y-size_2;@H_502_141@
  190. quad->br.vertices.x=newPosition.x+size_2;@H_502_141@
  191. quad->br.vertices.y=newPosition.y-size_2;@H_502_141@
  192. quad->tl.vertices.x=newPosition.x-size_2;@H_502_141@
  193. quad->tl.vertices.y=newPosition.y+size_2;@H_502_141@
  194. quad->tr.vertices.x=newPosition.x+size_2;@H_502_141@
  195. quad->tr.vertices.y=newPosition.y+size_2;@H_502_141@
  196. //我们一直想知道在CCParticleSystem中每次update时,如果粒子批次结点为空时为什么要调用postStep?它倒底是干什么的,看完下面的代码,就很清楚了。@H_502_141@
  197. voidCCParticleSystemQuad::postStep()@H_502_141@
  198. //绑定顶点缓冲区对象。@H_502_141@
  199. glBindBuffer(GL_ARRAY_BUFFER,m_pBuffersVBO[0]);@H_502_141@
  200. //用m_pQuads中数据更新绑定的缓冲区数据。@H_502_141@
  201. glBufferSubData(GL_ARRAY_BUFFER,153); font-weight:bold; background-color:inherit">sizeof(m_pQuads[0])*m_uParticleCount,m_pQuads);@H_502_141@
  202. //取消绑定缓冲区对象。@H_502_141@
  203. 502_141@
  204. CHECK_GL_ERROR_DEBUG();@H_502_141@
  205. //清楚了,原来这个函数是针对不使用批次结点时的VBO顶点缓冲的更新。@H_502_141@
  206. //绘制粒子系统。@H_502_141@
  207. voidCCParticleSystemQuad::draw()@H_502_141@
  208. //如果当前在粒子的批次结点有值,则draw()不应该被调用!为什么呢?因为有批次结点的话,渲染交给批次结点的draw()函数而不是当前粒子系统的draw()函数来处理。@H_502_141@
  209. CCAssert(!m_pBatchNode,"drawshouldnotbecalledwhenaddedtoaparticleBatchNode");@H_502_141@
  210. //使用相应的Shader@H_502_141@
  211. CC_NODE_DRAW_SETUP();@H_502_141@
  212. //绑定所用的纹理对象。@H_502_141@
  213. ccGLBindTexture2D(m_pTexture->getName());@H_502_141@
  214. //设定所用的ALPHA混合方案。@H_502_141@
  215. ccGLBlendFunc(m_tBlendFunc.src,m_tBlendFunc.dst);@H_502_141@
  216. //判断当前粒子索引是否为粒子总数,也就是判断是否已经update完成未出错。@H_502_141@
  217. CCAssert(m_uParticleIdx==m_uParticleCount,"Abnormalerrorinparticlequad");@H_502_141@
  218. //如果使用VAO。@H_502_141@
  219. //使用VAO绑定的顶点数组@H_502_141@
  220. glBindVertexArray(m_uVAOname);@H_502_141@
  221. //绑定索引数组@H_502_141@
  222. #ifCC_REBIND_INDICES_BUFFER@H_502_141@
  223. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,m_pBuffersVBO[1]);@H_502_141@
  224. //渲染调用@H_502_141@
  225. glDrawElements(GL_TRIANGLES,(GLsizei)m_uParticleIdx*6,GL_UNSIGNED_SHORT,0);@H_502_141@
  226. //渲染完取消绑定索引数组@H_502_141@
  227. //取消绑定顶点数组@H_502_141@
  228. glBindVertexArray(0);@H_502_141@
  229. //@H_502_141@
  230. //UsingVBOwithoutVAO@H_502_141@
  231. //@H_502_141@
  232. #definekQuadSizesizeof(m_pQuads[0].bl)@H_502_141@
  233. //设置使用相应的顶点格式为:位置+颜色+纹理坐标@H_502_141@
  234. ccGLEnableVertexAttribs(kCCVertexAttribFlag_PosColorTex);@H_502_141@
  235. //绑定顶点缓冲@H_502_141@
  236. //设置顶点缓冲中位置数据的描述@H_502_141@
  237. glVertexAttribPointer(kCCVertexAttrib_Position,3,GL_FLOAT,GL_FALSE,kQuadSize,(GLvoid*)offsetof(ccV3F_C4B_T2F,vertices));@H_502_141@
  238. //设置顶点缓冲中颜色数据的描述@H_502_141@
  239. glVertexAttribPointer(kCCVertexAttrib_Color,4,GL_UNSIGNED_BYTE,GL_TRUE,colors));@H_502_141@
  240. //设置顶点缓冲中纹理坐标数据的描述@H_502_141@
  241. glVertexAttribPointer(kCCVertexAttrib_TexCoords,2,texCoords));@H_502_141@
  242. //绑定索引缓冲@H_502_141@
  243. //渲染调用@H_502_141@
  244. glDrawElements(GL_TRIANGLES,0); background-color:inherit">//取消绑定@H_502_141@
  245. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); background-color:inherit">//渲染调用计数器加一@H_502_141@
  246. CC_INCREMENT_GL_DRAWS(1);@H_502_141@
  247. CHECK_GL_ERROR_DEBUG();@H_502_141@
  248. //设置粒子数量@H_502_141@
  249. voidCCParticleSystemQuad::setTotalParticles(unsignedinttp)@H_502_141@
  250. //如果要申请内存的粒子数量大于之前已经申请内存的粒子数量@H_502_141@
  251. if(tp>m_uAllocatedParticles)@H_502_141@
  252. //计算要申请的内存大小。@H_502_141@
  253. //粒子信息结构数组大小。@H_502_141@
  254. size_tparticlesSize=tp*sizeof(tCCParticle);@H_502_141@
  255. //顶点缓冲的大小@H_502_141@
  256. size_tquadsSize=sizeof(m_pQuads[0])*tp*1;@H_502_141@
  257. //索引缓冲的大小@H_502_141@
  258. size_tindicesSize=sizeof(m_pIndices[0])*tp*6*1;@H_502_141@
  259. //在m_pParticles指定的内存位置申请相应大小的内存用于存储粒子信息结构数组。@H_502_141@
  260. tCCParticle*particlesNew=(tCCParticle*)realloc(m_pParticles,particlesSize);@H_502_141@
  261. //在m_pQuads指定的内存位置申请相应大小的内存用于填充顶点缓冲。@H_502_141@
  262. ccV3F_C4B_T2F_Quad*quadsNew=(ccV3F_C4B_T2F_Quad*)realloc(m_pQuads,quadsSize);@H_502_141@
  263. //在m_pIndices指定的内存位置申请相应大小的内存用于填充索引缓冲。@H_502_141@
  264. GLushort*indicesNew=(GLushort*)realloc(m_pIndices,indicesSize);@H_502_141@
  265. //如果申请都成功。@H_502_141@
  266. if(particlesNew&&quadsNew&&indicesNew)@H_502_141@
  267. //将内存地址传值给成员指针。@H_502_141@
  268. m_pParticles=particlesNew;@H_502_141@
  269. m_pQuads=quadsNew;@H_502_141@
  270. m_pIndices=indicesNew;@H_502_141@
  271. //内存清零@H_502_141@
  272. memset(m_pParticles,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18.9473686218262px; margin:0px!important; padding:0px 3px 0px 10px!important"> memset(m_pQuads,quadsSize);@H_502_141@
  273. memset(m_pIndices,0); background-color:inherit">//记录申请内存的粒子数量@H_502_141@
  274. m_uAllocatedParticles=tp;@H_502_141@
  275. //如果失败,记录成功申请的内存地址打印出错LOG。@H_502_141@
  276. if(particlesNew)m_pParticles=particlesNew;@H_502_141@
  277. if(quadsNew)m_pQuads=quadsNew;@H_502_141@
  278. if(indicesNew)m_pIndices=indicesNew;@H_502_141@
  279. CCLOG("Particlesystem:outofmemory");@H_502_141@
  280. return;@H_502_141@
  281. //更新粒子数量@H_502_141@
  282. m_uTotalParticles=tp;@H_502_141@
  283. //根据是否使用批次结点来设定每个粒子对应的矩形顶点块的索引。@H_502_141@
  284. inti=0;i<m_uTotalParticles;i++)@H_502_141@
  285. m_pParticles[i].atlasIndex=i;@H_502_141@
  286. //填充索引缓冲。@H_502_141@
  287. setupIndices();@H_502_141@
  288. //初始化VAO@H_502_141@
  289. setupVBOandVAO();@H_502_141@
  290. //如果要申请内存的粒子数量小于原来申请的粒子数量,直接修改一下最大粒子数量就OK。@H_502_141@
  291. m_uTotalParticles=tp;@H_502_141@
  292. //如果当前OPENGL版本支持VAO。@H_502_141@
  293. //初始化VBO与VAO@H_502_141@
  294. voidCCParticleSystemQuad::setupVBOandVAO()@H_502_141@
  295. //初始化1个顶点数组对象,产生VAO对象的句柄@H_502_141@
  296. glGenVertexArrays(1,0); background-color:inherit">//绑定VAO。@H_502_141@
  297. glBindVertexArray(m_uVAOname);@H_502_141@
  298. //创建2个VBO缓冲区对象,产生两个句柄填充到句柄数组中。@H_502_141@
  299. glGenBuffers(2,0); background-color:inherit">//绑定第一个VBO缓冲区对象。@H_502_141@
  300. //将顶点数据拷贝到绑定的缓冲区。@H_502_141@
  301. glBufferData(GL_ARRAY_BUFFER,153); font-weight:bold; background-color:inherit">sizeof(m_pQuads[0])*m_uTotalParticles,m_pQuads,GL_DYNAMIC_DRAW);@H_502_141@
  302. //设置使用位置数据@H_502_141@
  303. glEnableVertexAttribArray(kCCVertexAttrib_Position);@H_502_141@
  304. //设置位置数据在顶点缓冲中的描述@H_502_141@
  305. glVertexAttribPointer(kCCVertexAttrib_Position,vertices));@H_502_141@
  306. //设置使用颜色数据@H_502_141@
  307. glEnableVertexAttribArray(kCCVertexAttrib_Color);@H_502_141@
  308. //设置颜色数据在顶点缓冲中的描述@H_502_141@
  309. //设置使用纹理坐标数据@H_502_141@
  310. glEnableVertexAttribArray(kCCVertexAttrib_TexCoords);@H_502_141@
  311. //设置纹理坐标数据在顶点缓冲中的描述@H_502_141@
  312. glVertexAttribPointer(kCCVertexAttrib_TexCoords,texCoords));@H_502_141@
  313. //绑定VBO的第二个缓冲区@H_502_141@
  314. //将索引缓冲区数据拷贝到绑定的缓冲区@H_502_141@
  315. glBufferData(GL_ELEMENT_ARRAY_BUFFER,153); font-weight:bold; background-color:inherit">sizeof(m_pIndices[0])*m_uTotalParticles*6,m_pIndices,GL_STATIC_DRAW);@H_502_141@
  316. glBindVertexArray(0);@H_502_141@
  317. //否则只使用VBO@H_502_141@
  318. voidCCParticleSystemQuad::setupVBO()@H_502_141@
  319. //创建2个VBO缓冲区对象,产生两个句柄填充到句柄数组中。@H_502_141@
  320. glGenBuffers(2,&m_pBuffersVBO[0]);@H_502_141@
  321. //绑定第一个VBO缓冲区对象并填充数据。@H_502_141@
  322. glBindBuffer(GL_ARRAY_BUFFER,m_pBuffersVBO[0]);@H_502_141@
  323. //绑定第二个VBO缓冲区对象并填充数据。@H_502_141@
  324. 502_141@
  325. //响应当前结点的EVNET_COME_TO_FOREGROUND事件。这个事件的意义是程序将由后面返回到前台。这个事件响应时可做资源的重新载入。@H_502_141@
  326. voidCCParticleSystemQuad::listenBackToForeground(CCObject*obj)@H_502_141@
  327. //重新初始化VBO和VAO。@H_502_141@
  328. //创建顶点缓冲和索引缓冲区。@H_502_141@
  329. boolCCParticleSystemQuad::allocMemory()@H_502_141@
  330. //如果已经申请则中断。@H_502_141@
  331. CCAssert((!m_pQuads&&!m_pIndices),"Memoryalreadyalloced");@H_502_141@
  332. CCAssert(!m_pBatchNode,"MemoryshouldnotbeallocedwhennotusingbatchNode");@H_502_141@
  333. //释放顶点与索引缓冲@H_502_141@
  334. //为顶点与索引缓冲申请内存。@H_502_141@
  335. m_pQuads=(ccV3F_C4B_T2F_Quad*)malloc(m_uTotalParticles*sizeof(ccV3F_C4B_T2F_Quad));@H_502_141@
  336. m_pIndices=(GLushort*)malloc(m_uTotalParticles*6*sizeof(GLushort));@H_502_141@
  337. //如果出现失败,则提示LOG并释放置空返回。@H_502_141@
  338. if(!m_pQuads||!m_pIndices)@H_502_141@
  339. CCLOG("cocos2d:Particlesystem:notenoughmemory");@H_502_141@
  340. CC_SAFE_FREE(m_pQuads);@H_502_141@
  341. CC_SAFE_FREE(m_pIndices);@H_502_141@
  342. //如果成功,置零操作返回true.@H_502_141@
  343. //设置CCParticleSystemQuad使用的粒子批次结点。@H_502_141@
  344. voidCCParticleSystemQuad::setBatchNode(CCParticleBatchNode*batchNode)@H_502_141@
  345. //如果当前使用的粒子批次结点与参数不同,则进行更换处理。@H_502_141@
  346. if(m_pBatchNode!=batchNode)@H_502_141@
  347. //先记录一下当前使用的。@H_502_141@
  348. CCParticleBatchNode*oldBatch=m_pBatchNode;@H_502_141@
  349. //将后调用基类相应函数,设置当前使用的粒子批次结点。@H_502_141@
  350. CCParticleSystem::setBatchNode(batchNode);@H_502_141@
  351. //如果参数值为空,代表不使用批次结点。则进行顶点缓冲的相关初始化。@H_502_141@
  352. if(!batchNode)@H_502_141@
  353. //创建顶点缓冲,填充索引,并根据是否可用VAO设置顶点缓冲,设置纹理。@H_502_141@
  354. allocMemory();@H_502_141@
  355. setTexture(oldBatch->getTexture());@H_502_141@
  356. setupVBO();@H_502_141@
  357. //如果批次结点有效,且更换前没有使用粒子批次结点。@H_502_141@
  358. elseif(!oldBatch)@H_502_141@
  359. //取得相应粒子批次结点的矩形数组,取出相应索引位置的矩形数据,将相应的顶点缓冲数据拷到矩形数组中。@H_502_141@
  360. ccV3F_C4B_T2F_Quad*quad=&(batchQuads[m_uAtlasIndex]);@H_502_141@
  361. memcpy(quad,153); font-weight:bold; background-color:inherit">sizeof(m_pQuads[0]));@H_502_141@
  362. //释放当前用的顶点缓冲@H_502_141@
  363. //释放所用的VBO顶点对象与AVO名称@H_502_141@
  364. glDeleteBuffers(2,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18.9473686218262px; margin:0px!important; padding:0px 3px 0px 10px!important"> glDeleteVertexArrays(1,&m_uVAOname);@H_502_141@
  365. //创建一个CCParticleSystemQuad,内部调用create实现。@H_502_141@
  366. CCParticleSystemQuad*CCParticleSystemQuad::node()@H_502_141@
  367. returnCCParticleSystemQuad::create();@H_502_141@
  368. CCParticleSystemQuad*CCParticleSystemQuad::create(){@H_502_141@
  369. //创建一个CCParticleSystemQuad的实例对象。@H_502_141@
  370. CCParticleSystemQuad*pParticleSystemQuad=newCCParticleSystemQuad();@H_502_141@
  371. //如果创建成功,进行初始化。成功后交由内存管理器进行引用计数器的管理。@H_502_141@
  372. if(pParticleSystemQuad&&pParticleSystemQuad->init())@H_502_141@
  373. pParticleSystemQuad->autorelease();@H_502_141@
  374. returnpParticleSystemQuad;@H_502_141@
  375. //如果失败,释放置空并返回NULL。@H_502_141@
  376. CC_SAFE_DELETE(pParticleSystemQuad);@H_502_141@
  377. returnNULL;@H_502_141@
  378. }@H_502_141@

总结: 类CCParticleSystemQuad的源码进一步完善了粒子系统的功能,使我们可以在不需要批次结点时也能够实现粒子系统的OPENGL顶点和索引缓冲的创建和渲染,这么看来CCParticleSystem是一个不完整的粒子系统的类,它只提供了使用粒子批次结点的粒子系统的渲染方案。

到这里,我们基本算领悟了Cocos2d-x中粒子系统的完整功能基类。后面我们将由此进入到多彩的粒子系统的演示中去!下课~

猜你在找的Cocos2d-x相关文章