2013-10-15 23 views
1

我有一個問題,我解決不了:創建索引和GL_TRIANGLES表面(只適用於頂點數據)

試圖繪製由方格(即有兩個三角形)的網格形成的面。

//m_totalVertices = m_rows*(m_cols *6) -> m_rows and m_cols are the quantity of columns and rows that build the surface 
glDrawArrays(GL_TRIANGLES, 0, m_totalVertices); 

爲例:

//first Quad 
Vertex[0] = -15,5; 
Vertex[1] = -5,5; 
Vertex[2] = -5,-5; 
Vertex[3] = -5,-5; 
Vertex[4] = -15,-5; 
Vertex[5] = -15,5; 
//second Quad 
Vertex[0] = -5,5; 
Vertex[1] = 5,5; 
Vertex[2] = 5,-5; 
Vertex[3] = 5,-5; 
Vertex[4] = -5,-5; 
Vertex[5] = -5,5; 
//third Quad 
Vertex[0] = 5,5; 
Vertex[1] = 15,5; 
Vertex[2] = 15,-5; 
Vertex[3] = 15,-5; 
Vertex[4] = 5,-5; 
Vertex[5] = 5,5; 

結果: enter image description here

作爲一個優化的事情,我想用「時,我只用了頂點數據,並繪製 一切正常索引「,以減少頂點數據的數量,但表面變形:

繪製它,即時通訊使用n分機功能:

//m_totalVertices = m_rows*(m_cols *6) -> m_rows and m_cols are the quantity of columns and rows that build the surface 
glDrawElements(GL_TRIANGLES, m_totalVertices, GL_UNSIGNED_INT, 0); 

例如:

//first Quad 
indices[0] = 0; 
indices[1] = 1; 
indices[2] = 2; 
indices[3] = 2; 
indices[4] = 3; 
indices[5] = 0; 
//second Quad 
indices[6] = 1; 
indices[7] = 4; 
indices[8] = 5; 
indices[9] = 5; 
indices[10] = 2; 
indices[11] = 1; 
//third Quad 
indices[12] = 4; 
indices[13] = 6; 
indices[14] = 7; 
indices[15] = 7; 
indices[16] = 5; 
indices[17] = 4; 

//first Quad 
Vertex[0] = -15,5; 
Vertex[1] = -5,5; 
Vertex[2] = -5,-5; 
Vertex[3] = -15,-5; 
//second Quad 
Vertex[0] = -5,5; 
Vertex[1] = 5,5; 
Vertex[2] = 5,-5; 
Vertex[3] = -5,-5; 
//third Quad 
Vertex[0] = 5,5; 
Vertex[1] = 15,5; 
Vertex[2] = 15,-5; 
Vertex[3] = 5,-5; 

結果: enter image description here

下面是隻用頂點數據(沒有索引)產生的表面的類的碼[WORKS PERFECT] :

#include "plane.h" 
#include "matrix.h" 
#include "glslshader.h" 
#include "texture.h" 

plane::plane(GLuint cols, GLuint rows,GLuint segmentSize, mixedColors color, CTexture* texture, GLshort textureMode) : 
m_matrix(0), 
m_shader(0), 
m_cols(cols), 
m_rows(rows), 
m_segmentSize(segmentSize), 
m_selectedColor(color), 
m_texture(texture), 
m_textureMode(textureMode), 
m_totalVertices(rows*(cols*6)) 
{ 
    //matrix handler 
    m_matrix = matrix::getInstance(); 

    //check that variables are > 1 
    if(m_cols < 1){m_cols = 1;} 
    if(m_rows < 1){m_rows = 1;} 

    // generate a VAO 
    glGenVertexArrays(1, &m_uiVAO); 

    vbo.createVBO(); 

} 

plane::~plane() 
{ 
    delete m_shader; 
    vbo.releaseVBO(); 

    glDeleteVertexArrays(1, &m_uiVAO); 
} 


bool plane::init() 
{ 
    //load the shaders 
    if(m_texture == NULL) 
    { 
     m_shader = new GLSLProgram("data/shaders/shader-primitives.vert", "data/shaders/shader-primitives.frag"); 
    } 
    else//if primitive use texture... 
     { 
      m_shader = new GLSLProgram("data/shaders/shader-texture.vert", "data/shaders/shader-texture.frag"); 
     } 

    if (!m_shader->initialize()) 
    { 
     cout << "Los shaders de las primitivas no pudieron ser incializados\n"; 
     return false; 
    } 
    m_shader->linkProgram(); 

    //number of QUAD vertex 
    const GLshort QUAD_ELEMENTS = 6; 

    GLuint r,c,q,x; 

    //bind VBO 
    vbo.bindVBO(); 

    //set the start where you draw the first square of the plane 
    // so that everything is centered 
    GLfloat initX,initY; 
    initX = initY = 0.0f; 

    //displacement of each QUAD in X and Y axis. 
    const float MODULE = 0.2f; 


    //find the init value of X (the start value where you draw the first QUAD) 
    if(m_cols > 1) 
    { 
     initX = (float)((m_cols*MODULE/2.0f))-0.1f; 
    } 
    //find the init value of y (the start value where you draw the first QUAD) 
    if(m_rows > 1) 
    { 
     initY = (float)((m_rows*MODULE/2.0f))-0.1f; 
    } 



    //QUAD vertex data 
    vector3f quad[QUAD_ELEMENTS]; 
    quad[0] = vector3f(-0.1f,0.1f,0.0f); quad[1] = vector3f(0.1f,0.1f,0.0f); 
    quad[2] = vector3f(0.1f,-0.1f,0.0f); quad[3] = vector3f(0.1f,-0.1f,0.0f); 
    quad[4] = vector3f(-0.1f,-0.1f,0.0f); quad[5] = vector3f(-0.1f,0.1f,0.0f); 



    x=0; 
    //put QUAD vertex in the "init position" 
    for(x=0;x<QUAD_ELEMENTS;++x) 
    { 
     quad[x].x = quad[x].x + (-initX); 
     quad[x].y = quad[x].y + initY; 
    } 


    //store de actual Y value of row (Y axis) 
    GLfloat newRow = 0.0f; 
    //store de actual X value of column (X axis) 
    GLfloat newColumn = 0.0f; 


    GLuint colorCounter = 0; 


    for(r=0;r<m_rows;++r) 
    { 
     //reset newColumn variable to 0.0f for each new column 
     newColumn = 0.0f; 

     //for each column 
     for(c=0;c<m_cols;++c) 
     { 
      //copy QUAD vertex data in new array 
      vector3f quadCopy[QUAD_ELEMENTS] = quad; 
      //for each column, move 0.1f to right 
      for(q=0;q<QUAD_ELEMENTS;++q) 
      { 
       //move right one MODULE (in x axis) 
       quadCopy[q].x = float(quadCopy[q].x + newColumn); 
       //move down one MODULE (in Y axis) 
       quadCopy[q].y = float(quadCopy[q].y + newRow); 
       //add vertex data and color to de vbo 
       vector3f resizedVertex = vector3f(quadCopy[q].x*m_segmentSize,quadCopy[q].y*m_segmentSize,quadCopy[q].z); 
       vbo.addData(&resizedVertex,sizeof(vector3f)); 
       //every 4 laps reset colorCounter to 0; 

       cout << "Vertex["<< q << "] = "<< resizedVertex.x << "," << resizedVertex.y << ";\n"; 
       if(colorCounter == 3){colorCounter = 0;} 
       vbo.addData(&color4f(m_selectedColor.color[colorCounter].r,m_selectedColor.color[colorCounter].g,m_selectedColor.color[colorCounter].b,m_selectedColor.color[colorCounter].a),sizeof(color4f)); 


       ++colorCounter; 
      } 

      //for each column, move right 0.1f 
      newColumn += MODULE; 

     } 

     newRow -= MODULE; 
    } 


    //bind VAO 
    glBindVertexArray(m_uiVAO); 
    //bind VBO 
    vbo.bindVBO(); 
    vbo.uploadDataToGPU(GL_STATIC_DRAW); 

    glEnableVertexAttribArray(1); 
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(vector3f)+sizeof(color4f), (void*)sizeof(vector3f)); 

    glEnableVertexAttribArray(0); 
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vector3f)+sizeof(color4f), 0); 

    return true; 
} 


void plane::render() 
{ 
    //bind shader 
    m_shader->bindShader(); 
    //send projection matrix to shader 
    m_shader->sendUniform4x4("projectionMatrix", glm::value_ptr(*m_matrix->getProjectionMatrix())); 


    //matrix transformations 
    m_matrix->loadIdentity(); 
    m_matrix->scale(vector3f(m_scale,m_scale,m_scale)); 
    m_matrix->translate(m_pos); 
    m_matrix->rotateX(m_orientation.x); 
    m_matrix->rotateY(m_orientation.y); 
    m_matrix->rotateY(m_orientation.z); 

    //sendtransformation matrix (modelview) 
    m_shader->sendUniform4x4("modelViewMatrix", glm::value_ptr(m_matrix->getModelViewMatrix())); 

    //bind VAO 
    glBindVertexArray(m_uiVAO); 

    glDrawArrays(GL_TRIANGLES, 0, m_totalVertices); 

} 

下面是代碼生成頂點數據和索引[DONT WORK]表面類(修改):

#include "plane.h" 
#include "matrix.h" 
#include "glslshader.h" 
#include "texture.h" 

plane::plane(GLuint cols, GLuint rows,GLuint segmentSize, mixedColors color, CTexture* texture, GLshort textureMode) : 
m_matrix(0), 
m_shader(0), 
m_cols(cols), 
m_rows(rows), 
m_segmentSize(segmentSize), 
m_selectedColor(color), 
m_texture(texture), 
m_textureMode(textureMode), 
m_totalVertices(rows*(cols*6)) 
{ 
    //matrix handler 
    m_matrix = matrix::getInstance(); 

    //check that variables are > 1 
    if(m_cols < 1){m_cols = 1;} 
    if(m_rows < 1){m_rows = 1;} 

    // generate a VAO 
    glGenVertexArrays(1, &m_uiVAO); 

    vbo.createVBO(); 
    vboIndices.createVBO(); 
} 

plane::~plane() 
{ 
    delete m_shader; 
    vbo.releaseVBO(); 
    vboIndices.releaseVBO(); 
    glDeleteVertexArrays(1, &m_uiVAO); 
} 


bool plane::init() 
{ 
    //load the shaders 
    if(m_texture == NULL) 
    { 
     m_shader = new GLSLProgram("data/shaders/shader-primitives.vert", "data/shaders/shader-primitives.frag"); 
    } 
    else//if primitive use texture... 
     { 
      m_shader = new GLSLProgram("data/shaders/shader-texture.vert", "data/shaders/shader-texture.frag"); 
     } 

    if (!m_shader->initialize()) 
    { 
     cout << "Los shaders de las primitivas no pudieron ser incializados\n"; 
     return false; 
    } 
    m_shader->linkProgram(); 

    //number of QUAD vertex 
    const GLshort QUAD_ELEMENTS = 4; 

    GLuint r,c,q,x; 

    //--------------------------------------------------------------------------- 
    //bind VBO 
    vboIndices.bindVBO(GL_ELEMENT_ARRAY_BUFFER); 
    //base indices that are used to generate dynamic indices to all vertex data 

    GLuint baseIndices[6] = {0,1,2,2,3,0}; 
    GLshort indicesCounter = 0; 



    cout << "indices==========================================\n"; 



    for(x=0;x<m_totalVertices;++x) 
    { 

     if(indicesCounter == 6) 
     { 
      cout << "new pack of indices = " << x << "\n"; 

      baseIndices[0] = baseIndices[1]; 
      if(x > 6){baseIndices[1] += 2;}else{if(x == 6){baseIndices[1] += 3;}} 
      baseIndices[2] = (baseIndices[1]+1); 
      baseIndices[3] = baseIndices[2]; 
      baseIndices[4] = baseIndices[0]+1; 
      baseIndices[5] = baseIndices[0]; 
      indicesCounter = 0; 
     } 

     vboIndices.addData(&baseIndices[indicesCounter],sizeof(GLuint)); 
     cout << "indices["<<x<<"] = " << baseIndices[indicesCounter] << "\n"; 

     ++indicesCounter; 
    } 
    //------------------------------------------------------------------------------- 


    //bind VBO 
    vbo.bindVBO(); 

    //set the start where you draw the first square of the plane 
    // so that everything is centered 
    GLfloat initX,initY; 
    initX = initY = 0.0f; 

    //displacement of each QUAD in X and Y axis. 
    const float MODULE = 0.2f; 


    //find the init value of X (the start value where you draw the first QUAD) 
    if(m_cols > 1) 
    { 
     initX = (float)((m_cols*MODULE/2.0f))-0.1f; 
    } 
    //find the init value of y (the start value where you draw the first QUAD) 
    if(m_rows > 1) 
    { 
     initY = (float)((m_rows*MODULE/2.0f))-0.1f; 
    } 



    //QUAD vertex data 
    vector3f quad[QUAD_ELEMENTS]; 

    quad[0] = vector3f(-0.1f,0.1f,0.0f); quad[1] = vector3f(0.1f,0.1f,0.0f); 
    quad[2] = vector3f(0.1f,-0.1f,0.0f); quad[3] = vector3f(-0.1f,-0.1f,0.0f); 


    //put QUAD vertex in the "init position" 
    for(x=0;x<QUAD_ELEMENTS;++x) 
    { 
     quad[x].x = quad[x].x + (-initX); 
     quad[x].y = quad[x].y + initY; 
    } 


    //store de actual Y value of row (Y axis) 
    GLfloat newRow = 0.0f; 
    //store de actual X value of column (X axis) 
    GLfloat newColumn = 0.0f; 


    GLuint colorCounter = 0; 

    for(r=0;r<m_rows;++r) 
    { 
     //reset newColumn variable to 0.0f for each new column 
     newColumn = 0.0f; 

     //for each column 
     for(c=0;c<m_cols;++c) 
     { 
      //copy QUAD vertex data in new array 
      vector3f quadCopy[QUAD_ELEMENTS] = quad; 
      //for each column, move 0.1f to right 
      for(q=0;q<QUAD_ELEMENTS;++q) 
      { 
       //move right one MODULE (in x axis) 
       quadCopy[q].x = float(quadCopy[q].x + newColumn); 
       //move down one MODULE (in Y axis) 
       quadCopy[q].y = float(quadCopy[q].y + newRow); 
       //add vertex data and color to de vbo 
       vector3f resizedVertex = vector3f(quadCopy[q].x*m_segmentSize,quadCopy[q].y*m_segmentSize,quadCopy[q].z); 
       vbo.addData(&resizedVertex,sizeof(vector3f)); 
       //every 4 laps reset colorCounter to 0; 

       cout << "Vertex["<< q << "] = "<< resizedVertex.x << "," << resizedVertex.y << ";\n"; 
       if(colorCounter == 3){colorCounter = 0;} 
       vbo.addData(&color4f(m_selectedColor.color[colorCounter].r,m_selectedColor.color[colorCounter].g,m_selectedColor.color[colorCounter].b,m_selectedColor.color[colorCounter].a),sizeof(color4f)); 


       ++colorCounter; 
      } 

      //for each column, move right 0.1f 
      newColumn += MODULE; 

     } 

     newRow -= MODULE; 
    } 


    //bind VAO 
    glBindVertexArray(m_uiVAO); 
    //bind VBO 
    vbo.bindVBO(); 
    vbo.uploadDataToGPU(GL_STATIC_DRAW); 

    glEnableVertexAttribArray(1); 
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(vector3f)+sizeof(color4f), (void*)sizeof(vector3f)); 

    glEnableVertexAttribArray(0); 
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vector3f)+sizeof(color4f), 0); 


    //load indices data in VBO 
    vboIndices.bindVBO(GL_ELEMENT_ARRAY_BUFFER); 
    vboIndices.uploadDataToGPU(GL_STATIC_DRAW); 

    return true; 
} 


void plane::render() 
{ 
    //bind shader 
    m_shader->bindShader(); 
    //send projection matrix to shader 
    m_shader->sendUniform4x4("projectionMatrix", glm::value_ptr(*m_matrix->getProjectionMatrix())); 


    //matrix transformations 
    m_matrix->loadIdentity(); 
    m_matrix->scale(vector3f(m_scale,m_scale,m_scale)); 
    m_matrix->translate(m_pos); 
    m_matrix->rotateX(m_orientation.x); 
    m_matrix->rotateY(m_orientation.y); 
    m_matrix->rotateY(m_orientation.z); 

    /sendtransformation matrix (modelview) 
    m_shader->sendUniform4x4("modelViewMatrix", glm::value_ptr(m_matrix->getModelViewMatrix())); 

    //bind VAO 
    glBindVertexArray(m_uiVAO); 

    glDrawElements(GL_TRIANGLES, m_totalVertices, GL_UNSIGNED_INT, 0); 
} 

這裏的類可處理VBO的代碼[這部作品完美,只把這裏爲你明白做方法] :

#include "common_header.h" 

#include "vertexBufferObject.h" 

CVertexBufferObject::CVertexBufferObject() 
{ 
    bDataUploaded = false; 
} 

/*----------------------------------------------- 

Name:  createVBO 

Params: a_iSize - initial size of buffer 

Result: Creates vertex buffer object. 

/*---------------------------------------------*/ 

void CVertexBufferObject::createVBO(int a_iSize) 
{ 
    //obtiene el ID del VBO 
    glGenBuffers(1, &uiBuffer); 
    //reserva espacio para los datos que va a alojar 
    data.reserve(a_iSize); 
    //setea el tamaño 
    iSize = a_iSize; 
} 

/*----------------------------------------------- 

Name:  releaseVBO 

Params: none 

Result: Releases VBO and frees all memory. 

/*---------------------------------------------*/ 

void CVertexBufferObject::releaseVBO() 
{ 
    //elimina el ID obtenido 
    glDeleteBuffers(1, &uiBuffer); 
    bDataUploaded = false; 
    //libera todos los datos almacenados 
    data.clear(); 
} 

/*----------------------------------------------- 

Name:  mapBufferToMemory 

Params: iUsageHint - GL_READ_ONLY, GL_WRITE_ONLY... 

Result: Maps whole buffer data to memory and 
      returns pointer to data. 

/*---------------------------------------------*/ 

void* CVertexBufferObject::mapBufferToMemory(int iUsageHint) 
{ 
    if(!bDataUploaded)return 0; 
    void* ptrRes = glMapBuffer(iBufferType, iUsageHint); 
    return ptrRes; 
} 

/*----------------------------------------------- 

Name:  mapSubBufferToMemory 

Params: iUsageHint - GL_READ_ONLY, GL_WRITE_ONLY... 
      uiOffset - data offset (from where should 
          data be mapped). 
      uiLength - length of data 

Result: Maps specified part of buffer to memory. 

/*---------------------------------------------*/ 

void* CVertexBufferObject::mapSubBufferToMemory(int iUsageHint, unsigned int uiOffset, unsigned int uiLength) 
{ 
    if(!bDataUploaded)return 0; 
    void* ptrRes = glMapBufferRange(iBufferType, uiOffset, uiLength, iUsageHint); 
    return ptrRes; 
} 

/*----------------------------------------------- 

Name:  unmapBuffer 

Params: none 

Result: Unmaps previously mapped buffer. 

/*---------------------------------------------*/ 

void CVertexBufferObject::unmapBuffer() 
{ 
    glUnmapBuffer(iBufferType); 
} 

/*----------------------------------------------- 

Name:  bindVBOiDrawingHint) 
{ 
    glBufferData(iBufferType, data.size(), &data[0], iDrawingHint); 
    bDataUploaded = true; 


Params: a_iBufferType - buffer type (GL_ARRAY_BUFFER, ...) 

Result: Binds this VBO. 

/*---------------------------------------------*/ 

void CVertexBufferObject::bindVBO(int a_iBufferType) 
{ 
    iBufferType = a_iBufferType; 
    glBindBuffer(iBufferType, uiBuffer); 
} 

/*----------------------------------------------- 

Name:  uploadDataToGPU 

Params: iUsageHint - GL_STATIC_DRAW, GL_DYNAMIC_DRAW... 

Result: Sends data to GPU. 

/*---------------------------------------------*/ 

void CVertexBufferObject::uploadDataToGPU(int iDrawingHint) 
{ 
    glBufferData(iBufferType, data.size(), &data[0], iDrawingHint); 
    bDataUploaded = true; 
    data.clear(); 
} 

/*----------------------------------------------- 

Name:  addData 

Params: ptrData - pointer to arbitrary data 
      uiDataSize - data size in chars 

Result: Adds arbitrary data to VBO. 

/*---------------------------------------------*/ 

void CVertexBufferObject::addData(void* ptrData, unsigned int uiDataSize) 
{ 
    data.insert(data.end(), (char*)ptrData, (char*)ptrData+uiDataSize); 
} 

/*----------------------------------------------- 

Name:  getDataPointer 

Params: none 

Result: Returns data pointer (only before uplading). 

/*---------------------------------------------*/ 

void* CVertexBufferObject::getDataPointer() 
{ 
    if(bDataUploaded)return 0; 
    return (void*)data[0]; 
} 

/*----------------------------------------------- 

Name:  getBuffer 

Params: none 

Result: Returns VBO ID. 

/*---------------------------------------------*/ 

unsigned int CVertexBufferObject::getBuffer() 
{ 
    return uiBuffer; 
} 
+0

您的索引代碼很大,很難閱讀。你可以詳細說明你如何填充baseIndices變量?看起來問題在那裏。這一切似乎都過於複雜,再加上我(可能還有許多其他人)無法很好地閱讀西班牙文。 –

+0

謝謝!我翻譯了所有的評論,以便更好地理解它們。無論如何,爲了避免必須讀取所有的代碼,我把代碼的輸出,請檢查我上面提到的「section」 - >「例如」這是輸出和圖像是結果。 – user2303826

+0

任何想法傢伙?即時消失..我不知道爲什麼指數不正確地繪製表面。 – user2303826

回答

1

我不能100%肯定,而無需更多的信息,但無論如何:

指標的正確排列應該是這樣的:0,1,2,2,3,0, 4,5,6,6,7,4,8,9,10,10,11,8。

這是因爲你使用你的索引,就好像你沒有重複的頂點一樣,但是根據輸出,你做:)。或者,如果您想要使用更少的空間,請考慮使用GL_QUADS而不是GL_TRIANGLES,這樣您只需要指定每個四元組的4個索引。

如果你想修復你的頂點,只提交頂點0,1,2,3,5,6,9,10到你的floatbuffer並且不要修改你的索引。

+0

謝謝!你是對的! :D的指標應該是:0,1,2,2,3,0,4,5,6,6,7,4,8,9,10,10,11,8這些生成它們,一切正常:)感謝提示和感謝所有的幫助。 – user2303826

+0

我有一個新的疑問,我爲頂點創建了兩個VBO,包括紋理和索引的另一個。 事實是紋理,儘管它們被正確映射,沒有顯示,或者它是錯誤的。對於每個四邊形,我應用以下紋理: texcoords [0] = texCoord(0.0,1.0); texcoords [1] = texCoord(1.0,1.0); texcoords [2] = texCoord(1.0,0.0); texcoords [3] = texCoord(0.0,0.0); – user2303826

+0

考慮到「索引VBO」包含6個點來表示QUAD的四個頂點,在「頂點VBO」中只添加四個頂點,而對於每個頂點,一個紋理座標。 – user2303826

相關問題