2017-10-14 5 views
0

Ich versuche, ein 3D-Schachspiel mit C++ und OpenGL zu machen und dabei bin ich auf einen sehr seltsamen Fehler gestoßen, wo das Dreieck (a stehen für die Schachfigur) wird nicht zeichnen und ich bin mit einem leeren Bildschirm verlassen. Wenn ich das Mesh-Objekt in der Hauptfunktion statt in der Stückklasse erzeuge, funktioniert es problemlos, aber wenn es in der Stückklasse ist, tut es das nicht. Ist das ein Problem mit Zeigern?C++ OpenGL Issue Zeichnung Mesh mit Vbo und Vao in einem Objekt gespeichert

Hier ist mein Code:

So in der Haupt ich ein Schach peice wird

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

und später im Hauptverfahren das Netz in einer Schleife gezogen wird (die Auslosung create-Methode gezeigt werden, später in diesem Beitrag)

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

im Schach peice Header ich das Netz Informationen und Objekt erstellen:

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

In der .cpp-Datei für die Schachfigur erstelle ich das Mesh-Objekt - Verticies ist ein vec3 Vektor und Indizes ist ein vorzeichenloser int-Vektor.

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

Dies ist der Mesh-Konstruktor

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); 
} 

und hier ist die whitch Zeichenfunktion

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

Wenn der Code I bereitgestellt wird ein Verfahren innerhalb des Mesh-Klasse haben fragen nicht ausreicht, nur und ich kann dem Thread weitere Codeabschnitte hinzufügen.

Vielen Dank.

Antwort

1

Vielleicht ist das ein Schuss aus der Hüfte, aber da Sie glGenVertexArrays im Konstruktor der Klasse verwenden Mesh, nehme ich an, dass Sie MeshglDeleteVertexArrays im Destruktor der Klasse verwenden.
In dieser Zeile:

mesh = Mesh(verticies, indicies); 

geschieht folgende:

Sie legen ein temporäres Mesh Objekt, der das Objekt in der Konstruktor Vertex-Array erzeugt. Zu diesem Zeitpunkt sind alle Daten gültig und das Vertex-Array-Objekt wird generiert (GPU). Wenn Sie das Objekt zuweisen, werden die Elemente des temporären Objekts in das Zielobjekt kopiert. Jetzt existieren 2 identische Objekte. Unmittelbar danach wird das temporäre Objekt Mesh zerstört und das Vertex-Array-Objekt vom Destruktor Mesh::~Mesh des temporären Objekts gelöscht (glDeleteVertexArrays). Zu diesem Zeitpunkt sind alle Daten verschwunden.

Setzen Sie einen Haltepunkt in den Destrutor Mesh::~Mesh, dann können Sie einfach den Ablauf verfolgen.

Die Klasse nicht kopierbar machen und nicht konstruierbar kopieren, sondern einen Verschiebungskonstruktor und Verschiebeoperator angeben.

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

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

    .... 
}; 

See:

+1

@ Rabbid76: "* entfernen glDeleteVertexArrays bilden die destructor von Mesh *" Nein, das nicht tun, . Das Löschen im Destruktor ist für dieses Design korrekt. Das Problem besteht darin, den Destruktor wie in diesem Fall falsch aufzurufen. Dies sollte ein Nur-Verschieben-Typ sein, also sollte es einen Move-Konstruktor/-Operator haben, um den VAO von einer Instanz zur anderen zu bewegen. –

+0

@ NicolBolas Ich kann dir nicht widersprechen, natürlich hast du Recht. – Rabbid76