Advertisement
thecplusplusguy

Simple obj loader (OpenGL,SDL,C++) - objloader.cpp

Aug 9th, 2011
20,604
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.44 KB | None | 0 0
  1. //This example program is created by thecplusplusuy for demonstration purposes. It's a simple Wavefront (.obj) loader:
  2. //http://www.youtube.com/user/thecplusplusguy
  3. //Free source, modify if you want, LGPL licence (I guess), I would be happy, if you would not delete the link
  4. //so other people can see the tutorial
  5. //compile under Linux:
  6. //g++ objloader.cpp -lSDL -lGL -lGLU
  7. //under Windows, set the libraries as I showed you in the tutorial 0
  8. #include <windows.h>
  9. #include <SDL/SDL.h> //check your include folder, it may be just SDL.h
  10. #include <GL/gl.h>
  11. #include <GL/glu.h>
  12. #include <cstdlib>
  13. #include <vector>
  14. #include <string>
  15. #include <algorithm>
  16. #include <fstream>
  17. #include <cstdio>
  18. #include <iostream>
  19.  
  20.  
  21. struct coordinate{
  22.     float x,y,z;
  23.     coordinate(float a,float b,float c) : x(a),y(b),z(c) {};
  24. };
  25.  
  26. //for faces, it can contain triangles and quads as well, the four variable contain which is that
  27. struct face{
  28.     int facenum;
  29.     bool four;
  30.     int faces[4];
  31.     face(int facen,int f1,int f2,int f3) : facenum(facen){  //constructor for triangle
  32.         faces[0]=f1;
  33.         faces[1]=f2;
  34.         faces[2]=f3;
  35.         four=false;
  36.     }
  37.     face(int facen,int f1,int f2,int f3,int f4) : facenum(facen){ //overloaded constructor for quad
  38.         faces[0]=f1;
  39.         faces[1]=f2;
  40.         faces[2]=f3;
  41.         faces[3]=f4;
  42.         four=true;
  43.     }
  44. };
  45.  
  46. float angle=0.0;    //we rotate or object with angle degrees
  47.  
  48. int loadObject(const char* filename)
  49. {
  50.     std::vector<std::string*> coord;    //read every single line of the obj file as a string
  51.     std::vector<coordinate*> vertex;
  52.     std::vector<face*> faces;
  53.     std::vector<coordinate*> normals;   //normal vectors for every face
  54.     std::ifstream in(filename); //open the .obj file
  55.     if(!in.is_open())   //if not opened, exit with -1
  56.     {
  57.         std::cout << "Nor oepened" << std::endl;
  58.         return -1;
  59.     }
  60.     char buf[256];
  61.     //read in every line to coord
  62.     while(!in.eof())
  63.     {
  64.         in.getline(buf,256);
  65.         coord.push_back(new std::string(buf));
  66.     }
  67.     //go through all of the elements of coord, and decide what kind of element is that
  68.     for(int i=0;i<coord.size();i++)
  69.     {
  70.         if(coord[i]->c_str()[0]=='#')   //if it is a comment (the first character is #)
  71.             continue;   //we don't care about that
  72.         else if(coord[i]->c_str()[0]=='v' && coord[i]->c_str()[1]==' ') //if vector
  73.         {
  74.             float tmpx,tmpy,tmpz;
  75.             sscanf(coord[i]->c_str(),"v %f %f %f",&tmpx,&tmpy,&tmpz);   //read in the 3 float coordinate to tmpx,tmpy,tmpz
  76.             vertex.push_back(new coordinate(tmpx,tmpy,tmpz));   //and then add it to the end of our vertex list
  77.         }else if(coord[i]->c_str()[0]=='v' && coord[i]->c_str()[1]=='n')    //if normal vector
  78.         {
  79.             float tmpx,tmpy,tmpz;   //do the same thing
  80.             sscanf(coord[i]->c_str(),"vn %f %f %f",&tmpx,&tmpy,&tmpz);
  81.             normals.push_back(new coordinate(tmpx,tmpy,tmpz)); 
  82.         }else if(coord[i]->c_str()[0]=='f') //if face
  83.         {
  84.             int a,b,c,d,e;
  85.             if(count(coord[i]->begin(),coord[i]->end(),' ')==3) //if it is a triangle (it has 3 space in it)
  86.             {
  87.           sscanf(coord[i]->c_str(),"f %d//%d %d//%d %d//%d",&a,&b,&c,&b,&d,&b);
  88.                 faces.push_back(new face(b,a,c,d)); //read in, and add to the end of the face list
  89.             }else{
  90.                 sscanf(coord[i]->c_str(),"f %d//%d %d//%d %d//%d %d//%d",&a,&b,&c,&b,&d,&b,&e,&b);
  91.                 faces.push_back(new face(b,a,c,d,e));   //do the same, except we call another constructor, and we use different pattern
  92.             }
  93.         }
  94.     }
  95. //raw
  96.     int num;    //the id for the list
  97.     num=glGenLists(1);  //generate a uniqe
  98.     glNewList(num,GL_COMPILE);  //and create it
  99.     for(int i=0;i<faces.size();i++)
  100.     {
  101.         if(faces[i]->four)  //if it's a quad draw a quad
  102.         {
  103.             glBegin(GL_QUADS);
  104.                 //basically all I do here, is use the facenum (so the number of the face) as an index for the normal, so the 1st normal owe to the first face
  105.                 //I subtract 1 because the index start from 0 in C++
  106.                 glNormal3f(normals[faces[i]->facenum-1]->x,normals[faces[i]->facenum-1]->y,normals[faces[i]->facenum-1]->z);
  107.                 //draw the faces
  108.                 glVertex3f(vertex[faces[i]->faces[0]-1]->x,vertex[faces[i]->faces[0]-1]->y,vertex[faces[i]->faces[0]-1]->z);
  109.                 glVertex3f(vertex[faces[i]->faces[1]-1]->x,vertex[faces[i]->faces[1]-1]->y,vertex[faces[i]->faces[1]-1]->z);
  110.                 glVertex3f(vertex[faces[i]->faces[2]-1]->x,vertex[faces[i]->faces[2]-1]->y,vertex[faces[i]->faces[2]-1]->z);
  111.                 glVertex3f(vertex[faces[i]->faces[3]-1]->x,vertex[faces[i]->faces[3]-1]->y,vertex[faces[i]->faces[3]-1]->z);
  112.             glEnd();
  113.         }else{
  114.             glBegin(GL_TRIANGLES);
  115.                 glNormal3f(normals[faces[i]->facenum-1]->x,normals[faces[i]->facenum-1]->y,normals[faces[i]->facenum-1]->z);
  116.                 glVertex3f(vertex[faces[i]->faces[0]-1]->x,vertex[faces[i]->faces[0]-1]->y,vertex[faces[i]->faces[0]-1]->z);
  117.                 glVertex3f(vertex[faces[i]->faces[1]-1]->x,vertex[faces[i]->faces[1]-1]->y,vertex[faces[i]->faces[1]-1]->z);
  118.                 glVertex3f(vertex[faces[i]->faces[2]-1]->x,vertex[faces[i]->faces[2]-1]->y,vertex[faces[i]->faces[2]-1]->z);
  119.             glEnd();
  120.         }
  121.     }
  122.     glEndList();
  123.     //delete everything to avoid memory leaks
  124.     for(int i=0;i<coord.size();i++)
  125.         delete coord[i];
  126.     for(int i=0;i<faces.size();i++)
  127.         delete faces[i];
  128.     for(int i=0;i<normals.size();i++)
  129.         delete normals[i];
  130.     for(int i=0;i<vertex.size();i++)
  131.         delete vertex[i];
  132.     return num; //return with the id
  133. }
  134.  
  135. int cube;
  136. void init()
  137. {
  138.     glClearColor(0.0,0.0,0.0,1.0);
  139.     glMatrixMode(GL_PROJECTION);
  140.     glLoadIdentity();
  141.     gluPerspective(45,640.0/480.0,1.0,500.0);
  142.     glMatrixMode(GL_MODELVIEW);
  143.     glEnable(GL_DEPTH_TEST);
  144.     cube=loadObject("test.obj");    //load the test.obj file
  145.     glEnable(GL_LIGHTING);  //we enable lighting, to make the 3D object to 3D
  146.     glEnable(GL_LIGHT0);
  147.     float col[]={1.0,1.0,1.0,1.0};  //light color is white
  148.     glLightfv(GL_LIGHT0,GL_DIFFUSE,col);
  149. }
  150.  
  151. void display()
  152. {
  153.     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  154.     glLoadIdentity();
  155.     float pos[]={-1.0,1.0,-2.0,1.0};    //set the position
  156.     glLightfv(GL_LIGHT0,GL_POSITION,pos);
  157.     glTranslatef(0.0,0.0,-5.0);
  158.     glRotatef(angle,0.0,0.0,1.0);
  159.     glCallList(cube);   //draw the 3D mesh
  160. }
  161.  
  162.  
  163. int main(int argc,char** argv)
  164. {
  165.     SDL_Init(SDL_INIT_EVERYTHING);
  166.     SDL_Surface* screen=SDL_SetVideoMode(640,480,32,SDL_SWSURFACE|SDL_OPENGL);
  167.     bool running=true;
  168.     Uint32 start;
  169.     SDL_Event event;
  170.     init();
  171.     while(running)
  172.     {
  173.         start=SDL_GetTicks();
  174.         while(SDL_PollEvent(&event))
  175.         {
  176.             switch(event.type)
  177.             {
  178.                 case SDL_QUIT:
  179.                     running=false;
  180.                     break;
  181.             }
  182.         }
  183.         display();
  184.         SDL_GL_SwapBuffers();
  185.         angle+=0.5;
  186.         if(angle>360)
  187.             angle-=360;
  188.         if(1000/30>(SDL_GetTicks()-start))
  189.             SDL_Delay(1000/30-(SDL_GetTicks()-start));
  190.     }
  191.     SDL_Quit();
  192.     return 0;  
  193. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement