CCGrid(CCGridBase CCGrid3D CCTiledGrid3D CCGridBase)


网格的的数据和渲染基类CCGridBase及其派生CCGrid3DCCTiledGrid3DCCGridBase的关键是处理了将屏幕渲染到纹理这个功能。 
它有两个重要的函数: 
//在渲染之前要做的处理。 
voidbeforeDraw(void); 
//在渲染之后要做的处理。 
voidafterDraw(CCNode *pTarget); 
每个CCNode有一个CCGridBase类型的成员指针变量。在其cpp的visit中调用。
<span style="color:#ff0000;">void CCNode::visit()
{
    if (!m_bIsVisible)
    {
        return;
    }
     kmGLPushMatrix();

     //如果m_pGrid有值并且被激活则开启渲染到纹理。
     if (m_pGrid && m_pGrid->isActive())
     {
         m_pGrid->beforeDraw();
 }

 //相应结点的渲染处理。
 …
    //如果m_pGrid有值并且被激活则关闭渲染到纹理,这样当前结点上所有绘制的图像都被输出到m_pGrid中对应的纹理中了。
     if (m_pGrid && m_pGrid->isActive())
     {
         m_pGrid->afterDraw(this);
    }
 
    kmGLPopMatrix();
}
</span>

CCGrid3D是一个基本的网格渲染类,他内部有所需要的顶点缓冲区。可以实现带纹理贴图的网格渲染功能。 
CCTiledGrid3D比较有趣,它与CCGrid3D的不同之处是它的网格不是由一个个顶点构成,而是由一个个四边形构成,CCGrid3D所表现的是网格各顶点的动画,而CCTiledGrid3D是表现每个格子中的四边形的动画。 





#ifndef __EFFECTS_CCGRID_H__

#define __EFFECTS_CCGRID_H__


#include "cocoa/CCObject.h"

#include "base_nodes/CCNode.h"

#include "CCCamera.h"

#include "ccTypes.h"

#include "textures/CCTexture2D.h"

#include "CCDirector.h"

#include "kazmath/mat4.h"

#ifdef EMSCRIPTEN

#include "base_nodes/CCGLBufferedNode.h"

#endif // EMSCRIPTEN


NS_CC_BEGIN


class CCTexture2D;

class CCGrabber;

class CCGLProgram;


/** Base class for other

*/

class CC_DLL CCGridBase : public CCObject

{

public:

    virtual ~CCGridBase(void);


  //网格是否激活

    inline bool isActive(void) { return m_bActive; }

//设置网格是否激活

    void setActive(bool bActive);


<span style="color:#ff0000;">//设置激活。
void CCGridBase::setActive(bool bActive)
{
	//保存激活设置
    m_bActive = bActive;
    if (! bActive)
{
	 //如果未激活,复原投影矩阵。
        CCDirector *pDirector = CCDirector::sharedDirector();
        ccDirectorProjection proj = pDirector->getProjection();
        pDirector->setProjection(proj);
    }
}</span>


//网格将被复用的次数

    inline int getReuseGrid(void) { return m_nReuseGrid; }

//设置网格将被复用的次数

    inline void setReuseGrid(int nReuseGrid) { m_nReuseGrid = nReuseGrid; }


//网格大小

    inline const CCSize& getGridSize(void) { return m_sGridSize; }

//设置网格大小

    inline void setGridSize(const CCSize& gridSize) { m_sGridSize = gridSize; }


    /** pixels between the grids */

//-----------格子占用像素点数??

    inline const CCPoint& getStep(void) { return m_obStep; }

    inline void setStep(const CCPoint& step) { m_obStep = step; }


 //纹理翻转

    inline bool isTextureFlipped(void) { return m_bIsTextureFlipped; }

    void setTextureFlipped(bool bFlipped);


//初始化 1、格子大小 2、纹理指针 3、是否翻转纹理

    bool initWithSize(const CCSize& gridSize, CCTexture2D *pTexture, bool bFlipped);

//初始化函数。

bool CCGridBase::initWithSize(const ccGridSize& gridSize, CCTexture2D *pTexture, bool bFlipped)

{

    bool bRet = true;

//未激活。

m_bActive = false;

<span style="color:#ff0000;">m_nReuseGrid = 0;
//保存格子大小。
    m_sGridSize = gridSize;
	//保存纹理。
m_pTexture = pTexture;
//占用纹理,对其引用计数器加一操作。
CC_SAFE_RETAIN(m_pTexture);
//保存是否进行纹理反转的变量。
    m_bIsTextureFlipped = bFlipped;
	//取得纹理中的图像大小。
const CCSize& texSize = m_pTexture->getContentSize();
//计算出一个格子所占的纹理寻址长度。
    m_obStep.x = texSize.width / m_sGridSize.x;
    m_obStep.y = texSize.height / m_sGridSize.y;
	//新建一个屏幕图像获取器,这家伙是干嘛的?其实就是一个获取屏幕图像的类,可以将屏幕上渲染出的图像输出到一张指定的纹理中,类似DX中的RTT。

    m_pGrabber = new CCGrabber();
    if (m_pGrabber)
{
	 //将纹理设置为输出纹理。
        m_pGrabber->grab(m_pTexture);
    }
    else
{
	 //如果图像获取器创建失败,做下返回值处理。
        bRet = false;
    }
    //取得对应的Shader代码片段。
m_pShaderProgram = CCShaderCache::sharedShaderCache()->programForKey(kCCShader_PositionTexture);
//计算所要用到的顶点数据并创建顶点缓冲区。
    calculateVertexPoints();

    return bRet;
}</span>

    bool initWithSize(const CCSize& gridSize);


<span style="color:#ff0000;">bool CCGridBase::initWithSize(const ccGridSize& gridSize)
{
	//取得设备指针,并通过它取得屏幕大小。
    CCDirector *pDirector = CCDirector::sharedDirector();
    CCSize s = pDirector->getWinSizeInPixels();
    //计算相应大小对应的2次幂大小。
    unsigned long POTWide = ccNextPOT((unsigned int)s.width);
    unsigned long POTHigh = ccNextPOT((unsigned int)s.height);

    // 使用ARGB8888格式。
    CCTexture2DPixelFormat format = kCCTexture2DPixelFormat_RGBA8888;
	//创建相应的像素绘冲区。
    void *data = calloc((int)(POTWide * POTHigh * 4), 1);
    if (! data)
    {
        CCLOG("cocos2d: CCGrid: not enough memory.");
        this->release();
        return false;
}

	//创建一个纹理。
CCTexture2D *pTexture = new CCTexture2D();
//使用像素数据初始化纹理。
    pTexture->initWithData(data, format, POTWide, POTHigh, s);
    //释放像素数据。
    free(data);
	//如果失败,返回false。
    if (! pTexture)
    {
        CCLOG("cocos2d: CCGrid: error creating texture");
        delete this;
        return false;
    }
	//使用创建的纹理初始化
    initWithSize(gridSize, pTexture, false);
	//释放纹理。
pTexture->release();

    return true;
}</span>




    void beforeDraw(void);

<span style="color:#ff0000;">//在开始渲染前的处理。
void CCGridBase::beforeDraw(void)
{
    // 先取得当前的投影矩阵保存到变量中
    CCDirector *director = CCDirector::sharedDirector();
    m_directorProjection = director->getProjection();

    // 设置新的投影矩阵。
set2DProjection();
// 设置开启屏幕渲染到纹理。
    m_pGrabber->beforeRender(m_pTexture);
}</span>


    void afterDraw(CCNode *pTarget);

<span style="color:#ff0000;">//在渲染结束后的处理。
void CCGridBase::afterDraw(cocos2d::CCNode *pTarget)
{
	//设置完成屏幕渲染到纹理。
    m_pGrabber->afterRender(m_pTexture);

    //恢复原投影矩阵。
    CCDirector *director = CCDirector::sharedDirector();
    director->setProjection(m_directorProjection);
	//
    if (pTarget->getCamera()->isDirty())
{
	 //取得演示的锚点做为摄像机的矩阵转换中心点。
        const CCPoint& offset = pTarget->getAnchorPointInPoints();

		//注意:下面三句的意义是对摄像机进行矩阵变换,这个矩阵变换是相对于自身中心点位置,俗称自身矩阵变换。
        //先将当前模型矩阵偏移到这个中心点。
        kmGLTranslatef(offset.x, offset.y, 0);
		 //进行本地矩阵的转换
        pTarget->getCamera()->locate();
		 //恢复原位置。
        kmGLTranslatef(-offset.x, -offset.y, 0);
		
    }
	//设置使用纹理。
    ccGLBindTexture2D(m_pTexture->getName());

    // restore projection for default FBO .fixed bug #543 #544
//TODO:         CCDirector::sharedDirector()->setProjection(CCDirector::sharedDirector()->getProjection());
//TODO:         CCDirector::sharedDirector()->applyOrientation();
	//进行渲染
    blit();
}</span><span style="color:#333333;">
</span>


    virtual void blit(void);//渲染

//进行渲染
void CCGridBase::blit(void)
{
    CCAssert(0, "");
}


    virtual void reuse(void);


<span style="color:#ff0000;">//还原到原来顶点位置。
void CCGridBase::reuse(void)
{
    CCAssert(0, "");
}</span>


    virtual void calculateVertexPoints(void); //计算顶点buffer

//计算顶点缓冲区。
void CCGridBase::calculateVertexPoints(void)
{
    CCAssert(0, "");
}


public:

//详细创建函数,参一为网格大小,参二为对应的纹理,参三为设置纹理是否反转。

static CCGridBase* create(const CCSize& gridSize, CCTexture2D *texture, bool flipped);

//简单创建函数,参数为网格大小

static CCGridBase* create(const CCSize& gridSize);

//设置2D投影矩阵

    void set2DProjection(void);

<span style="color:#ff0000;">//设置2D投影。
void CCGridBase::set2DProjection()
{
	//取得窗口大小
    CCDirector *director = CCDirector::sharedDirector();
    CCSize    size = director->getWinSizeInPixels();
	//重新设置视口大小
glViewport(0, 0, (GLsizei)(size.width * CC_CONTENT_SCALE_FACTOR()), (GLsizei)(size.height * CC_CONTENT_SCALE_FACTOR()) );
//开始设置投影矩阵。
kmGLMatrixMode(KM_GL_PROJECTION);
//先将投影矩阵单位化。
    kmGLLoadIdentity();
	//创建一个矩阵变量。
kmMat4 orthoMatrix;
//通过参数生成出投影矩阵变量的值,此处使用的是正交投影矩阵。
kmMat4OrthographicProjection(&orthoMatrix, 0, size.width * CC_CONTENT_SCALE_FACTOR(), 0, size.height * CC_CONTENT_SCALE_FACTOR(), -1, 1);
//将原单位化矩阵与正交投影矩阵相乘,当然还是正交投影矩阵了,做为投影矩阵的结果。
    kmGLMultMatrix( &orthoMatrix );
	//下面开始设置模型观察矩阵。
kmGLMatrixMode(KM_GL_MODELVIEW);
//将矩阵单位化。
    kmGLLoadIdentity();

	//设置投影矩阵。
    ccSetProjectionMatrixDirty();
}</span>


protected:

    bool m_bActive;

    int  m_nReuseGrid;

    CCSize m_sGridSize;

    CCTexture2D *m_pTexture;

    CCPoint m_obStep;

    CCGrabber *m_pGrabber;  //将屏幕画面渲染到纹理的处理器。

    bool m_bIsTextureFlipped;

    CCGLProgram* m_pShaderProgram;

    ccDirectorProjection m_directorProjection;//投影方式

};


/**

 CCGrid3D is a 3D grid implementation(实现). Each vertex(顶点) has 3 dimensions(规模 大小): x,y,z

 */

class CC_DLL CCGrid3D : public CCGridBase

#ifdef EMSCRIPTEN

, public CCGLBufferedNode

#endif // EMSCRIPTEN

{

public:

    CCGrid3D();

    ~CCGrid3D(void);  


//返回对应位置的顶点
    ccVertex3F vertex(const CCPoint& pos);

<span style="color:#ff0000;">ccVertex3F CCGrid3D::vertex(const ccGridSize& pos)</span><span style="color:#3333ff;background-color: rgb(255, 255, 255);">->版本问题 无视参数</span><span style="color:#ff0000;">
{
	//通过网格位置计算出起始顶点的索引。
int index = (pos.x * (m_sGridSize.y+1) + pos.y) * 3;
//为方便获取顶点数据,将顶点缓冲地址转换为相应的指针变量。
    float *vertArray = (float*)m_pVertices;
	//通过索引取得相应的顶点x,y,z。
    ccVertex3F vert = {vertArray[index], vertArray[index+1], vertArray[index+2]};
	//返回顶点
    return vert;
}</span>

    /** returns the original (non-transformed) vertex at a given position */

//返回原始顶点

    ccVertex3F originalVertex(const CCPoint& pos);

<span style="color:#ff0000;">ccVertex3F CCGrid3D::originalVertex(const ccGridSize& pos)
{
	//通过格子位置计算出起始顶点的索引。
    int index = (pos.x * (m_sGridSize.y+1) + pos.y) * 3;
 //为方便获取顶点数据,将顶点缓冲地址转换为相应的指针变量。
float *vertArray = (float*)m_pOriginalVertices;
	//通过索引取得相应的顶点x,y,z。
    ccVertex3F vert = {vertArray[index], vertArray[index+1], vertArray[index+2]};
	//返回顶点
    return vert;
}</span>

    /** sets a new vertex at a given position */

//设置对应网格位置的顶点

    void setVertex(const CCPoint& pos, const ccVertex3F& vertex);

<span style="color:#ff0000;">void CCGrid3D::setVertex(const ccGridSize& pos, const ccVertex3F& vertex)
{	//通过格子位置计算出起始顶点的索引。
int index = (pos.x * (m_sGridSize.y + 1) + pos.y) * 3;
//为方便获取顶点数据,将顶点缓冲地址转换为相应的指针变量。
float *vertArray = (float*)m_pVertices;
设置对应索引位置的顶点的x,y,z。
    vertArray[index] = vertex.x;
    vertArray[index+1] = vertex.y;
    vertArray[index+2] = vertex.z;
}</span>


//实现基类虚函数

    virtual void blit(void);

<span style="color:#ff0000;">//进行渲染处理
void CCGrid3D::blit(void)
{
	//计算格子的数量
    int n = m_sGridSize.x * m_sGridSize.y;

    //设置渲染顶点的格式
ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position | kCCVertexAttribFlag_TexCoords );
//开启使用Shader
m_pShaderProgram->use();
//设置Shader中的 顶点矩阵,其值 = 投影矩阵X模型矩阵X观察矩阵的结果,用于在Shader中进行顶点的最终位置计算。
    m_pShaderProgram->setUniformForModelViewProjectionMatrix();;


    //顶点缓冲中位置属性的指定。
    glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, 0, m_pVertices);

    //顶点缓冲中纹理贴图UV属性的指定。
    glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, 0, m_pTexCoordinates);

	//绘制三角形,每个格子两个三角形,使用GL_TRIANGLES方式进行绘制,则每个格子需要6个顶点。所以顶点数为n*6,渲染时按照索引绘冲m_pIndices所指定的三角形顶点索引来进行绘制。
glDrawElements(GL_TRIANGLES, (GLsizei) n*6, GL_UNSIGNED_SHORT, m_pIndices);
//增加一次DP统计值。
    CC_INCREMENT_GL_DRAWS(1);
}</span>

    virtual void reuse(void);

<span style="color:#ff0000;">//还原原来位置。
void CCGrid3D::reuse(void)
{
	//如果还原格子的变量大于0。
    if (m_nReuseGrid > 0)
{
	 //将原始顶点位置拷贝到顶点缓冲中。
        memcpy(m_pOriginalVertices, m_pVertices, (m_sGridSize.x+1) * (m_sGridSize.y+1) * sizeof(ccVertex3F));
		//还原格子的变量做减1操作。
        --m_nReuseGrid;
    }
}</span>

  virtual void calculateVertexPoints(void);

<span style="color:#ff0000;">void CCGrid3D::calculateVertexPoints(void)
{
	//取得纹理的宽高。
    float width = (float)m_pTexture->getPixelsWide();
float height = (float)m_pTexture->getPixelsHigh();
//取得纹理中图像区域的高度。
    float imageH = m_pTexture->getContentSizeInPixels().height;

	//定义临时变量。
int x, y, i;
//如果相应的顶点缓冲数据有值,先释放干净并置空。
    CC_SAFE_FREE(m_pVertices);
    CC_SAFE_FREE(m_pOriginalVertices);
    CC_SAFE_FREE(m_pTexCoordinates);
    CC_SAFE_FREE(m_pIndices);
	//计算总顶点数,每一行的顶点数为格子列数+1,每一列的顶点数为格子行数+1。
    unsigned int numOfPoints = (m_sGridSize.x+1) * (m_sGridSize.y+1);
	//为相应的顶点缓冲区申请相应大小的内存。
	//m_pVertices中存入的是顶点位置,使用ccVertex3F来存储。所申请的内存大小即为顶点数乘以ccVertex3F的字节数大小。
m_pVertices = malloc(numOfPoints * sizeof(ccVertex3F));
//同上。
m_pOriginalVertices = malloc(numOfPoints * sizeof(ccVertex3F));
//纹理UV使用ccVertex2F来存储。
m_pTexCoordinates = malloc(numOfPoints * sizeof(ccVertex2F));
//索引缓冲m_pIndices使用GLushort来存储绘制三角形所用的顶点的索引值,因为每个面3个索引,一个格子就需要6个索引。
    m_pIndices = (GLushort*)malloc(m_sGridSize.x * m_sGridSize.y * sizeof(GLushort) * 6);
	
	//为了方便填充数据,将缓冲区地址转换成相应的指针变量。
    GLfloat *vertArray = (GLfloat*)m_pVertices;
    GLfloat *texArray = (GLfloat*)m_pTexCoordinates;
    GLushort *idxArray = m_pIndices;

	//双循环遍历每个格子。
    for (x = 0; x < m_sGridSize.x; ++x)
    {
        for (y = 0; y < m_sGridSize.y; ++y)
        {
			 //取得格子索引。
            int idx = (y * m_sGridSize.x) + x;

			 //取得格子的左上角和右下角在图像中的相应位置。m_obStep是每个格子占用的图像点数。
            GLfloat x1 = x * m_obStep.x;
            GLfloat x2 = x1 + m_obStep.x;
            GLfloat y1 = y * m_obStep.y;
            GLfloat y2= y1 + m_obStep.y;

			 //取得格子的四个顶点的索引。
            GLushort a = (GLushort)(x * (m_sGridSize.y + 1) + y);
            GLushort b = (GLushort)((x + 1) * (m_sGridSize.y + 1) + y);
            GLushort c = (GLushort)((x + 1) * (m_sGridSize.y + 1) + (y + 1));
            GLushort d = (GLushort)(x * (m_sGridSize.y + 1) + (y + 1));

			 //按照三角形的绘制方式将格子顶点的索引组成两个三角形的顶点索引。
            GLushort tempidx[6] = {a, b, d, b, c, d};

			 //填充到相应的索引缓冲中。
            memcpy(&idxArray[6*idx], tempidx, 6*sizeof(GLushort));

			  //格子四个顶点的位置。
            int l1[4] = {a*3, b*3, c*3, d*3};
            ccVertex3F e = {x1, y1, 0};
            ccVertex3F f = {x2, y1, 0};
            ccVertex3F g = {x2, y2, 0};
            ccVertex3F h = {x1, y2, 0};

            ccVertex3F l2[4] = {e, f, g, h};

            int tex1[4] = {a*2, b*2, c*2, d*2};
            CCPoint tex2[4] = {ccp(x1, y1), ccp(x2, y1), ccp(x2, y2), ccp(x1, y2)};
			 //遍历放入相应的顶点位置和纹理UV中。
            for (i = 0; i < 4; ++i)
            {
				  //顶点的x,y,z
                vertArray[l1[i]] = l2[i].x;
                vertArray[l1[i] + 1] = l2[i].y;
                vertArray[l1[i] + 2] = l2[i].z;

				  //纹理U值
                texArray[tex1[i]] = tex2[i].x / width;
				  //纹理V值
                if (m_bIsTextureFlipped)
                {
					  //上下反转
                    texArray[tex1[i] + 1] = (imageH - tex2[i].y) / height;
                }
                else
                {
					  //正常
                    texArray[tex1[i] + 1] = tex2[i].y / height;
                }
            }
        }
    }
	//将顶点位置数据填充到保存原始顶点位置的内存中。
    memcpy(m_pOriginalVertices, m_pVertices, (m_sGridSize.x+1) * (m_sGridSize.y+1) * sizeof(ccVertex3F));
}</span>

public:

    /** create one Grid */

//创建3d网格

    static CCGrid3D* create(const CCSize& gridSize, CCTexture2D *pTexture, bool bFlipped);

    /** create one Grid */

    static CCGrid3D* create(const CCSize& gridSize);

    

protected:

    GLvoid *m_pTexCoordinates;//顶点缓冲指针_纹理UV

    GLvoid *m_pVertices;//顶点缓冲指针_位置

    GLvoid *m_pOriginalVertices;//原始顶点缓冲指针_位置

    GLushort *m_pIndices;//索引缓冲指针

};


/**

 CCTiledGrid3D is a 3D grid implementation(实现). It differs from Grid3D in that

 the tiles(瓦片) can be separated from(分离于。。) the grid.

*/

class CC_DLL CCTiledGrid3D : public CCGridBase //
//这也是一个网格类,但它在网格的每个位置点存的不是一个顶点,而是一个四边形格子。

#ifdef EMSCRIPTEN

, public CCGLBufferedNode

#endif // EMSCRIPTEN

{

public:

    CCTiledGrid3D();

    ~CCTiledGrid3D(void);


    /** returns the tile at the given position */

//返回相应位置的格子数据

    ccQuad3 tile(const CCPoint& pos);

    /** returns the original tile (untransformed) at the given position */

//返回原始位置的格子数据。

    ccQuad3 originalTile(const CCPoint& pos);

    /** sets a new tile */

<span style="color:#ff0000;">//设置相应位置的格子数据。</span>

  void setTile(const CCPoint& pos, const ccQuad3& coords);

<span style="color:#ff0000;">void CCTiledGrid3D::setTile(const ccGridSize& pos, const ccQuad3& coords)
{
	//先计算出对应格子的顶点索引
int idx = (m_sGridSize.y * pos.x + pos.y) * 4 * 3;
//为了方便填充数据,将缓冲区地址转换成相应的指针变量。
float *vertArray = (float*)m_pVertices;
//填充对应的数据
    memcpy(&vertArray[idx], &coords, sizeof(ccQuad3));
}</span>


    virtual void blit(void);

<span style="color:#ff0000;">void CCTiledGrid3D::blit(void)
{
	//取得格子的数量。
    int n = m_sGridSize.x * m_sGridSize.y;

    //开启使用shader片段
m_pShaderProgram->use();
//设置Shader中的 顶点矩阵,其值 = 投影矩阵X模型矩阵X观察矩阵的结果,用于在Shader中进行顶点的最终位置计算。
    m_pShaderProgram->setUniformForModelViewProjectionMatrix();
//设置顶点缓冲的结构,由位置和纹理坐构构成。
ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position | kCCVertexAttribFlag_TexCoords );
    //顶点缓冲中位置属性的指定       glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, 0, m_pVertices);
    //纹理坐标通道
    glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, 0, m_pTexCoordinates);
//绘制图形
    glDrawElements(GL_TRIANGLES, (GLsizei)n*6, GL_UNSIGNED_SHORT, m_pIndices);
	//更新DP统计
    CC_INCREMENT_GL_DRAWS(1);
}</span>

    virtual void reuse(void);

<span style="color:#ff0000;">void CCTiledGrid3D::reuse(void)
{
	//如果还原格子的变量大于0。
    if (m_nReuseGrid > 0)
    {
        int numQuads = m_sGridSize.x * m_sGridSize.y;
		//将原始顶点位置拷贝到顶点缓冲中。
        memcpy(m_pOriginalVertices, m_pVertices, numQuads * 12 * sizeof(GLfloat));
//还原格子的变量做减1操作。
        --m_nReuseGrid;
    }
}</span>


    virtual void calculateVertexPoints(void);

<span style="color:#ff0000;">//计算顶点缓冲的数据
void CCTiledGrid3D::calculateVertexPoints(void)
{
	//取得纹理的宽高
    float width = (float)m_pTexture->getPixelsWide();
float height = (float)m_pTexture->getPixelsHigh();
//取得纹理中图像区域的高度。
    float imageH = m_pTexture->getContentSizeInPixels().height;
    //定义临时变量。
    int numQuads = m_sGridSize.x * m_sGridSize.y;
//如果相应的顶点缓冲数据有值,先释放干净并置空。
 CC_SAFE_FREE(m_pVertices);
    CC_SAFE_FREE(m_pOriginalVertices);
    CC_SAFE_FREE(m_pTexCoordinates);
    CC_SAFE_FREE(m_pIndices);
//为相应的顶点缓冲区申请相应大小的内存。
    m_pVertices = malloc(numQuads*4*sizeof(ccVertex3F));
    m_pOriginalVertices = malloc(numQuads*4*sizeof(ccVertex3F));
    m_pTexCoordinates = malloc(numQuads*4*sizeof(ccVertex2F));
    m_pIndices = (GLushort*)malloc(numQuads*6*sizeof(GLushort));
	//为了方便填充数据,将缓冲区地址转换成相应的指针变量。
    GLfloat *vertArray = (GLfloat*)m_pVertices;
    GLfloat *texArray = (GLfloat*)m_pTexCoordinates;
    GLushort *idxArray = m_pIndices;
    
    int x, y;
    
   //双循环遍历每个格子。
    for (x = 0; x < m_sGridSize.x; ++x)
    {
        for (y = 0; y < m_sGridSize.y; ++y)
        {
			 //取得格子的左上角和右下角在图像中的位置。
            float x1 = x * m_obStep.x;
            float x2 = x1 + m_obStep.x;
            float y1 = y * m_obStep.y;
            float y2 = y1 + m_obStep.y;
            //填充数据
            *vertArray++ = x1;
            *vertArray++ = y1;
            *vertArray++ = 0;
            *vertArray++ = x2;
            *vertArray++ = y1;
            *vertArray++ = 0;
            *vertArray++ = x1;
            *vertArray++ = y2;
            *vertArray++ = 0;
            *vertArray++ = x2;
            *vertArray++ = y2;
            *vertArray++ = 0;
            
            float newY1 = y1;
            float newY2 = y2;
            //如果纹理V值上下反转,则做下处理。
            if (m_bIsTextureFlipped) 
            {
                newY1 = imageH - y1;
                newY2 = imageH - y2;
            }
			 //填充数据。
            *texArray++ = x1 / width;
            *texArray++ = newY1 / height;
            *texArray++ = x2 / width;
            *texArray++ = newY1 / height;
            *texArray++ = x1 / width;
            *texArray++ = newY2 / height;
            *texArray++ = x2 / width;
            *texArray++ = newY2 / height;
        }
    }
    //索引缓冲数据填充。
    for (x = 0; x < numQuads; x++)
    {
        idxArray[x*6+0] = (GLushort)(x * 4 + 0);
        idxArray[x*6+1] = (GLushort)(x * 4 + 1);
        idxArray[x*6+2] = (GLushort)(x * 4 + 2);
        
        idxArray[x*6+3] = (GLushort)(x * 4 + 1);
        idxArray[x*6+4] = (GLushort)(x * 4 + 2);
        idxArray[x*6+5] = (GLushort)(x * 4 + 3);
    }
    //填充原始位置顶点缓冲
    memcpy(m_pOriginalVertices, m_pVertices, numQuads * 12 * sizeof(GLfloat));
}</span>



public:


    /** create one Grid */

//创建格子

    static CCTiledGrid3D* create(const CCSize& gridSize, CCTexture2D *pTexture, bool bFlipped);

    /** create one Grid */

    static CCTiledGrid3D* create(const CCSize& gridSize);

    

protected:

//所要用到的顶点数据缓冲区。

    GLvoid *m_pTexCoordinates;

    GLvoid *m_pVertices;

    GLvoid *m_pOriginalVertices;

    GLushort *m_pIndices;

};

NS_CC_END


#endif // __EFFECTS_CCGRID_H__




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值