2013-08-21 185 views
0

我在OpenGL應用程序中加載.obj文件時出現問題。 它是由不同部分的汽車模型(使用不同的材料,如玻璃,車輪等)加載多紋理.obj文件(C++/opengl)

我有一個WavefrontModel類,它包含WavefrontSection數組,有自己的頂點,法線,材料和tex coords。

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

材料,法線和頂點加載罰款 這裏有一個畫面:

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

問題是當我嘗試應用,我裝紋理(每節)。 這裏的裝載代碼:

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


} 

下面是使整個模型的代碼:

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


    } 
} 

它調用render()上的每個WavefrontSection實例。 方法WavefrontSection ::渲染()的實現如下

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

(主叫ConstructVAO,我創建了舊法線和紋理座標太緩衝區)

這就是我得到: (攪拌機呈現是應該的,別人它是如何在我的引擎進行渲染)

blender renders and engine renders

什麼建議嗎?

回答

0

我解決了它。 問題是這裏

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,"vt") == 0) 
{ 
     tex.push_back(atof(strtok(NULL,WHITESPACE))); 
     tex.push_back(1-atof(strtok(NULL,WHITESPACE))); 
} 
取代了它