thecplusplusguy

Smooth normals - objloader.cpp

Aug 31st, 2011
2,117
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.94 KB | None | 0 0
  1. //http://www.youtube.com/user/thecplusplusguy
  2. #include "objloader.h"
  3.  
  4.     coordinate::coordinate(float a,float b,float c)
  5.     {
  6.         x=a;
  7.         y=b;
  8.         z=c;
  9.     }
  10.     face::face(int facen,int f1,int f2,int f3,int t1,int t2,int t3,int m){
  11.         facenum=facen;
  12.         faces[0]=f1;
  13.         faces[1]=f2;
  14.         faces[2]=f3;
  15.         texcoord[0]=t1;
  16.         texcoord[1]=t2;
  17.         texcoord[2]=t3;
  18.         mat=m;
  19.         four=false;
  20.     }
  21.     face::face(int facen,int f1,int f2,int f3,int f4,int t1,int t2,int t3,int t4,int m){
  22.         facenum=facen;
  23.         faces[0]=f1;
  24.         faces[1]=f2;
  25.         faces[2]=f3;
  26.         faces[3]=f4;
  27.         texcoord[0]=t1;
  28.         texcoord[1]=t2;
  29.         texcoord[2]=t3;
  30.         texcoord[3]=t4;
  31.         mat=m;
  32.         four=true;
  33.     }
  34.    
  35.     material::material(const char* na,float al,float n,float ni2,float* d,float* a,float* s,int i,int t)
  36.     {
  37.         name=na;
  38.         alpha=al;
  39.         ni=ni2;
  40.         ns=n;
  41.         dif[0]=d[0];
  42.         dif[1]=d[1];
  43.         dif[2]=d[2];
  44.        
  45.         amb[0]=a[0];
  46.         amb[1]=a[1];
  47.         amb[2]=a[2];
  48.        
  49.         spec[0]=s[0];
  50.         spec[1]=s[1];
  51.         spec[2]=s[2];
  52.        
  53.         illum=i;
  54.         texture=t;
  55.     }
  56.    
  57.     texcoord::texcoord(float a,float b)
  58.     {
  59.         u=a;
  60.         v=b;
  61.     }
  62.  
  63. int objloader::load(const char* filename)
  64. {
  65.     std::ifstream in(filename);
  66.     if(!in.is_open())
  67.     {
  68.         std::cout << "Nor oepened" << std::endl;
  69.         return -1;
  70.     }
  71.     char buf[256];
  72.     int curmat=0;
  73.     while(!in.eof())
  74.     {
  75.         in.getline(buf,256);
  76.         coord.push_back(new std::string(buf));
  77.     }
  78.     for(int i=0;i<coord.size();i++)
  79.     {
  80.         if((*coord[i])[0]=='#')
  81.             continue;
  82.         else if((*coord[i])[0]=='v' && (*coord[i])[1]==' ')
  83.         {
  84.             float tmpx,tmpy,tmpz;
  85.             sscanf(coord[i]->c_str(),"v %f %f %f",&tmpx,&tmpy,&tmpz);
  86.             vertex.push_back(new coordinate(tmpx,tmpy,tmpz));
  87.         }else if((*coord[i])[0]=='v' && (*coord[i])[1]=='n')
  88.         {
  89.             float tmpx,tmpy,tmpz;
  90.             sscanf(coord[i]->c_str(),"vn %f %f %f",&tmpx,&tmpy,&tmpz);
  91.             normals.push_back(new coordinate(tmpx,tmpy,tmpz)); 
  92.         }else if((*coord[i])[0]=='f')
  93.         {
  94.             int a,b,c,d,e;
  95.             if(count(coord[i]->begin(),coord[i]->end(),' ')==4)
  96.             {
  97.                 if(coord[i]->find("//")!=std::string::npos)
  98.                 {
  99.                     sscanf(coord[i]->c_str(),"f %d//%d %d//%d %d//%d %d//%d",&a,&b,&c,&b,&d,&b,&e,&b);
  100.                     faces.push_back(new face(b,a,c,d,e,0,0,0,0,curmat));
  101.                 }else if(coord[i]->find("/")!=std::string::npos)
  102.                 {
  103.                     int t[4];
  104.                     sscanf(coord[i]->c_str(),"f %d/%d/%d %d/%d/%d %d/%d/%d %d/%d/%d",&a,&t[0],&b,&c,&t[1],&b,&d,&t[2],&b,&e,&t[3],&b);
  105.                     faces.push_back(new face(b,a,c,d,e,t[0],t[1],t[2],t[3],curmat));
  106.                 }else{
  107.                     sscanf(coord[i]->c_str(),"f %d %d %d %d",&a,&b,&c,&d);
  108.                     faces.push_back(new face(-1,a,b,c,d,0,0,0,0,curmat));                  
  109.                 }
  110.             }else{
  111.                     if(coord[i]->find("//")!=std::string::npos)
  112.                     {
  113.                         sscanf(coord[i]->c_str(),"f %d//%d %d//%d %d//%d",&a,&b,&c,&b,&d,&b);
  114.                         faces.push_back(new face(b,a,c,d,0,0,0,curmat));
  115.                     }else if(coord[i]->find("/")!=std::string::npos)
  116.                     {
  117.                         int t[3];
  118.                         sscanf(coord[i]->c_str(),"f %d/%d/%d %d/%d/%d %d/%d/%d",&a,&t[0],&b,&c,&t[1],&b,&d,&t[2],&b);
  119.                         faces.push_back(new face(b,a,c,d,t[0],t[1],t[2],curmat));
  120.                     }else{
  121.                         sscanf(coord[i]->c_str(),"f %d %d %d",&a,&b,&c);
  122.                         faces.push_back(new face(-1,a,b,c,0,0,0,curmat));                  
  123.                     }
  124.             }
  125.     }else if((*coord[i])[0]=='u' && (*coord[i])[1]=='s' && (*coord[i])[2]=='e')
  126.     {
  127.         char tmp[200];
  128.         sscanf(coord[i]->c_str(),"usemtl %s",tmp);
  129.         for(int i=0;i<materials.size();i++)
  130.         {
  131.             if(strcmp(materials[i]->name.c_str(),tmp)==0)
  132.             {
  133.                 curmat=i;
  134.                 break;
  135.             }
  136.         }
  137.     }else if((*coord[i])[0]=='m' && (*coord[i])[1]=='t' && (*coord[i])[2]=='l' && (*coord[i])[3]=='l')
  138.     {
  139.         char filen[200];
  140.         sscanf(coord[i]->c_str(),"mtllib %s",filen);
  141.         std::ifstream mtlin(filen);
  142.         if(!mtlin.is_open())
  143.         {
  144.             std::cout << "connot open the material file" << std::endl;
  145.             clean();
  146.             return -1;
  147.         }
  148.         ismaterial=true;
  149.         std::vector<std::string> tmp;
  150.         char c[200];
  151.         while(!mtlin.eof())
  152.         {
  153.             mtlin.getline(c,200);
  154.             tmp.push_back(c);
  155.         }
  156.         char name[200];
  157.         char filename[200];
  158.         float amb[3],dif[3],spec[3],alpha,ns,ni;
  159.         int illum;
  160.         unsigned int texture;
  161.         bool ismat=false;
  162.         strcpy(filename,"\0");
  163.         std::cout << tmp.size() << std::endl;
  164.         for(int i=0;i<tmp.size();i++)
  165.         {
  166.             if(tmp[i][0]=='#')
  167.                 continue;
  168.             if(tmp[i][0]=='n' && tmp[i][1]=='e' && tmp[i][2]=='w')
  169.             {
  170.                 if(ismat)
  171.                 {
  172.                     if(strcmp(filename,"\0")!=0)
  173.                     {
  174.                         materials.push_back(new material(name,alpha,ns,ni,dif,amb,spec,illum,texture));
  175.                         strcpy(filename,"\0");
  176.                     }else{
  177.                             materials.push_back(new material(name,alpha,ns,ni,dif,amb,spec,illum,-1));             
  178.                     }
  179.                 }
  180.                 ismat=false;
  181.                 sscanf(tmp[i].c_str(),"newmtl %s",name);
  182.             }else if(tmp[i][0]=='N' && tmp[i][1]=='s')
  183.             {
  184.                 sscanf(tmp[i].c_str(),"Ns %f",&ns);
  185.                 ismat=true;
  186.             }else if(tmp[i][0]=='K' && tmp[i][1]=='a')
  187.             {
  188.                 sscanf(tmp[i].c_str(),"Ka %f %f %f",&amb[0],&amb[1],&amb[2]);
  189.                 ismat=true;
  190.             }else if(tmp[i][0]=='K' && tmp[i][1]=='d')
  191.             {
  192.                 sscanf(tmp[i].c_str(),"Kd %f %f %f",&dif[0],&dif[1],&dif[2]);
  193.                 ismat=true;
  194.             }else if(tmp[i][0]=='K' && tmp[i][1]=='s')
  195.             {
  196.                 sscanf(tmp[i].c_str(),"Ks %f %f %f",&spec[0],&spec[1],&spec[2]);
  197.                 ismat=true;
  198.             }else if(tmp[i][0]=='N' && tmp[i][1]=='i')
  199.             {
  200.                 sscanf(tmp[i].c_str(),"Ni %f",&ni);
  201.                 ismat=true;
  202.             }else if(tmp[i][0]=='d' && tmp[i][1]==' ')
  203.             {
  204.                 sscanf(tmp[i].c_str(),"d %f",&alpha);
  205.                 ismat=true;
  206.             }else if(tmp[i][0]=='i' && tmp[i][1]=='l')
  207.             {
  208.                 sscanf(tmp[i].c_str(),"illum %d",&illum);
  209.                 ismat=true;
  210.             }else if(tmp[i][0]=='m' && tmp[i][1]=='a')
  211.             {
  212.                 sscanf(tmp[i].c_str(),"map_Kd %s",filename);
  213.                 texture=loadTexture(filename);
  214.                 ismat=true;
  215.             }
  216.         }
  217.                 if(ismat)
  218.                 {
  219.                     if(strcmp(filename,"\0")!=0)
  220.                     {
  221.                         materials.push_back(new material(name,alpha,ns,ni,dif,amb,spec,illum,texture));
  222.                     }else{
  223.                             materials.push_back(new material(name,alpha,ns,ni,dif,amb,spec,illum,-1));             
  224.                     }
  225.                 }
  226.     }else if((*coord[i])[0]=='v' && (*coord[i])[1]=='t')
  227.     {
  228.         float u,v;
  229.         sscanf(coord[i]->c_str(),"vt %f %f",&u,&v);
  230.         texturecoordinate.push_back(new texcoord(u,1-v));
  231.         istexture=true;
  232.     }
  233. }
  234.     if(materials.size()==0)
  235.         ismaterial=false;
  236.     else
  237.         ismaterial=true;
  238.     std::cout << vertex.size() << " " << normals.size() << " " << faces.size() << " " << materials.size() << std::endl;
  239.     //draw
  240.     if(isvertexnormal)
  241.         smoothnormals();
  242.     int num;
  243.     num=glGenLists(1);
  244.     glNewList(num,GL_COMPILE);
  245.     int last=-1;
  246.     for(int i=0;i<faces.size();i++)
  247.     {
  248.         if(last!=faces[i]->mat && ismaterial)
  249.         {
  250.             float diffuse[]={materials[faces[i]->mat]->dif[0],materials[faces[i]->mat]->dif[1],materials[faces[i]->mat]->dif[2],1.0};
  251.             float ambient[]={materials[faces[i]->mat]->amb[0],materials[faces[i]->mat]->amb[1],materials[faces[i]->mat]->amb[2],1.0};
  252.             float specular[]={materials[faces[i]->mat]->spec[0],materials[faces[i]->mat]->spec[1],materials[faces[i]->mat]->spec[2],1.0};
  253.             glMaterialfv(GL_FRONT,GL_DIFFUSE,diffuse);
  254.             glMaterialfv(GL_FRONT,GL_AMBIENT,ambient);
  255.             glMaterialfv(GL_FRONT,GL_SPECULAR,specular);
  256.             glMaterialf(GL_FRONT,GL_SHININESS,materials[faces[i]->mat]->ns);
  257.             last=faces[i]->mat;
  258.             if(materials[faces[i]->mat]->texture==-1)
  259.                 glDisable(GL_TEXTURE_2D);
  260.             else{
  261.                 glEnable(GL_TEXTURE_2D);
  262.                 glBindTexture(GL_TEXTURE_2D,materials[faces[i]->mat]->texture);
  263.             }
  264.         }
  265.         if(faces[i]->four)
  266.         {
  267.             glBegin(GL_QUADS);
  268.                 glNormal3f(normals[faces[i]->facenum-1]->x,normals[faces[i]->facenum-1]->y,normals[faces[i]->facenum-1]->z);
  269.                
  270.                 if(istexture && materials[faces[i]->mat]->texture!=-1)
  271.                     glTexCoord2f(texturecoordinate[faces[i]->texcoord[0]-1]->u,texturecoordinate[faces[i]->texcoord[0]-1]->v);
  272.  
  273.                 if(isvertexnormal)
  274.                     glNormal3f(vertexnormals[faces[i]->faces[0]-1]->x,vertexnormals[faces[i]->faces[0]-1]->y,vertexnormals[faces[i]->faces[0]-1]->z);
  275.  
  276.                
  277.                 glVertex3f(vertex[faces[i]->faces[0]-1]->x,vertex[faces[i]->faces[0]-1]->y,vertex[faces[i]->faces[0]-1]->z);
  278.                
  279.                 if(istexture && materials[faces[i]->mat]->texture!=-1)
  280.                     glTexCoord2f(texturecoordinate[faces[i]->texcoord[1]-1]->u,texturecoordinate[faces[i]->texcoord[1]-1]->v);
  281.  
  282.  
  283.                 if(isvertexnormal)
  284.                     glNormal3f(vertexnormals[faces[i]->faces[1]-1]->x,vertexnormals[faces[i]->faces[1]-1]->y,vertexnormals[faces[i]->faces[1]-1]->z);
  285.                
  286.                 glVertex3f(vertex[faces[i]->faces[1]-1]->x,vertex[faces[i]->faces[1]-1]->y,vertex[faces[i]->faces[1]-1]->z);
  287.                
  288.                 if(istexture && materials[faces[i]->mat]->texture!=-1)
  289.                     glTexCoord2f(texturecoordinate[faces[i]->texcoord[2]-1]->u,texturecoordinate[faces[i]->texcoord[2]-1]->v);
  290.  
  291.                 if(isvertexnormal)
  292.                     glNormal3f(vertexnormals[faces[i]->faces[2]-1]->x,vertexnormals[faces[i]->faces[2]-1]->y,vertexnormals[faces[i]->faces[2]-1]->z);
  293.  
  294.                 glVertex3f(vertex[faces[i]->faces[2]-1]->x,vertex[faces[i]->faces[2]-1]->y,vertex[faces[i]->faces[2]-1]->z);
  295.                
  296.                 if(istexture && materials[faces[i]->mat]->texture!=-1)
  297.                     glTexCoord2f(texturecoordinate[faces[i]->texcoord[3]-1]->u,texturecoordinate[faces[i]->texcoord[3]-1]->v);
  298.  
  299.                 if(isvertexnormal)
  300.                     glNormal3f(vertexnormals[faces[i]->faces[3]-1]->x,vertexnormals[faces[i]->faces[3]-1]->y,vertexnormals[faces[i]->faces[3]-1]->z);
  301.            
  302.                 glVertex3f(vertex[faces[i]->faces[3]-1]->x,vertex[faces[i]->faces[3]-1]->y,vertex[faces[i]->faces[3]-1]->z);
  303.             glEnd();
  304.         }else{
  305.             glBegin(GL_TRIANGLES);
  306.                 glNormal3f(normals[faces[i]->facenum-1]->x,normals[faces[i]->facenum-1]->y,normals[faces[i]->facenum-1]->z);
  307.  
  308.                 if(istexture && materials[faces[i]->mat]->texture!=-1)
  309.                     glTexCoord2f(texturecoordinate[faces[i]->texcoord[0]-1]->u,texturecoordinate[faces[i]->texcoord[0]-1]->v);
  310.  
  311.                 if(isvertexnormal)
  312.                     glNormal3f(vertexnormals[faces[i]->faces[0]-1]->x,vertexnormals[faces[i]->faces[0]-1]->y,vertexnormals[faces[i]->faces[0]-1]->z);
  313.  
  314.  
  315.                 glVertex3f(vertex[faces[i]->faces[0]-1]->x,vertex[faces[i]->faces[0]-1]->y,vertex[faces[i]->faces[0]-1]->z);
  316.                
  317.                 if(istexture && materials[faces[i]->mat]->texture!=-1)
  318.                     glTexCoord2f(texturecoordinate[faces[i]->texcoord[1]-1]->u,texturecoordinate[faces[i]->texcoord[1]-1]->v);
  319.                
  320.                
  321.                 if(isvertexnormal)
  322.                     glNormal3f(vertexnormals[faces[i]->faces[1]-1]->x,vertexnormals[faces[i]->faces[1]-1]->y,vertexnormals[faces[i]->faces[1]-1]->z);
  323.                
  324.                 glVertex3f(vertex[faces[i]->faces[1]-1]->x,vertex[faces[i]->faces[1]-1]->y,vertex[faces[i]->faces[1]-1]->z);
  325.                
  326.                
  327.                 if(istexture && materials[faces[i]->mat]->texture!=-1)
  328.                     glTexCoord2f(texturecoordinate[faces[i]->texcoord[2]-1]->u,texturecoordinate[faces[i]->texcoord[2]-1]->v);
  329.  
  330.  
  331.                 if(isvertexnormal)
  332.                     glNormal3f(vertexnormals[faces[i]->faces[2]-1]->x,vertexnormals[faces[i]->faces[2]-1]->y,vertexnormals[faces[i]->faces[2]-1]->z);
  333.        
  334.                 glVertex3f(vertex[faces[i]->faces[2]-1]->x,vertex[faces[i]->faces[2]-1]->y,vertex[faces[i]->faces[2]-1]->z);
  335.             glEnd();
  336.         }
  337.     }
  338.     glEndList();
  339.     clean();
  340.     lists.push_back(num);
  341.     return num;
  342. }
  343.  
  344. void objloader::clean()
  345. {
  346.     for(int i=0;i<coord.size();i++)
  347.         delete coord[i];
  348.     for(int i=0;i<faces.size();i++)
  349.         delete faces[i];
  350.     for(int i=0;i<normals.size();i++)
  351.         delete normals[i];
  352.     for(int i=0;i<vertex.size();i++)
  353.         delete vertex[i];
  354.     for(int i=0;i<materials.size();i++)
  355.         delete materials[i];
  356.     for(int i=0;i<texturecoordinate.size();i++)
  357.         delete texturecoordinate[i];
  358.     for(int i=0;i<vertexnormals.size();i++)
  359.         delete vertexnormals[i];
  360.        
  361.     coord.clear();
  362.     faces.clear();
  363.     normals.clear();
  364.     vertex.clear();
  365.     materials.clear();
  366.     texturecoordinate.clear();
  367.     vertexnormals.clear();
  368. }
  369.  
  370. objloader::~objloader()
  371. {
  372.     for(std::vector<unsigned int>::const_iterator it=texture.begin();it!=texture.end();it++)
  373.     {
  374.         glDeleteTextures(1,&(*it));
  375.     }
  376.     for(std::vector<unsigned int>::const_iterator it=lists.begin();it!=lists.end();it++)
  377.     {
  378.         glDeleteLists(*it,1);
  379.     }
  380. }
  381.  
  382. unsigned int objloader::loadTexture(const char* filename)
  383. {
  384.     unsigned int num;
  385.     glGenTextures(1,&num);
  386.     SDL_Surface* img=SDL_LoadBMP(filename);
  387.     glBindTexture(GL_TEXTURE_2D,num);
  388.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
  389.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
  390.     glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,img->w,img->h,0,GL_RGB,GL_UNSIGNED_SHORT_5_6_5,img->pixels);
  391.     glTexEnvi(GL_TEXTURE_2D,GL_TEXTURE_ENV_MODE,GL_MODULATE);
  392.     SDL_FreeSurface(img);
  393.     texture.push_back(num);
  394.     return num;
  395. }
  396.  
  397. objloader::objloader()
  398. {
  399.     ismaterial=false;
  400.     isnormals=false;
  401.     istexture=false;
  402.     isvertexnormal=true;
  403. }
  404.  
  405. void objloader::smoothnormals()
  406. {
  407.     for(int i=1;i<vertex.size()+1;i++)
  408.     {
  409.         float vecX=0.0,vecY=0.0,vecZ=0.0;
  410.         int num=0;
  411.         for(int j=0;j<faces.size();j++)
  412.         {
  413.             if(faces[j]->faces[0]==i || faces[j]->faces[1]==i || faces[j]->faces[2]==i || faces[j]->faces[3]==i)
  414.             {
  415.                 vecX+=normals[faces[j]->facenum-1]->x;
  416.                 vecY+=normals[faces[j]->facenum-1]->y;
  417.                 vecZ+=normals[faces[j]->facenum-1]->z;
  418.                 num++;
  419.             }
  420.         }
  421.         if(num)
  422.         {
  423.             vecX/=num;
  424.             vecY/=num;
  425.             vecZ/=num;
  426.         }
  427.         float d=sqrt(vecX*vecX+vecY*vecY+vecZ*vecZ);
  428.         if(d)
  429.         {
  430.             vecX/=d;
  431.             vecY/=d;
  432.             vecZ/=d;
  433.         }
  434.         vertexnormals.push_back(new coordinate(vecX,vecY,vecZ));
  435.     }
  436. }
Advertisement
Add Comment
Please, Sign In to add comment