简体   繁体   English

加载多纹理的.obj文件(c ++ / opengl)

[英]Loading multitextured .obj file (c++/opengl)

I'm having a problem loading a .obj file in an OpenGL app. 我在OpenGL应用程序中加载.obj文件时遇到问题。 It's a car model made of different sections (which use different material for example glass, wheels etc..) 这是一个由不同部分组成的汽车模型(使用不同的材料,例如玻璃,车轮等)。

I have a WavefrontModel class, which contains an array of WavefrontSection that have their own vertices, normals, materials, and tex coords. 我有一个WavefrontModel类,其中包含一个WavefrontSection数组,这些数组具有自己的顶点,法线,材质和tex坐标。

class WavefrontSection
{
  public:
        WavefrontSection(string mat_name = ""){ material = NULL; }
        void ConstructVAO();
        void Render();

    std::vector<float> vert;
    std::vector<float> tex_coord;
    std::vector<float> norm;

        /* these are the indexes used to build the VAO */
        std::vector<int>   vert_index;
    std::vector<int>   norm_index;
    std::vector<int>   tex_index;

        /* This is the material, containing ambient, diffuse and specular materials,
           and texture */
    Material *material;

        /* This is the VAO */
        VAO vao;
};

Materials, normals and vertices are loaded fine Here's a screen: 可以很好地加载材质,法线和顶点这是一个屏幕:

http://postimg.org/image/ubkm0nrjj/ http://postimg.org/image/ubkm0nrjj/

The problem comes when i try to apply the textures (one per section) that I loaded. 当我尝试应用我加载的纹理(每节一个)时,问题就来了。 Here's the loader code: 这是加载程序代码:

int WavefrontModel::load(string file,string _mtlFile)
{
    gl3WriteOnStream("Loading model "+file,log_stream);

    ifstream model(file.c_str());

    if(!model)
    {
       cerr<<"Cannot open file "<<file<<endl;
       gl3WriteOnStream("Cannot open file "+file,error_stream);
       return -1;
    }

    char buf[256];
    char *curr_tok = NULL;

    /* These vectors stores all the vertices,normals and texture coord.
       Later each section will just copy in their arrays their vertices, normals
       and coords. To get the right order, i store the .obj face index information
       in WavefrontSections::*_index vector */

    std::vector<float> vert;
    std::vector<float> norm;
    std::vector<float> tex;

    mtlHeader.Open(_mtlFile);  /* I open the material file, to parse all the materials */

    int curr_section = 0;

    while(!model.eof())
    {
        model.getline(buf,256);

        curr_tok = strtok(buf,WHITESPACE);

        if(!curr_tok || curr_tok[0] == '#')
        {
            continue;
        }
        else if(strcmp(curr_tok,"v") == 0)
        {
            vert.push_back(atof(strtok(NULL,WHITESPACE)));
            vert.push_back(atof(strtok(NULL,WHITESPACE)));
            vert.push_back(atof(strtok(NULL,WHITESPACE)));
        }
    else if(strcmp(curr_tok,"vn") == 0)
    {
        norm.push_back(atof(strtok(NULL,WHITESPACE)));
        norm.push_back(atof(strtok(NULL,WHITESPACE)));
        norm.push_back(atof(strtok(NULL,WHITESPACE)));
    }
    else if(strcmp(curr_tok,"vt") == 0)
    {
        tex.push_back(atof(strtok(NULL,WHITESPACE)));
        tex.push_back(atof(strtok(NULL,WHITESPACE)));
    }
    else if(strcmp(curr_tok,"usemtl") == 0)
    {
        char *mtl = strtok(NULL,WHITESPACE);
        bool already_pres = false;

            /*I check if a sections already uses that material,
              if so, i add the new indexes to that section,
              otherwise I just create a new section */

        for(int i = 0;i < sections.size();i++)
        {
           if(strcmp(mtl,sections[i]->material->name.c_str()) == 0)
           {
               curr_section = i;
               already_pres = true;
               break;
           }
        }


        if(!already_pres)
        {
           curr_section = sections.size();
           sections.push_back(new WavefrontSection(mtl));
           sections[curr_section]->material = mtlHeader.parseMaterial(mtl);
        }
    }
    else if(strcmp(curr_tok,"f") == 0)
    {
      char *tmp_tok = NULL;
      char *temp = NULL;

          /* Here I parse model's faces. I added a '-1' to the indexes, because in the .obj
             file they start from 1, but in my vectors they start from 0 */

      while((tmp_tok = strtok(NULL,WHITESPACE)))
      {
            sections[curr_section]->vert_index.push_back(atoi(tmp_tok)-1);

            if((temp = strstr(tmp_tok,"//"))) ///no texture
            {
               temp++;
               sections[curr_section]->norm_index.push_back(atoi(++temp)-1);
            }
            else if((temp = strstr(tmp_tok,"/"))) ///with texture
            {
           sections[curr_section]->tex_index.push_back(atoi(++temp)-1);

           if((temp = strstr(temp,"/")))
           {
              sections[curr_section]->norm_index.push_back(atoi(++temp)-1);
           }
            }
       }
    }

    }


    cout<<"This model has got "<<sections.size()<<" sections"<<endl;

    /* Now I add vertices, normals and texture coords to each section, 
       using the indexes that I previously stored in each section */

    for(int i = 0;i < sections.size();i++)
    {
      for(int j = 0;j < sections[i]->vert_index.size();j++)
      {
        sections[i]->vert.push_back(vert[sections[i]->vert_index[j]*3]);   //x component
        sections[i]->vert.push_back(vert[sections[i]->vert_index[j]*3+1]); //y component
        sections[i]->vert.push_back(vert[sections[i]->vert_index[j]*3+2]); //z component
      }

      for(int j = 0;j < sections[i]->tex_index.size();j++) 
      {
        sections[i]->tex_coord.push_back(tex[sections[i]->tex_index[j]*2]);   //u component
        sections[i]->tex_coord.push_back(tex[sections[i]->tex_index[j]*2+1]); //v component
      }

      for(int j = 0;j < sections[i]->norm_index.size();j++)
      {
        sections[i]->norm.push_back(norm[sections[i]->norm_index[j]*3]);     //x component
        sections[i]->norm.push_back(norm[sections[i]->norm_index[j]*3+1]);   //y component
        sections[i]->norm.push_back(norm[sections[i]->norm_index[j]*3+2]);   //z component
      }

       sections[i]->ConstructVAO();   //I construct the VAO for each section

        printf("Section %i has %i verts, %i normals, %i tex coords\n",i,sections[i]->vert.size()/3,sections[i]->norm.size()/3,sections[i]->tex_coord.size()/2);
    }


}

And here's the code to render the entire model: 这是渲染整个模型的代码:

void WavefrontModel::render(GLenum render_mode,bool normals,bool textured)
{
    glPolygonMode(GL_FRONT_AND_BACK,render_mode);

    glModelMatrix.LoadIdentity();
    glModelMatrix.translate(pos);
    glModelMatrix.rotate(angle,rot.x,rot.y,rot.z);
    glModelMatrix.scale(scaleVec);

    shader->sendUniformMatrix4fv(shader->getUniformLocation("projMat"),1,GL_FALSE,GLXSDLRenderPipeline::glProjectionMatrix);
    shader->sendUniformMatrix4fv(shader->getUniformLocation("viewMat"),1,GL_FALSE,GLXSDLRenderPipeline::glViewMatrix);
    shader->sendUniformMatrix4fv(shader->getUniformLocation("modMat"),1,GL_FALSE,glModelMatrix);
    shader->sendUniform1i(shader->getUniformLocation("texture"),0);


    for(int i = 0;i < sections.size();i++)
    {
      if(sections[i]->material)
      {
        sections[i]->material->sendMaterialUniforms(shader);
        sections[i]->material->texture.bind_unit(0);
      }
        shader->bind();
        sections[i]->Render();
        shader->unbind();

      if(sections[i]->material)
        sections[i]->material->texture.unbind();


    }
}

which calls render() on each WavefrontSection instance. 在每个WavefrontSection实例上调用render()。 The method WavefrontSection::render() is implemented as follows 方法WavefrontSection :: render()的实现如下

void WavefrontSection::Render()
{
    vao.DrawArrays(GL_TRIANGLES,0,vert.size());
}

(calling ConstructVAO, i created the buffers which old normals and texture coordinates too) (调用ConstructVAO,我也创建了旧法线和纹理坐标的缓冲区)

This is what i get: (blender render is how it should be, others are how it is rendered in my engine) 这就是我得到的:(混合渲染应该是这样,其他是在引擎中渲染的样子)

blender renders and engine renders 混合器渲染和引擎渲染

any advice? 有什么建议吗?

I solved it. 我解决了 The problem was here 问题在这里

else if(strcmp(curr_tok,"vt") == 0)
{
       tex.push_back(atof(strtok(NULL,WHITESPACE)));
       tex.push_back(atof(strtok(NULL,WHITESPACE)));
}

I replaced it with 我用

else if(strcmp(curr_tok,"vt") == 0)
{
        tex.push_back(atof(strtok(NULL,WHITESPACE)));
        tex.push_back(1-atof(strtok(NULL,WHITESPACE)));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM