简体   繁体   English

C ++ OBJ文件解析器

[英]C++ OBJ file parser

I am making a file parser for the OBJ files and everything is going into the correct place but for some reason it doesn't run till the end of the file. 我正在为OBJ文件制作一个文件解析器,一切都进入了正确的位置,但由于某种原因它不会运行到文件的末尾。

    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;

This is the code it takes in the first 3 lines then just stops. 这是前3行所需的代码然后才停止。 I am checking the totalFaces vector which takes in the first number of each set of 3. 我正在检查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**

is my obj file. 是我的obj文件。

You don't have to use eof(). 您不必使用eof()。 Look my code: 看看我的代码:

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

}

In above sample code the 'Vn' for normal is missing. 在上面的示例代码中,缺少正常的“Vn”。 You can add another condition to check 'Vn' similar to other. 您可以添加另一个条件来检查'Vn'与其他类似。 I hope this could solve you problem. 我希望这可以解决你的问题。 If you need complete sample program then look here . 如果您需要完整的示例程序,请查看此处

It's incorrect to check eof() in the loop condition. 在循环条件下检查eof()是不正确的。 It's not a prediction, it indicates that the previous read failed because of EOF. 这不是预测,它表明之前的读取因EOF而失败。 Eg even an empty file doesn't start with .eof true. 例如,即使空文件也不以.eof true开头。

Also, 'vn' is neither one character nor two characters. 此外,'vn'既不是一个字符,也不是两个字符。 line[0] definitely is one character and obviously cannot equal the two characters "vn". line[0]肯定是一个字符,显然不能等于两个字符“vn”。

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

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