您的位置:首页 > 移动开发 > Cocos引擎

cocos2d-x 之 CCTextureAtlas 简介

2012-02-27 18:09 274 查看
CCTextureAtlas是一个大图绘制管理类。说白了,它本身保存一张大图的纹理和一个记录画大图某一区域的信息结构体的数组,通过操纵这个数组你可以绘制出一批四边形,这些四边形的纹理和绘制的坐标都存放在你操作的数组之中的(又把废话重复了一遍。)

由于CCTextureAtlas使用了opengl的VBO(顶点数组对象),所以用CCTextureAtlas所作的绘制在效率上比较高。

下面介绍一下该类的成员:

1.GLuint
m_pBuffersVBO[2],这是两个opengl VBO的句柄。一个用来做顶点数组句柄,一个用来做顶点索引数组句柄。

2.GLushort
*m_pIndices,这是一个顶点索引数组的类本地备份。

3 ccV3F_C4B_T2F_Quad *  m_pQuads ,这是一个顶点数组的类本地备份。这应该是CCTextureAtlas类实现的核心,所有该类的功能都再围绕该结构体在做操纵。

4. CCTexture2D  *m_pTexture,这是保存大图的纹理管理类。

5  int  m_uCapacity,四边形的容量。

6 int  m_uTotalQuads,实际上使用的四边形的数目。

7 m_bDirty ,当前opengl VBO中的数据是否是脏数据。为什么会存在这么一个类呢?实际上因为CCTextureAtlas容许你动态改变它管理的四边形数据,一旦你改变了该数据
就需要一个标志位告诉该类在绘制四边形的时候把VBO中得数据更新掉。该成员就是起这个作用。

该类的主要功能和实现介绍

初始化。

         该类的初始化需要提供的参数,除了需要加载的图片外还需要提供一个容量值。

初始化的流程:

 1.如果提供一个文件名作为纹理参数,则调用纹理缓冲的加载该图片,如果提供纹理则接着到下一步。

2 根据提供的容量nCapaciity,malloc分配nCapaciity大小
的ccV3F_C4B_T2F_Quad 数组,和6倍nCapaciity的容量的GLuint数组。

3 生成VBO。

4 初始化顶点索引数组。该操作在CCTextureAtlas::initIndices()中完成,特别注意索引初始化的顺序。

            代码如下:

  /*这段代码取自CCTextureAtlas::initIndices()
*四边形存储形式如图 : 0 — 2  opengl中绘图逆时针算正向绘制,所以正确顺序是0-1-2,3-2-1。
*		       |  / |
*/		       1 — 3
for( unsigned int i=0; i < m_uCapacity; i++)
{
#if CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP
m_pIndices[i*6+0] = i*4+0;
m_pIndices[i*6+1] = i*4+0;
m_pIndices[i*6+2] = i*4+2;
m_pIndices[i*6+3] = i*4+1;
m_pIndices[i*6+4] = i*4+3;
m_pIndices[i*6+5] = i*4+3;
#else
m_pIndices[i*6+0] = (GLushort)(i*4+0);
m_pIndices[i*6+1] = (GLushort)(i*4+1);
m_pIndices[i*6+2] = (GLushort)(i*4+2);

// inverted index. issue #179
m_pIndices[i*6+3] = (GLushort)(i*4+3);
m_pIndices[i*6+4] = (GLushort)(i*4+2);
m_pIndices[i*6+5] = (GLushort)(i*4+1);
//		m_pIndices[i*6+3] = i*4+2;
//		m_pIndices[i*6+4] = i*4+3;
//		m_pIndices[i*6+5] = i*4+1;
#endif
}
通过上面的代码我们很容易看出四边形是通过绘制两个三角形绘制出来的。
在这函数的结尾,将顶点数组和顶点索引数组导入到opengl中,下面这段代码就不解释了,如果你实在想知道,建议你看看opengl方面的书籍。

#if CC_USES_VBO
glBindBuffer(GL_ARRAY_BUFFER, m_pBuffersVBO[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(m_pQuads[0]) * m_uCapacity, m_pQuads, GL_DYNAMIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_pBuffersVBO[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(m_pIndices[0]) * m_uCapacity * 6, m_pIndices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
#endif // CC_USES_VBO

CCTextureAtlas绘制功能的实现是在这个函数中CCTextureAtlas::drawNumberOfQuads,里面大部分都是opengl的命令,比较令我感兴趣的是这句话:
if (m_bDirty)
{
glBufferSubData(GL_ARRAY_BUFFER, sizeof(m_pQuads[0]) * start, sizeof(m_pQuads[0]) * n, &m_pQuads[start]);
m_bDirty = false;
}这句话的作用就是之前说的。如果该类所管理的四边形信息结构体数组被外界改了,需要置位m_bDirty为true,这样在画的时候,就把相关的数据更新到opengl中。
CCTextureAtlas提供了增删改查m_pQuads的函数。值得一提的是CCTextureAtlas::resizeCapacity这个函数。

resizeCapacity会根据重置数组大小重新生成数组,然后它要重新生成那两个VBO(你知道,不知道看前面吧),然后初始化索引。

好了,打多了眼疼。就到这里吧
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  buffer 存储 c