C ++ OBJ file parser

I am making a parser for OBJ files, and everything goes to the right place, but for some reason it does not start until the end of the file.

    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 that is required in the first three lines, then just stops. I check the vector totalFaces, which takes the first number of each set of 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**

- my obj file.

+4
source share
2 answers

You do not need to use eof (). Check out 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 the above code example, the "Vn" value for the normal is missing. You can add one more condition to check "Vn", as well as on another. Hope this can solve your problem. If you need a complete sample program, look here .

+2

eof() . , , - EOF. . .eof true.

, 'vn' , . line[0] , , "vn".

+1

All Articles