2014-01-14 4 views
4

Я делаю парсер файлов для файлов OBJ, и все идет в нужное место, но по какой-то причине оно не запускается до конца файла.C++ OBJ file parser

void loader::readIn() 
{ 
    //!takes in the all the data and 
    //!puts in string first. 
    std::string line; 

    while(!myFile.eof()) 
    { 

     linetype = unknown;//enum set to uknown 
     line.clear(); // clear line 
     ss.clear(); // clear string stream 
     std::getline(myFile,line); //intake line , to string line 

     //found = line.find("v "); //enum to check the line type i,e Face ,vertex 
     if(line[0] == 'v') //! check to see if the first char is v 
      { 
      linetype = vertex; 

      } 

    // found = line.find("f "); 
     if(line[0] == 'f') //! checkl to see if the first char is f 
     { 
      linetype = face; 

     } 

    // found = line.find("vn "); 
     if(line[0] == 'vn') //! checkl to see if the first char is vn 
     { 

      linetype = vertexNormal; 

     } 
     // found = line.find("vt ") 
     if(line[0] == 'vt') //! checkl to see if the first char is vt 
     { 
      linetype = vertexTexture; 

     } 

      if(line[0] == ' ' || '#') // if the start of the line is empty or a # 
     { 
      line.clear(); //clear line 
       std::getline(myFile,line); // intake the next line 
     } 



     switch(linetype) 
     { 
     case vertex:  //!stores the verrtex floats in vert. 

      ss >> vertexFloat[0] >> vertexFloat[1] >> vertexFloat[2]; 
      verts.push_back(new coordinate(vertexFloat[0],vertexFloat[1],vertexFloat[2])); //creates new coord 
      linetype = unknown; 
      break; 

     case face: 
      int n; // these are the counters for the float arrays 
      int m; 
      int b; 
      n = 0; 
      m = 0; 
      b = 0; 
      int faces[3]; //temperary float array 
      int faceText[3]; 
      int faceNorm[3]; 
      ss.str(line); //string stream intake line 
      ss.ignore(1); 
      while(!ss.eof()) 
      { 

       ss >> faces[n]; // intake first umber 
       n++; 

       if(ss.peek() == '/') 
       { 
        ss.ignore(1); 

        if(ss.peek() != '/') 
        { 
         ss >> faceText[m]; 
         m++; 
        } 
       } 

       ss.ignore(1); 
       ss >> faceNorm[b]; 
       b++; 

      } 


      for(int i = 0; i < 3 ; ++i) 
      { 
      totalFaces.push_back(faces[i]); // push back all the ints on the correct 
      faceTexture.push_back(faceText[i]); // vector 
      faceNormal.push_back(faceNorm[i]); 
      } 
      break; 

Это код, который требуется в первых трех строках, затем просто останавливается. Я проверяю вектор totalFaces, который принимает первое число каждого набора из 3.

**f 1/2/3 4//6 7/8/9 
f 1/2/3 4//6 7/8/9 
f 1/2/3 4//6 7/8/9 
f 1/2/3 4//6 7/8/9 
f 1/2/3 4//6 7/8/9 
f 1/2/3 4//6 7/8/9 
f 1/2/3 4//6 7/8/9 
f 1/2/3 4//6 7/8/9 
f 1/2/3 4//6 7/8/9** 

- это мой файл obj.

+0

Вы можете использовать while (std :: getline (myFile, line)) {.. ваш код здесь ..} –

ответ

1

Неправильно установить eof() в состояние цикла. Это не предсказание, это указывает на то, что предыдущее чтение не удалось из-за EOF. Например. даже пустой файл не начинается с .eof true.

Кроме того, 'vn' не является ни символом, ни двумя символами. line[0] определенно один символ и, очевидно, не может равняться двум символам «vn».

+0

Какие альтернативы я могу использовать для eof(), чтобы он читался в конце файла. – Student123

+0

Просто попробуйте прочитать и затем проверить результат потока. Если все еще хорошо, чтение преуспело, и строка в порядке. Если нет, все готово. Это просто. Чтобы сделать это действительно удобным, 'std :: getline (stream, line)' возвращает поток, который вы можете протестировать напрямую - поток преобразуется в 'true', когда он все еще хорош. – MSalters

2

Вам не нужно использовать eof(). Посмотрите мой код:

void Mesh::LoadObjModel(const char *filename) 
{ 
    std::ifstream in(filename, std::ios::in); 
    if (!in) 
    { 
     std::cerr << "Cannot open " << filename << std::endl; 
     exit(1); 

    } 
    std::string line; 
    while (std::getline(in, line)) 
    { 
    //check v for vertices 
    if (line.substr(0,2)=="v "){ 
     std::istringstream v(line.substr(2)); 
     glm::vec3 vert; 
     double x,y,z; 
     v>>x;v>>y;v>>z; 
     vert=glm::vec3(x,y,z); 
     vertices.push_back(vert); 
    } 
    //check for texture co-ordinate 
    else if(line.substr(0,2)=="vt"){ 

     std::istringstream v(line.substr(3)); 
     glm::vec2 tex; 
     int U,V; 
     v>>U;v>>V; 
     tex=glm::vec2(U,V); 
     texture.push_back(tex); 

    } 
    //check for faces 
    else if(line.substr(0,2)=="f "){ 
    int a,b,c; //to store mesh index 
    int A,B,C; //to store texture index 
    //std::istringstream v; 
    //v.str(line.substr(2)); 
    const char* chh=line.c_str(); 
    sscanf (chh, "f %i/%i %i/%i %i/%i",&a,&A,&b,&B,&c,&C); //here it read the line start with f and store the corresponding values in the variables 

    //v>>a;v>>b;v>>c; 
    a--;b--;c--; 
    A--;B--;C--; 
    //std::cout<<a<<b<<c<<A<<B<<C; 
    faceIndex.push_back(a);textureIndex.push_back(A); 
    faceIndex.push_back(b);textureIndex.push_back(B); 
    faceIndex.push_back(c);textureIndex.push_back(C); 
    } 

} 
//the mesh data is finally calculated here 
for(unsigned int i=0;i<faceIndex.size();i++) 
{ 
    glm::vec3 meshData; 
    glm::vec2 texData; 
    meshData=glm::vec3(vertices[faceIndex[i]].x,vertices[faceIndex[i]].y,vertices[faceIndex[i]].z); 
    texData=glm::vec2(texture[textureIndex[i]].x,texture[textureIndex[i]].y); 
    meshVertices.push_back(meshData); 
    texCoord.push_back(texData); 
} 

} 

В приведенном выше примере кода отсутствует символ «Vn» для нормального. Вы можете добавить еще одно условие, чтобы проверить «Vn», как и на другое. Надеюсь, это может решить вашу проблему. Если вам нужна полная программа-образец, посмотрите here.

+0

Почему вы декрементируете 'a',' b', 'c',' A', 'B' и' C'. – ASK

+0

@Ask, В файле obj Индекс начинается с 1, а не с нулем, так что я уменьшился. –