1
votes

I am following some tutorial on OpenGL and am running into a problem. I constructed a class called Mesh that takes an array of vertices in its constructor and generates vertexarrays and such to do the drawing. The problem is is that I am not seeing anything. Here is the interface:

class Mesh
{
public:
    Mesh(Vertex * vertices, size_t numVertices);
    virtual ~Mesh();

    void Draw();
private:
    enum    {       POSITION_VB, NUM_BUFFERS    };

    GLuint m_vertexArrayObject;
    GLuint m_vertexArrayBuffers;
    size_t m_drawCount;
};

and here are the implementations

#include "mesh.h"

Mesh::Mesh(Vertex *vertices, size_t numVertices)
{
    m_drawCount = numVertices;

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

    glGenBuffers(NUM_BUFFERS, &m_vertexArrayBuffers);
    glBindBuffer(GL_ARRAY_BUFFER, m_vertexArrayBuffers);
    glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(vertices[0]), vertices, GL_STATIC_DRAW);

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

void Mesh::Draw()
{
    glBindVertexArray(m_vertexArrayObject);
    glDrawArrays(GL_TRIANGLES, 0, m_drawCount);
    glBindVertexArray(0);
}

Mesh::~Mesh()
{
    glDeleteVertexArrays(1, &m_vertexArrayObject);
}

The Vertex type is a simple class that looks as

class Vertex {
public:
    Vertex(glm::vec3 const & pos)   {   this->pos = pos;}
private:
    glm::vec3 pos;
};

If I change the implementation of Mesh::Draw() to

glBegin(GL_TRIANGLES);              
glVertex3f(-1.0f, -0.25f, 0.0f);    //triangle first vertex
glVertex3f(-0.5f, -0.25f, 0.0f);    //triangle second vertex
glVertex3f(-0.75f, 0.25f, 0.0f);    //triangle third vertex
glEnd();                            //end drawing of triangles

I am getting a triangle printed to the screen. My question is: Does this necessarily mean that there is an error in the implementation of Mesh' member functions, and if so, can anyone spot it? I thought maybe the glBegin method bypasses some error somewhere else in the code that the vertexarray method cannot bypass. I would be grateful for any help. Also, I can post additional code if needed!

The shader code:

#version 120

void main()
{
    gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
}
1
What about the shaders?Falla Coulibaly
I have the shaders set up elsewhere, I am pretty sure they function correctly as they also determine the color of the glBegin part that is drawableSlugger
@Slugger: It is impossible to write a single shader which can with with both glVertex* commands and glVertexAttribPointer commands. At least, not without relying on NVIDIA's non-standard behavior. So I would like to see your shaders.Nicol Bolas
I just added the shader code. Sorry for the late reply, I was at uni all day todaySlugger

1 Answers

0
votes

More than likely your Mesh classes destructor is to blame:

Mesh::~Mesh()
{
    glDeleteVertexArrays(1, &m_vertexArrayObject);
}

You have an implicit copy constructor, which does a byte-for-byte copy of your class's members whenever a copy of your Mesh is necessary. That byte-for-byte copy includes the name (m_vertexArrayObject) of an OpenGL-managed resource, which means you now have two distinct objects referencing the same resource.

As soon as one of these copies goes out of scope, it will delete the VAO that is still referenced by the original object.

The simplest way to solve this problem is to disable the copy constructor (C++11 has new syntax for this), then you will get a compiler error anytime a copy needs to be made.

private:
    Mesh (const Mesh& original); // Copy ctor is inaccessible.

If you really do want to support multiple Mesh objects sharing the same Vertex Array Object, you will need to add reference counting and only free the VAO when the reference count reaches 0.