读取三维网格模型(Wavefront OBJ文件)
无法向立方体:cube.obj
有法向兔子模型:bunny.obj
有法向有纹理八字模型:Eight.obj
OBJ文件的格式可参考:http://www.cnblogs.com/youthlion/archive/2013/01/21/2870451.html
利用OpenGL显示该模型的绘制效果(全部)
顶点显示
线条显示
面片显示
核心代码说说
1、下面的点、纹理、法向量、面用于构成一个PIC的类,PIC用于存储从OBJ文件中读取的3D图形的信息:
1 struct POINT3{ 2 double X; 3 double Y; 4 double Z; 5 }; 6 struct WenLi{ 7 double TU; 8 double TV; 9 }; 10 struct FaXiangLiang{ 11 double NX; 12 double NY; 13 double NZ; 14 }; 15 struct Mian{ 16 int V[3]; 17 int T[3]; 18 int N[3]; 19 }; 20 class PIC 21 { 22 public: 23 vector<POINT3> V;//V:代表顶点。格式为V X Y Z,V后面的X Y Z表示三个顶点坐标。浮点型 24 vector<WenLi> VT;//表示纹理坐标。格式为VT TU TV。浮点型 25 vector<FaXiangLiang> VN;//VN:法向量。每个三角形的三个顶点都要指定一个法向量。格式为VN NX NY NZ。浮点型 26 vector<Mian> F;//F:面。面后面跟着的整型值分别是属于这个面的顶点、纹理坐标、法向量的索引。 27 //面的格式为:f Vertex1/Texture1/Normal1 Vertex2/Texture2/Normal2 Vertex3/Texture3/Normal3 28 };
2、下面函数用于读取obj文件并将信息保存在PIC实例的对象中:
1 void CMainWnd::ReadPIC() 2 { 3 ifstream ifs(name);//cube bunny Eight 4 string s; 5 Mian *f; 6 POINT3 *v; 7 FaXiangLiang *vn; 8 WenLi *vt; 9 while(getline(ifs,s)) 10 { 11 if(s.length()<2)continue; 12 if(s[0]=='v'){ 13 if(s[1]=='t'){//vt 0.581151 0.979929 纹理 14 istringstream in(s); 15 vt=new WenLi(); 16 string head; 17 in>>head>>vt->TU>>vt->TV; 18 m_pic.VT.push_back(*vt); 19 }else if(s[1]=='n'){//vn 0.637005 -0.0421857 0.769705 法向量 20 istringstream in(s); 21 vn=new FaXiangLiang(); 22 string head; 23 in>>head>>vn->NX>>vn->NY>>vn->NZ; 24 m_pic.VN.push_back(*vn); 25 }else{//v -53.0413 158.84 -135.806 点 26 istringstream in(s); 27 v=new POINT3(); 28 string head; 29 in>>head>>v->X>>v->Y>>v->Z; 30 m_pic.V.push_back(*v); 31 } 32 } 33 else if(s[0]=='f'){//f 2443//2656 2442//2656 2444//2656 面 34 for(int k=s.size()-1;k>=0;k--){ 35 if(s[k]=='/')s[k]=' '; 36 } 37 istringstream in(s); 38 f=new Mian(); 39 string head; 40 in>>head; 41 int i=0; 42 while(i<3) 43 { 44 if(m_pic.V.size()!=0) 45 { 46 in>>f->V[i]; 47 f->V[i]-=1; 48 } 49 if(m_pic.VT.size()!=0) 50 { 51 in>>f->T[i]; 52 f->T[i]-=1; 53 } 54 if(m_pic.VN.size()!=0) 55 { 56 in>>f->N[i]; 57 f->N[i]-=1; 58 } 59 i++; 60 } 61 m_pic.F.push_back(*f); 62 } 63 } 64 }
3、下面函数用于根据保存在obj中图形利用openGL中的函数绘制出来:
1 void CMainWnd::GLCube() 2 { 3 for(int i=0;i<m_pic.F.size();i++) 4 { 5 glBegin(GL_POINTS); // 绘制三角形GL_TRIANGLES;GL_LINE_LOOP;GL_LINES;GL_POINTS 6 if(m_pic.VT.size()!=0)glTexCoord2f(m_pic.VT[m_pic.F[i].T[0]].TU,m_pic.VT[m_pic.F[i].T[0]].TV); //纹理 7 if(m_pic.VN.size()!=0)glNormal3f(m_pic.VN[m_pic.F[i].N[0]].NX,m_pic.VN[m_pic.F[i].N[0]].NY,m_pic.VN[m_pic.F[i].N[0]].NZ);//法向量 8 glVertex3f(m_pic.V[m_pic.F[i].V[0]].X/YU,m_pic.V[m_pic.F[i].V[0]].Y/YU, m_pic.V[m_pic.F[i].V[0]].Z/YU); // 上顶点 9 10 if(m_pic.VT.size()!=0)glTexCoord2f(m_pic.VT[m_pic.F[i].T[1]].TU,m_pic.VT[m_pic.F[i].T[1]].TV); //纹理 11 if(m_pic.VN.size()!=0)glNormal3f(m_pic.VN[m_pic.F[i].N[1]].NX,m_pic.VN[m_pic.F[i].N[1]].NY,m_pic.VN[m_pic.F[i].N[1]].NZ);//法向量 12 glVertex3f(m_pic.V[m_pic.F[i].V[1]].X/YU,m_pic.V[m_pic.F[i].V[1]].Y/YU, m_pic.V[m_pic.F[i].V[1]].Z/YU); // 左下 13 14 if(m_pic.VT.size()!=0)glTexCoord2f(m_pic.VT[m_pic.F[i].T[2]].TU,m_pic.VT[m_pic.F[i].T[2]].TV); //纹理 15 if(m_pic.VN.size()!=0)glNormal3f(m_pic.VN[m_pic.F[i].N[2]].NX,m_pic.VN[m_pic.F[i].N[2]].NY,m_pic.VN[m_pic.F[i].N[2]].NZ);//法向量 16 glVertex3f(m_pic.V[m_pic.F[i].V[2]].X/YU,m_pic.V[m_pic.F[i].V[2]].Y/YU, m_pic.V[m_pic.F[i].V[2]].Z/YU); // 右下 17 glEnd();// 三角形绘制结束 18 19 20 /*if(m_pic.VN.size()!=0){ 21 glBegin(GL_LINES); // 绘制三角形 22 glVertex3f(m_pic.V[m_pic.F[i].V[0]].X/YU,m_pic.V[m_pic.F[i].V[0]].Y/YU, m_pic.V[m_pic.F[i].V[0]].Z/YU); // 上顶点 23 glVertex3f(m_pic.V[m_pic.F[i].V[0]].X/YU+m_pic.VN[m_pic.F[i].N[0]].NX 24 ,m_pic.V[m_pic.F[i].V[0]].Y/YU+m_pic.VN[m_pic.F[i].N[0]].NY 25 , m_pic.V[m_pic.F[i].V[0]].Z/YU+m_pic.VN[m_pic.F[i].N[0]].NZ); // 左下 26 glEnd(); // 三角形绘制结束 27 }*/ 28 } 29 }
链接
本文链接:http://www.cnblogs.com/zjutlitao/p/4187529.html
本文github: https://github.com/beautifulzzzz/OpenGL/tree/master/TuXing