目录(?)[+]
[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版本为:
cocos2d-2.0-x-2.0.2@ Aug 30 2012
http://cn.cocos2d-x.org/download
上一节我们了解了粒子系统的原理,也学习了Cocos2d-x中的两个有关粒子系统的类:
(1)CCParticleSystem :粒子系统的基类,提供对粒子的创建和更新管理。
(2)CCParticleBatchNode:粒子系统的批次结点,用于将使用相同纹理的粒子系统进行同批次渲染优化处理。
在学习CCParticleSystem时,我们留下了一些疑问,什么时候调用setBatchNode?以及做为基类,CCParticleSystem提供了两个供子类重载的纯虚函数poststep()和updateQuaDWithParticle,它们的具体用法是什么?我们仍然有一些迷茫。
我们今天来了解一下CCParticleSystemQuad,这个类是CCParticleSystem的子类。它将解开我们的这些疑惑。
打开CCParticleSystemQuad.h:
[cpp] view plain copy classCC_DLLCCParticleSystemQuad:publicCCParticleSystem { protected: //如果当前粒子系统未使用批次结点,则需要为粒子系统创建单独的顶点缓冲及索引缓冲以及OPENGL进行渲染的一些相关物件。 ccV3F_C4B_T2F_Quad*m_pQuads;//OPENGL渲染图形所用的四边形顶点缓冲。 glushort*m_pIndices;//OPENGL渲染图形所用的索引缓冲。 //这里有宏判断当前OPENGL版本是否支持使用VAO处理顶点缓冲(VAO是什么?这个问题问的好,VAO是OPENGL3.X以上引入的新特性,VBO是VertexBufferObject,VAO是VertexArrayObject。VAO是OpenGL3.0以后才引入的新东西,但是在2.0版本中做为扩展接口。VBO其实就是显卡中的显存,为了提高渲染速度,可以将要绘制的顶点数据缓存在显存中,这样就不需要将要绘制的顶点数据重复从cpu发送到GPU,浪费带宽资源。而VAO则是一个容器,可以包括多个VBO,它类似于以前的callList,由于它进一步将VBO容于其中,所以绘制效率将在VBO的基础上更进一步。) #ifCC_TEXTURE_ATLAS_USE_VAO gluintm_uVAOname;//VAO的句柄。 #endif gluintm_pBuffersVBO[2];//VBO的两个句柄,第一个句柄对应顶点缓冲,第二个句柄对应索引缓冲。 public: //构造函数。 CCParticleSystemQuad(); //析构函数。 virtual~CCParticleSystemQuad(); //创建函数,参为为PList,内部调用create实现。 CC_DEPRECATED_ATTRIBUTEstaticCCParticleSystemQuad*particleWithfile(constchar*pListfile); //上面函数的create实现。 staticCCParticleSystemQuad*create(char*pListfile); //初始化索引缓冲。 voIDsetupIndices(); //初始化方理坐标。 voIDinitTexCoordsWithRect(constCCRect&rect); //设置显示一个精灵帧。 voIDsetdisplayFrame(CCSpriteFrame*spriteFrame); //设置使用纹理对象上指定的矩形图像区域做为粒子系统的贴图。 voIDsetTextureWithRect(CCTexture2D*texture,//重载基类粒子系统的相应函数。 //初始化粒子数量。 virtualboolinitWithTotalParticles(unsignedintnumberOfParticles); //设置所用的纹理对象指针 virtualvoIDsetTexture(CCTexture2D*texture); //上一篇留下的疑问,虽然明显是更新粒子顶点缓冲中的位置数据。但上一篇为什么没有实现? voIDupdateQuaDWithParticle(tCCParticle*particle,153); Font-weight:bold; background-color:inherit">constCCPoint&newposition); //上一篇留下的疑问,不知道是做什么,咱们到CPP中看吧。 voIDpoststep(); //渲染处理。 voIDdraw(); //设置批次结点。 voIDsetBatchNode(CCParticleBatchNode*batchNode); //设置总的粒子数量。 voIDsetTotalParticles(unsignedinttp); //监听响应当前结点的EVNET_COME_TO_FOREGROUND事件的回调函数。 voIDListenBackToForeground(CCObject*obj); //创建一个当前实例结点,内部调用create实现。 CC_DEPRECATED_ATTRIBUTEstaticCCParticleSystemQuad*node(); //上面的create实现。 staticCCParticleSystemQuad*create(); private: //如果使用VAO #ifCC_TEXTURE_ATLAS_USE_VAO //初始化VAO和VBO voIDsetupVBOandVAO(); #else //初始化VBO voIDsetupVBO(); #endif //申请内存。 boolallocmemory(); };对应的实现:
copy //重载粒子系统基类的初始化函数,创建相应数量的粒子。 boolCCParticleSystemQuad::initWithTotalParticles(unsignedintnumberOfParticles) { //调用基类的相应函数。 if(CCParticleSystem::initWithTotalParticles(numberOfParticles)) //创建顶点和索引缓冲,如果失败释放并返回。 if(!this->allocmemory()){ this->release(); returnfalse; } //填充索引缓冲。 setupIndices(); //如果当前OPENGL版本支持VAO,就创建VAO,如果不支持,只创建VBO。 setupVBOandVAO(); #else setupVBO(); //设置使用顶点格式为“位置+纹理+顶点色”的顶点格式组合。 setShaderProgram(CCshadercache::sharedshadercache()->programForKey(kCCShader_positionTexturecolor)); //告诉通知中心,注册函数ListenBackToForeground用来响应当前结点的EVNET_COME_TO_FOREGROUND事件。这个事件的意义是程序将由后面返回到前台。这个事件响应时可做资源的重新载入。 CCNotificationCenter::sharednotificationCenter()->addobserver(this, callfuncO_selector(CCParticleSystemQuad::ListenBackToForeground), EVNET_COME_TO_FOREGROUND, NulL); true; //构造函数。 CCParticleSystemQuad::CCParticleSystemQuad() :m_pQuads(NulL) ,m_pIndices(NulL) memset(m_pBuffersVBO,sizeof(m_pBuffersVBO)); //析构函数。 CCParticleSystemQuad::~CCParticleSystemQuad() //对所创建的顶点缓冲,索引缓冲,以及VBO,VA0进行释放。 if(NulL==m_pBatchNode) CC_SAFE_FREE(m_pQuads); CC_SAFE_FREE(m_pIndices); glDeleteBuffers(2,&m_pBuffersVBO[0]); glDeleteVertexArrays(1,&m_uVAOname); } //注销对通知管理器注册的相应事件的响应处理函数。 CCNotificationCenter::sharednotificationCenter()->removeObserver( CCParticleSystemQuad*CCParticleSystemQuad::particleWithfile(char*pListfile) returnCCParticleSystemQuad::create(pListfile); CCParticleSystemQuad*CCParticleSystemQuad::create(char*pListfile) //创建一个CCParticleSystemQuad实例对象,进行初始化后交由内存管理器进行引用计数器的管理。 CCParticleSystemQuad*pRet=newCCParticleSystemQuad(); if(pRet&&pRet->initWithfile(pListfile)) pRet->autorelease(); returnpRet; //如果失败,删除并置空,返回NulL。 CC_SAFE_DELETE(pRet); //初始化纹理坐标。 voIDCCParticleSystemQuad::initTexCoordsWithRect(constCCRect&pointRect) //创建出相应的矩形。 CCRectrect=CCRectMake( 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()); //默认使用的是批次结点,以批次结点的纹理对设置所用的图像区域矩形宽高。 GLfloatwIDe=(GLfloat)pointRect.size.wIDth; GLfloathigh=(GLfloat)pointRect.size.height; //如果使用单纹理对象,取得纹理的宽高。 if(m_pTexture) wIDe=(GLfloat)m_pTexture->getPixelsWIDe(); high=(GLfloat)m_pTexture->getPixelsHigh(); //此宏是为了解决精灵边缘黑线而做的纹理坐标的微调。 #ifCC_FIX_ARTIFACTS_BY_STRECHING_TEXEL GLfloatleft=(rect.origin.x*2+1)/(wIDe*2); GLfloatbottom=(rect.origin.y*2+1)/(high*2); GLfloatright=left+(rect.size.wIDth*2-2)/(wIDe*2); GLfloattop=bottom+(rect.size.height*2-2)/(high*2); GLfloatleft=rect.origin.x/wIDe; GLfloatbottom=rect.origin.y/high; GLfloatright=left+rect.size.wIDth/wIDe; GLfloattop=bottom+rect.size.height/high; //将top与bottom交换一下,因为在Cococs2d-x中坐标系Y轴是向上为正,这里处理一下后面可以做为顶点位置数据。 CC_SWAP(top,bottom,float); //根据是否使用批次结点来取得相应的矩形顶点缓冲数组。 ccV3F_C4B_T2F_Quad*quads=NulL; unsignedintstart=0,end=0; if(m_pBatchNode) {//如果使用批次结点,这里取得批次结点中所有粒子所对应的矩形顶点数组。 quads=m_pBatchNode->getTextureAtlas()->getQuads(); //取得起始和结束的粒子所对应的矩形索引。 start=m_uAtlasIndex; end=m_uAtlasIndex+m_uTotalParticles; else {//如果使用单纹理对象,则起始矩形索引就是0,结束矩形索引就是最大粒子数量。 quads=m_pQuads; start=0; end=m_uTotalParticles; //遍历所有的矩形顶点。 for(unsignedinti=start;i<end;i++) //设置四个顶点的纹理坐标。 quads[i].bl.texCoords.u=left; quads[i].bl.texCoords.v=bottom; quads[i].br.texCoords.u=right; quads[i].br.texCoords.v=bottom; quads[i].tl.texCoords.u=left; quads[i].tl.texCoords.v=top; quads[i].tr.texCoords.u=right; quads[i].tr.texCoords.v=top; voIDCCParticleSystemQuad::setTextureWithRect(CCTexture2D*texture,153); Font-weight:bold; background-color:inherit">constCCRect&rect) //如果当前尚无纹理对或者使用的纹理与参数指定的纹理不同。则设置使用参数指定的纹理。 if(!m_pTexture||texture->getname()!=m_pTexture->getname()) CCParticleSystem::setTexture(texture); //设置指定的矩形图像区域做为贴图计算粒子系统的纹理坐标. this->initTexCoordsWithRect(rect); //设置使用的纹理对象。 voIDCCParticleSystemQuad::setTexture(CCTexture2D*texture) //取得纹理的大小。 constCCSize&s=texture->getContentSize(); this->setTextureWithRect(texture,CCRectMake(0,s.wIDth,s.height)); //设置使用精灵帧中的纹理。 voIDCCParticleSystemQuad::setdisplayFrame(CCSpriteFrame*spriteFrame) //有效性判断。 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"); //如果当前尚无纹理对或者使用的纹理与参数指定的纹理不同。则设置使用参数指定的纹理。 if(!m_pTexture||spriteFrame->getTexture()->getname()!=m_pTexture->getname()) //设置使用精灵帧中的纹理. this->setTexture(spriteFrame->getTexture()); voIDCCParticleSystemQuad::setupIndices() //遍历粒子数目计算索引缓冲值。 inti=0;i<m_uTotalParticles;++i) constunsignedinti6=i*6; inti4=i*4; m_pIndices[i6+0]=(glushort)i4+0; m_pIndices[i6+1]=(glushort)i4+1; m_pIndices[i6+2]=(glushort)i4+2; m_pIndices[i6+5]=(glushort)i4+1; m_pIndices[i6+4]=(glushort)i4+2; m_pIndices[i6+3]=(glushort)i4+3; //更新指定粒子的顶点缓冲中的位置数据。 voIDCCParticleSystemQuad::updateQuaDWithParticle(tCCParticle*particle,153); Font-weight:bold; background-color:inherit">constCCPoint&newposition) //定义临时指针变量用于取得相应的粒子所对应的矩形顶点缓冲。 ccV3F_C4B_T2F_Quad*quad; //如果使用了批次结点。 if(m_pBatchNode) //取得批次结点中对应的矩形顶点缓冲数组指针。 ccV3F_C4B_T2F_Quad*batchQuads=m_pBatchNode->getTextureAtlas()->getQuads(); //通过索引取得相应的矩形顶点缓冲。 quad=&(batchQuads[m_uAtlasIndex+particle->atlasIndex]); else //如果没有使用批次结点,直接取得相应的粒子的矩形顶点缓冲。 quad=&(m_pQuads[m_uParticleIDx]); //根据是否由Alpha值来设定RGB取得相应的颜色值。 cccolor4Bcolor=(m_bOpacityModifyRGB) ?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) :ccc4(particle->color.r*255,particle->color.g*255,particle->color.b*255,particle->color.a*255); //填真顶点缓冲中的颜色信息。 quad->bl.colors=color; quad->br.colors=color; quad->tl.colors=color; quad->tr.colors=color; //设置顶点的位置信息 GLfloatsize_2=particle->size/2; //判断是否进行旋转。 if(particle->rotation) //定义临时变量来存放以size_2为半径的矩形外圆上的四个顶点。 GLfloatx1=-size_2; GLfloaty1=-size_2; GLfloatx2=size_2; GLfloaty2=size_2; //定义临时变量来存放圆心。 GLfloatx=newposition.x; GLfloaty=newposition.y; //求得旋转角度。 GLfloatr=(GLfloat)-CC_degrees_TO_radians(particle->rotation); //通过sin,cos来计算旋转后的矩形外圆上的四个角的顶点位置。 GLfloatcr=cosf(r); GLfloatsr=sinf(r); GLfloatax=x1*cr-y1*sr+x; GLfloatay=x1*sr+y1*cr+y; GLfloatbx=x2*cr-y1*sr+x; GLfloatby=x2*sr+y1*cr+y; GLfloatcx=x2*cr-y2*sr+x; GLfloatcy=x2*sr+y2*cr+y; GLfloatdx=x1*cr-y2*sr+x; GLfloatdy=x1*sr+y2*cr+y; //填充计算旋转后的顶点位置信息。 quad->bl.vertices.x=ax; quad->bl.vertices.y=ay; quad->br.vertices.x=bx; quad->br.vertices.y=by; quad->tl.vertices.x=dx; quad->tl.vertices.y=dy; quad->tr.vertices.x=cx; quad->tr.vertices.y=cy; //如果不旋转,直接填充位置信息。 quad->bl.vertices.x=newposition.x-size_2; quad->bl.vertices.y=newposition.y-size_2; quad->br.vertices.x=newposition.x+size_2; quad->br.vertices.y=newposition.y-size_2; quad->tl.vertices.x=newposition.x-size_2; quad->tl.vertices.y=newposition.y+size_2; quad->tr.vertices.x=newposition.x+size_2; quad->tr.vertices.y=newposition.y+size_2; //我们一直想知道在CCParticleSystem中每次update时,如果粒子批次结点为空时为什么要调用poststep?它倒底是干什么的,看完下面的代码,就很清楚了。 voIDCCParticleSystemQuad::poststep() //绑定顶点缓冲区对象。 glBindBuffer(GL_ARRAY_BUFFER,m_pBuffersVBO[0]); //用m_pQuads中数据更新绑定的缓冲区数据。 glBufferSubData(GL_ARRAY_BUFFER,153); Font-weight:bold; background-color:inherit">sizeof(m_pQuads[0])*m_uParticleCount,m_pQuads); //取消绑定缓冲区对象。 CHECK_GL_ERROR_DEBUG(); //清楚了,原来这个函数是针对不使用批次结点时的VBO顶点缓冲的更新。 //绘制粒子系统。 voIDCCParticleSystemQuad::draw() //如果当前在粒子的批次结点有值,则draw()不应该被调用!为什么呢?因为有批次结点的话,渲染交给批次结点的draw()函数而不是当前粒子系统的draw()函数来处理。 CCAssert(!m_pBatchNode,"drawshouldnotbecalleDWhenaddedtoaparticleBatchNode"); //使用相应的Shader CC_NODE_DRAW_SETUP(); //绑定所用的纹理对象。 ccGLBindTexture2D(m_pTexture->getname()); //设定所用的Alpha混合方案。 ccGLBlendFunc(m_tBlendFunc.src,m_tBlendFunc.dst); //判断当前粒子索引是否为粒子总数,也就是判断是否已经update完成未出错。 CCAssert(m_uParticleIDx==m_uParticleCount,"Abnormalerrorinparticlequad"); //如果使用VAO。 //使用VAO绑定的顶点数组 glBindVertexArray(m_uVAOname); //绑定索引数组 #ifCC_REBIND_INDICES_BUFFER glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,m_pBuffersVBO[1]); //渲染调用 glDrawElements(GL_TRIANGLES,(GLsizei)m_uParticleIDx*6,GL_UNSIGNED_SHORT,0); //渲染完取消绑定索引数组 //取消绑定顶点数组 glBindVertexArray(0); // //UsingVBOwithoutVAO // #definekQuadSizesizeof(m_pQuads[0].bl) //设置使用相应的顶点格式为:位置+颜色+纹理坐标 ccGLEnabLevertexAttribs(kCCVertexAttribFlag_PoscolorTex); //绑定顶点缓冲 //设置顶点缓冲中位置数据的描述 glVertexAttribPointer(kCCVertexAttrib_position,3,GL_float,GL_FALSE,kQuadSize,(GLvoID*)offsetof(ccV3F_C4B_T2F,vertices)); //设置顶点缓冲中颜色数据的描述 glVertexAttribPointer(kCCVertexAttrib_color,4,GL_UNSIGNED_BYTE,GL_TRUE,colors)); //设置顶点缓冲中纹理坐标数据的描述 glVertexAttribPointer(kCCVertexAttrib_TexCoords,2,texCoords)); //绑定索引缓冲 //渲染调用 glDrawElements(GL_TRIANGLES,0); background-color:inherit">//取消绑定 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); background-color:inherit">//渲染调用计数器加一 CC_INCREMENT_GL_DRAWS(1); CHECK_GL_ERROR_DEBUG(); //设置粒子数量 voIDCCParticleSystemQuad::setTotalParticles(unsignedinttp) //如果要申请内存的粒子数量大于之前已经申请内存的粒子数量。 if(tp>m_uAllocatedParticles) //计算要申请的内存大小。 //粒子信息结构数组大小。 size_tparticlesSize=tP*sizeof(tCCParticle); //顶点缓冲的大小 size_tquadsSize=sizeof(m_pQuads[0])*tP*1; //索引缓冲的大小 size_tindicesSize=sizeof(m_pIndices[0])*tP*6*1; //在m_pParticles指定的内存位置申请相应大小的内存用于存储粒子信息结构数组。 tCCParticle*particlesNew=(tCCParticle*)realloc(m_pParticles,particlesSize); //在m_pQuads指定的内存位置申请相应大小的内存用于填充顶点缓冲。 ccV3F_C4B_T2F_Quad*quadsNew=(ccV3F_C4B_T2F_Quad*)realloc(m_pQuads,quadsSize); //在m_pIndices指定的内存位置申请相应大小的内存用于填充索引缓冲。 glushort*indicesNew=(glushort*)realloc(m_pIndices,indicesSize); //如果申请都成功。 if(particlesNew&&quadsNew&&indicesNew) //将内存地址传值给成员指针。 m_pParticles=particlesNew; m_pQuads=quadsNew; m_pIndices=indicesNew; //内存清零 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); memset(m_pIndices,0); background-color:inherit">//记录申请内存的粒子数量。 m_uAllocatedParticles=tp; //如果失败,记录成功申请的内存地址打印出错LOG。 if(particlesNew)m_pParticles=particlesNew; if(quadsNew)m_pQuads=quadsNew; if(indicesNew)m_pIndices=indicesNew; cclOG("Particlesystem:outofmemory"); return; //更新粒子数量。 m_uTotalParticles=tp; //根据是否使用批次结点来设定每个粒子对应的矩形顶点块的索引。 inti=0;i<m_uTotalParticles;i++) m_pParticles[i].atlasIndex=i; //填充索引缓冲。 setupIndices(); //初始化VAO setupVBOandVAO(); //如果要申请内存的粒子数量小于原来申请的粒子数量,直接修改一下最大粒子数量就OK。 m_uTotalParticles=tp; //如果当前OPENGL版本支持VAO。 //初始化VBO与VAO voIDCCParticleSystemQuad::setupVBOandVAO() //初始化1个顶点数组对象,产生VAO对象的句柄 glGenVertexArrays(1,0); background-color:inherit">//绑定VAO。 glBindVertexArray(m_uVAOname); //创建2个VBO缓冲区对象,产生两个句柄填充到句柄数组中。 glGenBuffers(2,0); background-color:inherit">//绑定第一个VBO缓冲区对象。 //将顶点数据拷贝到绑定的缓冲区。 glBufferData(GL_ARRAY_BUFFER,153); Font-weight:bold; background-color:inherit">sizeof(m_pQuads[0])*m_uTotalParticles,m_pQuads,GL_DYNAMIC_DRAW); //设置使用位置数据 glEnabLevertexAttribarray(kCCVertexAttrib_position); //设置位置数据在顶点缓冲中的描述 glVertexAttribPointer(kCCVertexAttrib_position,vertices)); //设置使用颜色数据 glEnabLevertexAttribarray(kCCVertexAttrib_color); //设置颜色数据在顶点缓冲中的描述 //设置使用纹理坐标数据 glEnabLevertexAttribarray(kCCVertexAttrib_TexCoords); //设置纹理坐标数据在顶点缓冲中的描述 glVertexAttribPointer(kCCVertexAttrib_TexCoords,texCoords)); //绑定VBO的第二个缓冲区 //将索引缓冲区数据拷贝到绑定的缓冲区 glBufferData(GL_ELEMENT_ARRAY_BUFFER,153); Font-weight:bold; background-color:inherit">sizeof(m_pIndices[0])*m_uTotalParticles*6,m_pIndices,GL_STATIC_DRAW); glBindVertexArray(0); //否则只使用VBO voIDCCParticleSystemQuad::setupVBO() //创建2个VBO缓冲区对象,产生两个句柄填充到句柄数组中。 glGenBuffers(2,&m_pBuffersVBO[0]); //绑定第一个VBO缓冲区对象并填充数据。 glBindBuffer(GL_ARRAY_BUFFER,m_pBuffersVBO[0]); //绑定第二个VBO缓冲区对象并填充数据。 //响应当前结点的EVNET_COME_TO_FOREGROUND事件。这个事件的意义是程序将由后面返回到前台。这个事件响应时可做资源的重新载入。 voIDCCParticleSystemQuad::ListenBackToForeground(CCObject*obj) //重新初始化VBO和VAO。 //创建顶点缓冲和索引缓冲区。 boolCCParticleSystemQuad::allocmemory() //如果已经申请则中断。 CCAssert((!m_pQuads&&!m_pIndices),"Memoryalreadyalloced"); CCAssert(!m_pBatchNode,"MemoryshouldnotbealloceDWhennotusingbatchNode"); //释放顶点与索引缓冲 //为顶点与索引缓冲申请内存。 m_pQuads=(ccV3F_C4B_T2F_Quad*)malloc(m_uTotalParticles*sizeof(ccV3F_C4B_T2F_Quad)); m_pIndices=(glushort*)malloc(m_uTotalParticles*6*sizeof(glushort)); //如果出现失败,则提示LOG并释放置空返回。 if(!m_pQuads||!m_pIndices) cclOG("cocos2d:Particlesystem:notenoughmemory"); CC_SAFE_FREE(m_pQuads); CC_SAFE_FREE(m_pIndices); //如果成功,置零 *** 作返回true. //设置CCParticleSystemQuad使用的粒子批次结点。 voIDCCParticleSystemQuad::setBatchNode(CCParticleBatchNode*batchNode) //如果当前使用的粒子批次结点与参数不同,则进行更换处理。 if(m_pBatchNode!=batchNode) //先记录一下当前使用的。 CCParticleBatchNode*oldBatch=m_pBatchNode; //将后调用基类相应函数,设置当前使用的粒子批次结点。 CCParticleSystem::setBatchNode(batchNode); //如果参数值为空,代表不使用批次结点。则进行顶点缓冲的相关初始化。 if(!batchNode) //创建顶点缓冲,填充索引,并根据是否可用VAO设置顶点缓冲,设置纹理。 allocmemory(); setTexture(oldBatch->getTexture()); setupVBO(); //如果批次结点有效,且更换前没有使用粒子批次结点。 elseif(!oldBatch) //取得相应粒子批次结点的矩形数组,取出相应索引位置的矩形数据,将相应的顶点缓冲数据拷到矩形数组中。 ccV3F_C4B_T2F_Quad*quad=&(batchQuads[m_uAtlasIndex]); memcpy(quad,153); Font-weight:bold; background-color:inherit">sizeof(m_pQuads[0])); //释放当前用的顶点缓冲 //释放所用的VBO顶点对象与AVO名称 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); //创建一个CCParticleSystemQuad,内部调用create实现。 CCParticleSystemQuad*CCParticleSystemQuad::node() returnCCParticleSystemQuad::create(); CCParticleSystemQuad*CCParticleSystemQuad::create(){ //创建一个CCParticleSystemQuad的实例对象。 CCParticleSystemQuad*pParticleSystemQuad=newCCParticleSystemQuad(); //如果创建成功,进行初始化。成功后交由内存管理器进行引用计数器的管理。 if(pParticleSystemQuad&&pParticleSystemQuad->init()) pParticleSystemQuad->autorelease(); returnpParticleSystemQuad; //如果失败,释放置空并返回NulL。 CC_SAFE_DELETE(pParticleSystemQuad); returnNulL; }
总结: 类CCParticleSystemQuad的源码进一步完善了粒子系统的功能,使我们可以在不需要批次结点时也能够实现粒子系统的OPENGL顶点和索引缓冲的创建和渲染,这么看来CCParticleSystem是一个不完整的粒子系统的类,它只提供了使用粒子批次结点的粒子系统的渲染方案。
到这里,我们基本算领悟了Cocos2d-x中粒子系统的完整功能基类。后面我们将由此进入到多彩的粒子系统的演示中去!下课~
总结以上是内存溢出为你收集整理的Cocos2d-x2.0 粒子系统深入分析三部曲(二)全部内容,希望文章能够帮你解决Cocos2d-x2.0 粒子系统深入分析三部曲(二)所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)