2017-10-14 162 views
0

我想做一个使用c + +和OpenGL的3D国际象棋游戏,同时这样做,我遇到了一个非常奇怪的错误,其中三角形棋子)不会画,我留下一个空白的屏幕。当我在主函数中而不是在片类中创建网格对象时,它可以毫无问题地工作,但是当它在片类中时不会。这是指针问题吗?C++ OpenGL问题绘图网格vbo和vao存储在一个对象内

这里是我的代码:

所以在主我

Piece piece = Piece(vec3(0, 0, 0)); //Create a chess peice 

,后来在网格在循环中得出的主要方法创建一个国际象棋peice的(抽签方法将显示后来在这篇文章)

piece.GetMesh().Draw(); //Draw the chess peice 

在棋peice的标题创建网格信息和对象:

//Mesh information 
vector <vec3> verticies; 
vector <unsigned int> indicies; 
Mesh mesh; 

在棋盘的.cpp文件中,我创建了网格对象 - verticies是一个vec3矢量,而indicies是一个无符号的int矢量。

mesh = Mesh(verticies, indicies); //Create the mesh object 

这是网状构造

Mesh::Mesh(vector <vec3> verticies, vector <unsigned int> indicies) 
{ 
    unsigned int numVerticies = verticies.size(); 
    unsigned int numIndicies = indicies.size(); 

    vector <vec2> texCoords; 

    //set the tex coords 
    unsigned int texCoordsIndex = 0; 

    for (unsigned int i = 0; i < numIndicies; i++) 
    { 
     switch (texCoordsIndex) 
     { 
     case 0: 
      texCoords.push_back(vec2(0, 0)); 
      texCoordsIndex++; 
      break; 
     case 1: 
      texCoords.push_back(vec2(0, 1)); 
      texCoordsIndex++; 
      break; 
     case 2: 
      texCoords.push_back(vec2(1, 1)); 
      texCoordsIndex = 0; 
      break; 
     } 
    } 

    //Sends the mesh to the buffer 
    drawCount = indicies.size(); 

    glGenVertexArrays(1, &vao); 
    glBindVertexArray(vao); 

    glGenBuffers(NUM_BUFFERS, vbo); 
    glBindBuffer(GL_ARRAY_BUFFER, vbo[POSITION_VB]); 
    glBufferData(GL_ARRAY_BUFFER, verticies.size() * sizeof(verticies[0]), &verticies[0], GL_STATIC_DRAW); 

    glEnableVertexAttribArray(0); 
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); 

    glBindBuffer(GL_ARRAY_BUFFER, vbo[TEXCOORD_VB]); 
    glBufferData(GL_ARRAY_BUFFER, texCoords.size() * sizeof(texCoords[0]), &texCoords[0], GL_STATIC_DRAW); 

    glEnableVertexAttribArray(1); 
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0); 

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[INDEX_VB]); 
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicies.size() * sizeof(indicies[0]), &indicies[0], GL_STATIC_DRAW); 

    glBindVertexArray(0); 
} 

,这里是绘制函数whitch是网类

void Mesh::Draw() 
{ 
    glBindVertexArray(vao); 
    glDrawElements(GL_TRIANGLES, drawCount, GL_UNSIGNED_INT, 0); 
    glBindVertexArray(0); 
} 

内的方法。如果我所提供的代码是不够的只是问我可以在线程中添加更多的代码段。

谢谢。

回答

1

也许这就是从臀部开枪,但因为你在类Mesh的构造函数中使用glGenVertexArrays,我假设你在类Mesh的析构函数使用glDeleteVertexArrays
在这一行:

mesh = Mesh(verticies, indicies); 

会发生以下情况:

你创建临时Mesh对象,其产生在其构造的顶点数组对象。此时所有的数据都是有效的,并且生成顶点数组对象(GPU)。分配对象时,临时对象的成员将被复制到目标对象。现在存在2个相同的对象。紧接着完成后,临时对象的临时对象Mesh被破坏,并且顶点数组对象被临时对象的析构函数Mesh::~Mesh删除(glDeleteVertexArrays)。此时所有的数据都消失了。

在destrutor Mesh::~Mesh中放置一个断点,然后您可以简单地跟踪到期。

使该类不可复制且不可复制构造,但指定移动构造函数和移动运算符。

class Mesh 
{ 
    Mesh(const Mesh &) = delete; 
    Mesh & operator = (const Mesh &) = delete; 

    Mesh(Mesh &&); 
    Mesh & operator = (Mesh &&); 

    .... 
}; 

参见:

+1

@ Rabbid76: “*删除glDeleteVertexArrays成网状的析构函数*” 不,不这样做。在这个设计中,在析构函数中删除它是正确的。问题在于不正确地调用析构函数,就像在这种情况下一样。这应该是只能移动的类型,所以它应该有一个移动构造器/操作符将VAO从一个实例移动到另一个实例。 –

+0

@NicolBolas我不能不同意,当然你是对的。 – Rabbid76