topical media & game development

talk show tell print

lib-of-vs-addons-ofxObjLoader-src-ofxObjLoader.cpp / cpp



  include <ofxObjLoader.h>
  
  ofxObjLoader::ofxObjLoader(){
    verbose=false;
  }
  
  ofxObjLoader::ofxObjLoader(char file[]){
    ofxObjLoader();
    loadFile(file);
  }
  
  void ofxObjLoader::loadFile(char file[]){
  
    string newFileName = ofToDataPath(file);
    //validate the file name
    if(strlen(file)==0){
      complain("filename string was empty");
      return;
    }
  
    //make sure the file exists on the disk
    ifstream existanceChecker(newFileName.c_str());
    if(!existanceChecker.is_open()){
      complain("file not found");
      return;
    }
    existanceChecker.close();
  
    // we will now slowly parse through the file f
    ifstream f;
    f.open(newFileName.c_str(),iostream::binary);
    while(f.good()){
  
      //get the first token on this line. it's a command
      char objCommand[256];
      f.getline(objCommand,256,' ');
  
      if(!strcmp(objCommand,"v")){
        vertices.push_back(objVertex());
        f >> vertices.back().x;
        f >> vertices.back().y;
        f >> vertices.back().z;
  
        ignoreRestOfLine(&f);
  
      }else if(!strcmp(objCommand,"#")){//comment
        ignoreRestOfLine(&f);
  
      }else if(!strcmp(objCommand,"vt")){
        texCoords.push_back(objVertex());
        f >> texCoords.back().x;
        f >> texCoords.back().y;
        f >> texCoords.back().z;
        ignoreRestOfLine(&f);
  
      }else if(!strcmp(objCommand,"vn")){
        normals.push_back(objVertex());
        f >> normals.back().x;
        f >> normals.back().y;
        f >> normals.back().z;
        ignoreRestOfLine(&f);
  
      }else if(!strcmp(objCommand,"f") || !strcmp(objCommand,"fo")){
        char x[256];
        int strlen_x;
        faces.push_back(objFace());
  
        
get the number of vertices in this face and store it in the face struct.

  
        int oldpos = f.tellg(); //push file ptr
        f.getline(x,256);
        strlen_x=strlen(x);
        faces.back().count = 1;
        for(int i=0;i<strlen_x;i++){
              if(x[i]==' '||x[i]=='\t')faces.back().count++;
        }
        f.seekg(oldpos);//pop file ptr
  
        
get the number of forward slashes per line in order to categorise.

  
        oldpos = f.tellg(); //push file ptr
        f.getline(x,256);
        strlen_x=strlen(x);
        faces.back().type = 1;
        for(int i=0;i<strlen_x;i++){
              if(x[i]=='/')faces.back().type++;
              else if(x[i]==' '||x[i]=='\t')break;//only count the first one.
        }
        f.seekg(oldpos);//pop file ptr
  
        
validate vertex size to make sure this is a type of face-spec we know how to parse which is only 2, 3, and 4

  
        if(faces.back().count>4 ){
              complain("Unrecognized face vertex count.");
              ignoreRestOfLine(&f);
              continue;
        }
  
        
validate vertex.type - the data-depth. ie. how many numbers per chunk.

  
        if(faces.back().type!=3  && faces.back().type!=2 && faces.back().type!=1 ){
              complain("Unrecognized face vertex type.");
              ignoreRestOfLine(&f);
              continue;
        }
  
        
loop through and collect the appropriate data into the arrays.

  
        for(int thisVertexID=0;thisVertexID<faces.back().count;thisVertexID++){
              if(faces.back().count>=thisVertexID+1){
  
              //depending on the syntax of the face vertex chunk, parse accordingly
              if(faces.back().type==3){
                // \%i/\%i/\%i
  
                //collect the geometric vertex
                f.getline(x,256,'/');
                faces.back().vertices[thisVertexID] = strtol(x,NULL,10);
  
                //collect the texture vertex
                f.getline(x,256,'/');
                faces.back().texCoords[thisVertexID] = strtol(x,NULL,10);
  
                //collect the vertex normal, but beware of the end-of-line
                if(faces.back().count==thisVertexID+1)f.getline(x,256);
                else f.getline(x,256,' ');
                faces.back().normals[thisVertexID] = strtol(x,NULL,10);
  
            }else if(faces.back().type==2){
              // \%i/\%i
  
              //collect the geometric vertex
              f.getline(x,256,'/');
              faces.back().vertices[thisVertexID] = strtol(x,NULL,10);
  
              //collect the texture vertex, but beware of the end-of-line
              if(faces.back().count==thisVertexID+1)f.getline(x,256);
              else f.getline(x,256,' ');
              faces.back().texCoords[thisVertexID] = strtol(x,NULL,10);
  
            }else if(faces.back().type==1){
              // \%i
  
              //collect the geometric vertex, but beware of the end-of-line
              if(faces.back().count==thisVertexID+1)f.getline(x,256);
              else f.getline(x,256,' ');
              faces.back().vertices[thisVertexID] = strtol(x,NULL,10);
            }
  
          }
  
        }
  
      }else if(strlen(objCommand)==0){
      }else{
        if(objCommand[0]!='#'){
                  char s[256];
                  sprintf(s,"command token not parsed: \%s",objCommand);
                  complain(s);
             }
        ignoreRestOfLine(&f);
      }
    }
    f.close();
  
  }
  
  ofxObjLoader::~ofxObjLoader(){
  
  }
  
  objVertex ofxObjLoader::getVertex(int i){
    if(i<vertices.size())return vertices[i];
    else return vertices[0];
  }
  
  void ofxObjLoader::renderFace(int i){
    
draw the verts

  
  
    for(int ii=0;ii<faces[i].count;ii++){
          if(faces[i].type>3){
            glTexCoord2f(texCoords[faces[i].texCoords[ii]-1].x,
                     texCoords[faces[i].texCoords[ii]-1].y);
          }
  
          if(faces[i].type>2){
            glNormal3f(normals[faces[i].normals[ii]-1].x,
                   normals[faces[i].normals[ii]-1].y,
                   normals[faces[i].normals[ii]-1].z);
          }
  
          int index = faces[i].vertices[ii]-1;
          float x=vertices[index].x;
          float y=vertices[index].y;
          float z=vertices[index].z;
          glVertex3f(x,y,z);
    }
  }
  
  void ofxObjLoader::fillFaces(){
  if defined(__DARWIN__)
    glEnable(GL_RESCALE_NORMAL);
  endif
    for(int i=0;i<faces.size();i++){
      glBegin(GL_TRIANGLE_FAN);
      renderFace(i);
      glEnd();
    }
  }
  
  void ofxObjLoader::outlineFaces(){
    for(int i=0;i<faces.size();i++){
      glBegin(GL_LINE_LOOP);
      renderFace(i);
      glEnd();
    }
  }
  
  void ofxObjLoader::pointVertices(){
    for(int i=0;i<faces.size();i++){
      glBegin(GL_POINTS);
      renderFace(i);
      glEnd();
    }
  }
  
  void ofxObjLoader::ignoreRestOfLine(ifstream *f){
    char buff[256];
    f->getline(buff,256);
    //ok, now skip empty lines as well.
    if(f->peek()=='\n'||f->peek()=='\r')ignoreRestOfLine(f);
  }
  
  void ofxObjLoader::complain(char *s){
    if(verbose)fprintf(stderr,"ofxObjLoader: \%s\n",s);
  }
  
  objVertex::objVertex(float xx,float yy,float zz){
          x=xx;
          y=yy;
          z=zz;
  }
  
  objVertex::objVertex(){
          x=0;
          y=0;
          z=0;
  }
  


(C) Æliens 04/09/2009

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.