0

I have been having problems rendering a model in opengl. I have made my own obj parser and a render function using glDrawElements but I can't see the problem. This is my parser function:

void load_obj(char *nom)
{
FILE *file = fopen(nom, "r");
int iv = 0, in = 0, it = 0, ifa = 0;

if(file != NULL)
{
    while(1)
    {
        char lineHeader[128];
        int res = fscanf(file, "%s", lineHeader);

        if(res == EOF)
            break;

        if(strcmp(lineHeader, "v") == 0)
        {
            float vertex[3] = {0,0,0};
            fscanf(file, "%f %f %f\n", 
                &vertex[0], &vertex[1], &vertex[2]);

            vertices[iv] = vertex[0];
            vertices[iv+1] = vertex[1];
            vertices[iv+2] = vertex[2];
            iv += 3;
        }
        else if(strcmp(lineHeader, "vt") == 0)
        {
            float tex_vert[2] = {0,0};
            fscanf(file, "%f %f\n", 
                &tex_vert[0], &tex_vert[1]);

            texturas[it] = tex_vert[0];
            texturas[it+1] = tex_vert[1];
            it += 2;
        }
        else if(strcmp(lineHeader, "vn") == 0)
        {
            float normal[3] = {0,0,0};
            fscanf(file, "%f %f %f\n", 
                &normal[0], &normal[1], &normal[2]);

            normales[in] = normal[0];
            normales[in+1] = normal[1];
            normales[in+2] = normal[2];
            in += 3;
        }
        else if(strcmp(lineHeader, "f") == 0)
        {
            unsigned int vertexIndex[9] = {0,0,0,0,0,0,0,0,0};
            fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n", 
                &vertexIndex[0], &vertexIndex[1], &vertexIndex[2],
                &vertexIndex[3], &vertexIndex[4], &vertexIndex[5],
                &vertexIndex[6], &vertexIndex[7], &vertexIndex[8]);

            vertTriangulos[ifa] = vertexIndex[0];
            vertTriangulos[ifa+1] = vertexIndex[1];
            vertTriangulos[ifa+2] = vertexIndex[2];
            vertTriangulos[ifa+3] = vertexIndex[3];
            vertTriangulos[ifa+4] = vertexIndex[4];
            vertTriangulos[ifa+5] = vertexIndex[5];
            vertTriangulos[ifa+6] = vertexIndex[6];
            vertTriangulos[ifa+7] = vertexIndex[7];
            vertTriangulos[ifa+8] = vertexIndex[8];
            ifa += 9;

            nTriangulos++;
        }
    }
 }

And this is my draw function:

void draw()
{
        glClear(GL_COLOR_BUFFER_BIT);
        glMatrixMode(GL_MODELVIEW);

        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glEnableClientState(GL_NORMAL_ARRAY);

        glVertexPointer(3, GL_FLOAT, 0, vertices);
        glTexCoordPointer(2, GL_FLOAT, 0, texturas);
        glNormalPointer(GL_FLOAT, 0, normales);

        glDrawElements(GL_TRIANGLES, nTriangulos*9, GL_UNSIGNED_INT, vertTriangulos);

        glDisableClientState(GL_VERTEX_ARRAY);
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
        glDisableClientState(GL_NORMAL_ARRAY);
   }

Being the variables:

    long nTriangulos;
float *vertices, *normales, *texturas;
unsigned int *vertTriangulos;

The obj file I'm using is a simple cube, but the mesh I'm rendering is a complete disaster.

EDIT: I have changed my code and now the parser looks like this:

    if(strcmp(lineHeader, "f") == 0)
    {
    unsigned int vertexIndex[9] = {0,0,0,0,0,0,0,0,0};
    fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n", 
        &vertexIndex[0], &vertexIndex[1], &vertexIndex[2],
        &vertexIndex[3], &vertexIndex[4], &vertexIndex[5],
        &vertexIndex[6], &vertexIndex[7], &vertexIndex[8]);

        for(int i = 0; i < 9; i += 3)
        {
            bool cierto = true;
            int pos = 0;

            if(indexbuff.size() > 0)
            {
                for(int i = 0; i < registro.size(); i++)
                {
                    if(vertexIndex[0] == registro[i].in1 
                        && vertexIndex[1] == registro[i].in2 
                        && vertexIndex[2] == registro[i].in3)
                    {
                        cierto = false;
                        pos = i;
                    }
                }
            }

            if(cierto)
            {
                verticebuff.push_back(vertices[vertexIndex[i]]);
                verticebuff.push_back(vertices[vertexIndex[i]+1]);
                verticebuff.push_back(vertices[vertexIndex[i]+2]);

                textbuff.push_back(texturas[vertexIndex[i+1]]);
                textbuff.push_back(texturas[vertexIndex[i+1]+1]);

                normalbuff.push_back(normales[vertexIndex[i+2]]);
                normalbuff.push_back(normales[vertexIndex[i+2]+1]);
                normalbuff.push_back(normales[vertexIndex[i+2]+2]);

                indexbuff.push_back(verticebuff.size()/3);

                index3 indice;
                indice.in1 = vertexIndex[i];
                indice.in2 = vertexIndex[i+1];
                indice.in3 = vertexIndex[i+2];
                registro.push_back(indice);
            }
            else
            {
                indexbuff.push_back(i);
            }
        }
       }

But it doesn't seem to work properly.

2

1 Answer 1

5

Classic obj to opengl buffer mistake, the element buffer index points to all attributes. In other words if opengl sees a 0 index it takes the first element out of all the enabled buffers and move on to the next index. There is no way to use the obj structure directly without duplication of the data as you are reading

you face code should be

if(/*vertexIndex[0..2] triplet has not been seen yet*/){
verticebuff.pushback(vertices[vertexIndex[0]]);
verticebuff.pushback(vertices[vertexIndex[0]+1]);
verticebuff.pushback(vertices[vertexIndex[0]+2]);


textbuff.pushback(texturas[vertexIndex[1]]);
textbuff.pushback(texturas[vertexIndex[1]+1]);

normalbuff.pushback(normales[vertexIndex[2]]);
normalbuff.pushback(normales[vertexIndex[2]+1]);

indexbuff.pushback(verticebuff.size()/3);
} else {
    indexbuff.pushback(/*index of the seen triplet*/);
}

//repeat 3 times

then you can paint them with draw elements.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.