obj文件的理解请参考:http://foolog.net/?p=941
要注意一点,obj文件中面的保存,有的是按照三角形(也就是只有三个点),有的是按照空间四边形保存(包含四个点),这里是按照四个点来的,注释中已经给出。
#ifndef GLUT_DISABLE_ATEXIT_HACK #define GLUT_DISABLE_ATEXIT_HACK #endif #define GLEW_STATIC #include <GL/glew.h> #include <GL/wglew.h> #include <GL/freeglut.h> #include <vector> #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> //for matrices #include <glm/gtc/type_ptr.hpp> //undefine if u want to use the default bending constraint of pbd #include<sstream> #include <fstream> #include<iostream> using namespace std; GLfloat rtx = 0.0f, rty = 0.0f, rtz = 0.0; GLfloat step = 0.1; //float exp1 = 1e-3; const int GRID_SIZE = 10; GLint viewport[4]; GLdouble PP[16]; int v_num; //记录点的数量 int vn_num;//记录法线的数量 int vt_num;// int f_num; //记录面的数量 GLfloat **vArr; //存放点的二维数组 GLfloat **vnArr;//存放法线的二维数组 int **fvArr; //存放面顶点的二维数组 int **fnArr; //存放面法线的二维数组 int readfile(string addrstr) //将文件内容读到数组中去 { int i; string s1; float f2,f3,f4; vArr=new GLfloat*[v_num]; for (i=0; i<v_num; i++) { vArr[i]=new GLfloat[3]; } vnArr=new GLfloat*[vn_num]; for (i=0; i<vn_num; i++) { vnArr[i]=new GLfloat[3]; } fvArr=new int*[f_num]; fnArr=new int*[f_num]; for (i=0; i<f_num; i++) { fvArr[i]=new int[4]; fnArr[i]=new int[3]; } ifstream infile(addrstr.c_str()); string sline;//每一行 int ii=0,jj=0,kk=0; while(getline(infile,sline)) { if(sline[0]=='v') { if(sline[1]=='n')//vn { istringstream sin(sline); sin>>s1>>f2>>f3>>f4; vnArr[ii][0]=f2; vnArr[ii][1]=f3; vnArr[ii][2]=f4; ii++; } else if(sline[1] == 't'){} else//v { istringstream sin(sline); sin>>s1>>f2>>f3>>f4; vArr[jj][0]=f2; vArr[jj][1]=f3; vArr[jj][2]=f4; jj++; } } if (sline[0]=='f') //读取面 { istringstream in(sline); GLfloat a; in>>s1;//去掉前缀f int i,k; //点数改这里 for(i=0; i<4; i++) { in>>s1; // cout<<s1<<endl; printf("%s\n",s1.c_str()); //取得顶点索引和法线索引 a=0; for(k=0; s1[k]!='/'; k++) { a=a*10+(s1[k]-48); } fvArr[kk][i]=a; a=0; for(k=k+2; s1[k]; k++) { a=a*10+(s1[k]-48);; } fnArr[kk][i]=a; } kk++; } } return 0; } void getLineNum(string addrstr){ //获取点数以及面数 // cout<<addrstr.c_str()<<endl; v_num = vn_num = f_num = vt_num = 0; ifstream infile(addrstr.c_str()); string sline;//每一行 while(getline(infile, sline)){ // cout<<sline<<endl; printf("%s\n",sline.c_str()); if(sline[0]=='v'){ if(sline[1] == 'n'){ vn_num ++; }else if(sline[1] =='t'){ //vt vt_num ++; }else{ v_num ++; } }else{ if(sline[0] == 'f'){ f_num ++; } } } } string s1; GLfloat f2,f3,f4; void DrawGrid() { glBegin(GL_LINES); glColor3f(0.5f, 0.5f, 0.5f); for(int i=-GRID_SIZE;i<=GRID_SIZE;i++) { glVertex3f((float)i,0,(float)-GRID_SIZE); glVertex3f((float)i,0,(float)GRID_SIZE); glVertex3f((float)-GRID_SIZE,0,(float)i); glVertex3f((float)GRID_SIZE,0,(float)i); } glEnd(); } void draw(void) { cout<<f_num; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glTranslatef(0,0,-10); glRotatef(15,1,0,0); DrawGrid(); glBegin(GL_LINES); glColor3f(1, 1, 1); for(int i = 0; i < f_num; i++){ int a0,a1,a2,a3; a0 = fvArr[i][0]-1; a1 = fvArr[i][1]-1; a2 = fvArr[i][2]-1; //点数改这里 a3 = fvArr[i][3]-1; glVertex3f(vArr[a0][0],vArr[a0][1],vArr[a0][2]); glVertex3f(vArr[a1][0],vArr[a1][1],vArr[a1][2]); cout<<vArr[a0][0]<<" line "<<vArr[a1][0]<<endl; glVertex3f(vArr[a1][0],vArr[a1][1],vArr[a1][2]); glVertex3f(vArr[a2][0],vArr[a2][1],vArr[a2][2]); cout<<vArr[a1][0]<<" line "<<vArr[a2][0]<<endl; glVertex3f(vArr[a2][0],vArr[a2][1],vArr[a2][2]); //点数改这里 glVertex3f(vArr[a3][0],vArr[a3][1],vArr[a3][2]); glVertex3f(vArr[a3][0],vArr[a3][1],vArr[a3][2]); cout<<vArr[a2][0]<<" line "<<vArr[a0][0]<<endl; glVertex3f(vArr[a0][0],vArr[a0][1],vArr[a0][2]); } glEnd(); glutSwapBuffers(); } void OnReshape(int nw, int nh) { glViewport(0,0,nw, nh); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60, (GLfloat)nw / (GLfloat)nh, 1.f, 100.0f); glGetIntegerv(GL_VIEWPORT, viewport); glGetDoublev(GL_PROJECTION_MATRIX, PP); glMatrixMode(GL_MODELVIEW); } //float step = 0.001; int main(int argc, char * argv[]) { getLineNum("yifu.obj"); readfile("yifu.obj"); glutInit(&argc, argv); glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); glutInitWindowPosition(100, 100); glutInitWindowSize(1024, 1024); glutCreateWindow("Hello OpenGL"); // init(); glutDisplayFunc(draw); // glutIdleFunc(draw); //指定程序空闲时调用函数 glutReshapeFunc(OnReshape); //指定窗口形状变化时的回调函数 glEnable(GL_DEPTH_TEST); glutMainLoop(); return 0; }