使用OpenGL渲染.obj文件 [英] Rendering .obj files with OpenGL

查看:135
本文介绍了使用OpenGL渲染.obj文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在用opengl渲染模型时遇到了问题.我已经使用glDrawElements制作了自己的obj解析器和渲染函数,但看不到问题.这是我的解析器功能:

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

这是我的绘画功能:

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

成为变量:

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

我正在使用的obj文件是一个简单的多维数据集,但是我正在渲染的网格是完全的灾难.

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

我已经更改了代码,现在解析器如下所示:

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.

推荐答案

Classic obj出现opengl缓冲区错误,元素缓冲区索引指向所有属性.换句话说,如果opengl看到一个0索引,它将第一个元素从启用的缓冲区的 all 中移出,并移至下一个索引.在读取时没有重复数据就无法直接使用obj结构

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

您的代码应该是

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.

这篇关于使用OpenGL渲染.obj文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆