Rendering .obj files with OpenGL

扶醉桌前 提交于 2019-12-11 13:33:22

问题


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.


回答1:


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.



来源:https://stackoverflow.com/questions/22185654/rendering-obj-files-with-opengl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!