LoadOBJPlus

From class_wiki
Jump to: navigation, search
bool loadOBJPlus(const char * path, 
	     std::vector<glm::vec3> & out_vertices, 
	     std::vector<glm::vec2> & out_uvs,
	     std::vector<glm::vec3> & out_normals) 
{
  printf("Loading OBJ file %s...\n", path);
  
  std::vector<unsigned int> vertexIndices, uvIndices, normalIndices;
  std::vector<glm::vec3> temp_vertices; 
  std::vector<glm::vec2> temp_uvs;
  std::vector<glm::vec3> temp_normals;
  
  
  FILE * file = fopen(path, "r");
  if( file == NULL ){
    printf("Impossible to open the file ! Are you in the right path ? See Tutorial 1 for details\n");
    getchar();
    return false;
  }
  
  while( 1 ){
    
    char lineHeader[128];
    // read the first word of the line
    int res = fscanf(file, "%s", lineHeader);
    if (res == EOF)
      break; // EOF = End Of File. Quit the loop.
    
    // else : parse lineHeader
    
    if ( strcmp( lineHeader, "v" ) == 0 ){
      glm::vec3 vertex;
      fscanf(file, "%f %f %f\n", &vertex.x, &vertex.y, &vertex.z );
      temp_vertices.push_back(vertex);
    }else if ( strcmp( lineHeader, "vt" ) == 0 ){
      glm::vec2 uv;
      fscanf(file, "%f %f\n", &uv.x, &uv.y );
      uv.y = -uv.y; // Invert V coordinate since we will only use DDS texture, which are inverted. Remove if you want to use TGA or BMP loaders.
      temp_uvs.push_back(uv);
    }else if ( strcmp( lineHeader, "vn" ) == 0 ){
      glm::vec3 normal;
      fscanf(file, "%f %f %f\n", &normal.x, &normal.y, &normal.z );
      temp_normals.push_back(normal);
    }else if ( strcmp( lineHeader, "f" ) == 0 ){
      std::string vertex1, vertex2, vertex3;
      unsigned int vertexIndex[3], uvIndex[3], normalIndex[3];
      int matches;
      
      // remember position in case fscanf fails
      long int fpos = ftell (file);
      matches = fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n", &vertexIndex[0], &uvIndex[0], &normalIndex[0], &vertexIndex[1], &uvIndex[1], &normalIndex[1], &vertexIndex[2], &uvIndex[2], &normalIndex[2] );
      if (matches == 9) {
	
	vertexIndices.push_back(vertexIndex[0]);
	vertexIndices.push_back(vertexIndex[1]);
	vertexIndices.push_back(vertexIndex[2]);
	uvIndices    .push_back(uvIndex[0]);
	uvIndices    .push_back(uvIndex[1]);
	uvIndices    .push_back(uvIndex[2]);
	normalIndices.push_back(normalIndex[0]);
	normalIndices.push_back(normalIndex[1]);
	normalIndices.push_back(normalIndex[2]);
	continue;
      }
      // go back to before fscanf and try again
      fseek(file, fpos, SEEK_SET);
      matches = fscanf(file, "%d %d %d\n", &vertexIndex[0], &vertexIndex[1], &vertexIndex[2]);
      
      if (matches != 3){
	printf("File can't be read by our simple parser :-( Try exporting with other options\n");
	return false;
      }
      
      vertexIndices.push_back(vertexIndex[0]);
      vertexIndices.push_back(vertexIndex[1]);
      vertexIndices.push_back(vertexIndex[2]);

      if (temp_normals.size() == temp_vertices.size()) {
	normalIndices.push_back(vertexIndex[0]);
	normalIndices.push_back(vertexIndex[1]);
	normalIndices.push_back(vertexIndex[2]);
      }

      
    }else{
      // Probably a comment, eat up the rest of the line
      char stupidBuffer[1000];
      fgets(stupidBuffer, 1000, file);
    }
    
  }
  
  // For each vertex of each triangle
  for( unsigned int i=0; i<vertexIndices.size(); i++ ){
    
    // Get the indices of its attributes, get the attributes thanks to the index, and put attributes in buffers
    
    unsigned int vertexIndex = vertexIndices[i];
    glm::vec3 vertex = temp_vertices[ vertexIndex-1 ];
    out_vertices.push_back(vertex);
    
    if (uvIndices.size() == vertexIndices.size()) {
      unsigned int uvIndex = uvIndices[i];
      glm::vec2 uv = temp_uvs[ uvIndex-1 ];
      out_uvs.push_back(uv);
    }
    
    if (normalIndices.size() == vertexIndices.size()) {
      unsigned int normalIndex = normalIndices[i];
      glm::vec3 normal = temp_normals[ normalIndex-1 ];
      out_normals.push_back(normal);
    }
    
  }
  
  return true;
}