Thread: How to load .obj files?

  1. #1
    Registered User
    Join Date
    Oct 2006
    Location
    UK/Norway
    Posts
    485

    How to load .obj files?

    Hallo,

    I am working on a raytracer and are trying to make a mesh class so that I can load my own objects from files instead of just having boring primitives. I have written my own simple .obj file loader but something is really really wrong. When I try to load a model of a simple box I only get like 6 pixels that get the color of it. First I thought that maybe it was just because it was to small, but that is not the case (I think).

    So I was hoping that someone could take a look and maybe spot whats wrong.

    My method is to load the vertex coordinates from a file and construct triangles from it. I have already made a triangle class with intersection and all, so that part should work fine (a single triangle primitive renders perfectly)

    Code:
    // A small structure for holding the two cordinates of the UV
    struct UV
    {
           float u;
           float v;
    };
    
    
    // Convert a string into a Vector3D
    Vector3D processVertex(std::string line);
    
    // Create triangle
    std::vector<Triangle> createTriangel(std::vector<Vector3D> list);
    
    
    // Read the file, and convert it so that it can be used to something usefull
    std::vector<Triangle> loadFromFile(char* FileName)
    {     
          std::string currentLine;            // Variable that holds the current line
                                              // we are using.
          std::vector<Vector3D> vertexList;   // A dynamic vector array for holding
                                              // the info about the vertexs
          std::vector<UV> uvList;             // Dynamic list of uvs
          std::vector<Vector3D> normal;       // Dynamic list with the normals of 
                                              // the object
                                              
          std::vector<Triangle> triangleList; // The list we return to create the object
                                              // as this is bacis we dont need to 
                                              // return uv and normals
            
          // Open file
          std::ifstream myFile (FileName);
          if (myFile.is_open())
          {
              // While the file is open, we read the info and construct triangles
              while ( getline(myFile, currentLine) ) 
              {
                  // Check if this line holds vertex information. If the line starts 
                  // with "v ", we will use it.
                  if (currentLine[0] == 'v' && currentLine[1] == ' ' )
                  {
                      vertexList.push_back(processVertex(currentLine));
                  }
                  
                  // Check if the line holds uv information. If its starts with
                  // "vt" if a uv.
                  if (currentLine[0] == 'v' && currentLine[1] == 't')
                  {
                     // Read uv info
                     // My render dont have textures at this point
                  }
                  
                  // Check if the line holds normal information. If its starts with
                  // "vn" if a normal.
                  if (currentLine[0] == 'v' && currentLine[1] == 'n')
                  {
                     // Read normal info
                     // going to add this later
                  }
              
              }
              // Finished with reading the file, close it
              myFile.close();
          }
          
          
          // Create the triangles as the file is loaded
          // Dont work, not sure where the error is
          triangleList = createTriangel(vertexList);
          
          // Temp, just to check. This workd perfect.
          //triangleList.push_back(Triangle(Vector3D(0,0,0),Vector3D(-150,0,0),Vector3D(0,150,0)));
          
          return triangleList;
    }
    
    
    // Convert a string into a vertex
    Vector3D processVertex(std::string line)
    {
             std::string vertexString[3];
             
             for (int x = 0; x < 3; x++)
             {
                 for (int i = 2; i <= line.size(); i++)
                 {
                     //Break up the string into the three cordinates
                     if ( line[i] != ' ')
                     {
                        vertexString[x].push_back(line[i]);    
                     }
                 }
             }
             
             // Convert the string into a number
             Vector3D vertex( (float)atof(vertexString[0].c_str()),
                              (float)atof(vertexString[1].c_str()),
                              (float)atof(vertexString[2].c_str())
                              );
             return vertex;
    }
    
    // Convert the vertex cords into triangles
    std::vector<Triangle> createTriangel(std::vector<Vector3D> list)
    {
        std::vector<Triangle> triangleList;
        
        for (int i = 0; i <= list.size(); i= i + 3 )
        {
            triangleList.push_back(Triangle( list[i + 0],
                                              list[i + 1],
                                              list[i + 2] 
                                             ));
        }
        
        return triangleList;
    }
    Thanks for your time

  2. #2
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    I don't have time at the moment to examine that code, but... Naming your object data files with .obj is probably a bad idea. .obj is the name used on Windows systems for C and C++ intermediate object files. You might want to pick a different extension to avoid confusion. When in doubt, .dat or .bin are usually safe.

  3. #3
    Lean Mean Coding Machine KONI's Avatar
    Join Date
    Mar 2007
    Location
    Luxembourg, Europe
    Posts
    444
    I think he's referring to the Wavefront .obj file format specification for the Advanced Visualizer software that is a very simple text based format to store 3d objects. 3D studio max is able to export .obj files for example and I already used it several times in projects to load complex models with several thousands of polygons.

  4. #4
    The Right Honourable psychopath's Avatar
    Join Date
    Mar 2004
    Location
    Where circles begin.
    Posts
    1,071
    I haven't attempted an obj loader yet myself, but there's a source example at the bottom of this page that you could compare to.
    M.Eng Computer Engineering Candidate
    B.Sc Computer Science

    Robotics and graphics enthusiast.

  5. #5
    Registered User
    Join Date
    Oct 2006
    Location
    UK/Norway
    Posts
    485
    Thanks for your replies.

    I changed some of my code, as there was a problem with ones of the loops reading the information from a line.

    Right now it should work, but it does not.

    I have tried to print the output from every function and they are right. My three Vector3D variables that represent the three vertexes have the right numbers in them. And so has all the sizes for the arrays.

    The weird thing is that this works:
    Code:
          // The vector is empty at this point
          // Add a triangle to the mesh, to check if intersection code works
          mesh.push_back(Triangle(Vector3D(0,0,0),Vector3D(-150,0,0),Vector3D(0,150,0)));
    But not this:
    Code:
         // Create triangles out of the list of vertexes
         mesh = createTriangel(vertexList);
    createTriangle is defined as this, and I think this should work fine
    Code:
    // Convert the vertex cords into triangles
    std::vector<Triangle> createTriangel(std::vector<Vector3D> list)
    {
        std::vector<Triangle> triangleList;
        
        for (int i = 0; i < list.size(); i= i + 3 )
        {
            triangleList.push_back(Triangle( list[i + 0],
                                             list[i + 1],
                                             list[i + 2] 
                                             ));
        }
        
        return triangleList;
    }
    As the first works, where I create a triangle manually I guess my intersection code works fine, so the problem is with loading from file. Anyone have any ideas to what it could be?
    I have tried to print the coordinates of the triangles I load from a file and they are right. I even tried to load the same triangle as I manually create in example one, but that does not even work.

    Something here is really messed up, but I have no clue. Maybe I return something wrong or should have a pointer somewhere or something?

    Thank you very much for your time

    Here is the rest of the code:
    Code:
    // Convert a string into a Vector3D
    Vector3D processVertex(std::string line);
    
    // Create triangle
    std::vector<Triangle> createTriangel(std::vector<Vector3D> list);
    
    
    // Read the file, and convert it so that it can be used to something usefull
    std::vector<Triangle> loadFromFile(char* FileName)
    {     
          std::string currentLine;            // Variable that holds the current line
                                              // we are using.
          std::vector<Vector3D> vertexList;   // A dynamic vector array for holding
                                              // the info about the vertexs
          std::vector<UV> uvList;             // Dynamic list of uvs
          std::vector<Vector3D> normal;       // Dynamic list with the normals of 
                                              // the object
                                              
          std::vector<Triangle> mesh;         // The list we return to create the object
                                              // as this is bacis we dont need to 
                                              // return uv and normals
            
          // Open file
          std::ifstream myFile (FileName);
          if (myFile.is_open())
          {
              // While the file is open, we read the info and construct triangles
              while ( getline(myFile, currentLine) ) 
              {
                  // Check if this line holds vertex information. If the line starts 
                  // with "v ", we will use it.
                  if (currentLine[0] == 'v' && currentLine[1] == ' ' )
                  {
                      vertexList.push_back(processVertex(currentLine));
                  }
                  
                  // Check if the line holds uv information. If its starts with
                  // "vt" if a uv.
                  if (currentLine[0] == 'v' && currentLine[1] == 't')
                  {
                     // Read uv info
                     // My render dont have textures at this point
                  }
                  
                  // Check if the line holds normal information. If its starts with
                  // "vn" if a normal.
                  if (currentLine[0] == 'v' && currentLine[1] == 'n')
                  {
                     // Read normal info
                     // going to add this later
                  }
              
              }
              // Finished with reading the file, close it
              myFile.close();
          }
          
          
          // Create the triangles as the file is loaded
          // Dont work, not sure where the error is
          //mesh = createTriangel(vertexList);
          
          // Temp, just to check. This workd perfect.
          mesh.push_back(Triangle(Vector3D(0,0,0),Vector3D(-150,0,0),Vector3D(0,150,0)));
          
          return mesh;
    }
    
    
    // Convert a string into a vertex
    Vector3D processVertex(std::string line)
    {
             std::string vertexString[3];
             int x = 0;
             
             for (int i = 2; i <= line.size(); i++)
             {
                 if ( line[i] == ' ')
                 {
                      x++;
                 }
                 else
                 {
                     // add to same cord
                     vertexString[x].push_back(line[i]);
                 }
             }
             
             
             // Convert the string into a number
             Vector3D vertex( (float)atof(vertexString[0].c_str()),
                              (float)atof(vertexString[1].c_str()),
                              (float)atof(vertexString[2].c_str())
                              );
             
             return vertex;
    }
    
    // Convert the vertex cords into triangles
    std::vector<Triangle> createTriangel(std::vector<Vector3D> list)
    {
        std::vector<Triangle> triangleList;
        
        for (int i = 0; i < list.size(); i= i + 3 )
        {
            triangleList.push_back(Triangle( list[i + 0],
                                             list[i + 1],
                                             list[i + 2] 
                                             ));
        }
        
        return triangleList;
    }
    [/CODE]

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. accessing all files in a folder.
    By pastitprogram in forum C++ Programming
    Replies: 15
    Last Post: 04-30-2008, 10:56 AM
  2. File send app - md5 checksum different when load is put on server.
    By (Slith++) in forum Networking/Device Communication
    Replies: 5
    Last Post: 12-31-2007, 01:23 PM
  3. Help with loading files into rich text box
    By blueparukia in forum C# Programming
    Replies: 3
    Last Post: 10-19-2007, 12:59 AM
  4. Relocation in .obj -files
    By willkoh in forum C++ Programming
    Replies: 6
    Last Post: 04-06-2005, 01:59 PM
  5. reinserting htm files into chm help files
    By verb in forum Windows Programming
    Replies: 0
    Last Post: 02-15-2002, 09:35 AM