Question

I'm trying to load a model into my project and I get an exception at glDrawElements. I read the model file (.nfg), and retain the vertices and indices into vectors, and I use Vertex Buffer Object to bind my model.

I tried this: I modified the fourth parameter from (GLvoid*)(sizeof(Vector3) * x) to (GLvoid*)(offset(Vertex, attribute)), but didn't do anything (in the link, the problem was that he was sending memory address in the 4th parameter, and I thought maybe I was sending the wrong parameter to the wrong attribute, which still, would be a problem when actually showing the model).

I'm using OpenGL ES 2.0 and I'm not doing this project for neither Android or iOS; currently working in Visual Studio 2013 on Windows 8.1

The model loader:

void loadModelNfg(const std::string &filename, 
                    GLuint &vbo, GLuint &ibo, GLuint &num, Shaders shaders){

    // put here the verteces and indices from the file
    std::vector<Vertex> vertices;
    std::vector<GLushort> indices;

    _loadModelNfg(filename, vertices, indices);
    std::cout << "Mesh Loader: loaded file: " << filename << "\n";

    // creates OpenGL objects necessary for drawing
    GLuint gl_vertex_buffer_object, gl_index_buffer_object;

    // vertex buffer object -> object in which to keep the vertices
    glGenBuffers(1, &gl_vertex_buffer_object);
    glBindBuffer(GL_ARRAY_BUFFER, gl_vertex_buffer_object);

    glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), 
                    &vertices[0], GL_STATIC_DRAW);

    glBindBuffer(GL_ARRAY_BUFFER, 0);

    // index buffer object -> object in which to keep the indices
    glGenBuffers(1, &gl_index_buffer_object);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gl_index_buffer_object);

    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), 
                    &indices[0], GL_STATIC_DRAW);

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    vbo = gl_vertex_buffer_object;
    ibo = gl_index_buffer_object;
    num = indices.size();
}

Calling the previous function:

// for now, global variables:
GLuint vbo, ibo, num;
Shader myShaders;

int Init ( ESContext* esContext ) {
    glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );

    // this one works: tried with a triangle
    int ret = myShaders.Init("../Resources/Shaders/TriangleShaderVS.vs", 
                    "../Resources/Shaders/TriangleShaderFS.fs");
    if (ret == 0)
        loadModelNfg("../../ResourcesPacket/Models/Bila.nfg", vbo, ibo, num, myShaders);

    return ret;
}

Drawing the model:

void Draw(ESContext* esContext) {
    Matrix world;
    world.SetIdentity();
    Matrix view = c.getView();
    Matrix persp = c.getPerspective();
    Matrix trans = world * view *persp;

    glClear(GL_COLOR_BUFFER_BIT);
    glUseProgram(myShaders.program);

    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);

    if (myShaders.positionAttribute != -1) {
            glEnableVertexAttribArray(myShaders.positionAttribute);
            glVertexAttribPointer(myShaders.positionAttribute, 3, GL_FLOAT, 
                    GL_FALSE, sizeof(Vertex), (GLvoid*)(offsetof(Vertex, pos)));
    }
    if (myShaders.normalAttribute != -1) {
            glEnableVertexAttribArray(myShaders.normalAttribute);
            glVertexAttribPointer(myShaders.normalAttribute, 3, GL_FLOAT, 
                    GL_FALSE, sizeof(Vertex), (GLvoid*)(offsetof(Vertex, norm)));
    }
    if (myShaders.binormalAttribute != -1) {
            glEnableVertexAttribArray(myShaders.binormalAttribute);
            glVertexAttribPointer(myShaders.binormalAttribute, 3, GL_FLOAT, 
                    GL_FALSE, sizeof(Vertex), (GLvoid*)(offsetof(Vertex, binorm)));
    }
    if (myShaders.tangentAttribute != -1) {
            glEnableVertexAttribArray(myShaders.tangentAttribute);
            glVertexAttribPointer(myShaders.tangentAttribute, 3, GL_FLOAT, 
                    GL_FALSE, sizeof(Vertex), (GLvoid*)(offsetof(Vertex, tgt)));
    }
    if (myShaders.texcoordAttribute != -1) {
            glEnableVertexAttribArray(myShaders.texcoordAttribute);
            glVertexAttribPointer(myShaders.texcoordAttribute, 2, GL_FLOAT, 
                    GL_FALSE, sizeof(Vertex), (GLvoid*)(offsetof(Vertex, uv)));
    }
    if (myShaders.colorAttribute != -1) {
            glEnableVertexAttribArray(myShaders.colorAttribute);
            glVertexAttribPointer(myShaders.colorAttribute, 3, GL_FLOAT, 
                    GL_FALSE, sizeof(Vertex), (GLvoid*)(offsetof(Vertex, col)));
    }
    if (myShaders.MVPuniform != -1) {
            glUniformMatrix4fv(myShaders.MVPuniform, 1, GL_FALSE, (GLfloat*) trans.m);
    }

    // HERE GETS EXCEPTION
    glDrawElements(GL_TRIANGLES, num, GL_UNSIGNED_SHORT, (GLvoid*) 0);

    eglSwapBuffers (esContext->eglDisplay, esContext->eglSurface);
}

I am not sure that I am correctly binding the buffers in the loadModelNfg() function.

From what can this problem come and how can it be resolved?

EDIT:

GL_VENDOR:   Imagination Technologies (Host GL: 'Intel'); 
GL_RENDERER: PowerVR PVRVFrame 4.2SGX 530 (Host 'Intel(R) HD Graphics 400'); 
GL_VERSION:  OpenGL ES 2.0 (SDK build: 2.04.24.0809)

EDIT:

I surrounded the function with try-catch statement, but it still breaks when calling it:

try {
    glDrawElements(GL_TRIANGLES, num, GL_UNSIGNED_SHORT, (GLvoid*)0);
}
catch (const std::exception& e) {
    std::cout << e.what() << "\n";
}

I forgot to mention that the project/solution builds successful (after cleaning, or by rebuild).

Was it helpful?

Solution

After learning that OpenGL doesn't throw exceptions, I started looking how it handles errors. I found out that it "returns" error codes (or 0 if success), which can be found with glGetError().

Going withglGetError() through the code, I found out that the error was caused by glUseProgram(myShaders.program);.

Knowing that, I went through the functions which used myShaders variable, and I found that, after calling loadModelNfg("../../ResourcesPacket/Models/Bila.nfg", vbo, ibo, num, myShaders);, the variable got change.

Remembering that I don't use it anymore, I just removed it, and everything was fine.

What is strange is that I didn't modified the myShaders variable anywhere in that function (the code in the question is the final one). The problem, I think, is that I didn't declared the parameter const Shaders shaders.

So, the conclusion: use glGetError() and breakpoints in code to find the real problem. It may not be the where it breaks!

PS: I hope it's ok that I put this as an answer. If it's not, I'll update the question.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top