openGL 解析ply文件并且显示三维模型
一、ply文件简介
ply文件是一种用于描述图形结构的文件。一般包括:头部、顶点列表、面片列表、其他元素列表等。
例如下面这个ply文件描述了一个cube。
ply format ascii 1.0 comment made by anonymous comment this file is a cube element vertex 8 property float32 x property float32 y property float32 z element face 12 property list uint8 int32 vertex_index end_header 0 0 0 0 0 0.01 0 0.01 0.01 0 0.01 0 0.01 0 0 0.01 0 0.01 0.01 0.01 0.01 0.01 0.01 0 3 0 1 2 3 0 3 2 3 7 9 5 3 7 4 5 3 0 4 5 3 0 1 5 3 1 5 6 3 1 2 6 3 2 6 7 3 2 3 7 3 1 7 4 3 3 0 4
二、ply文件的解析及用openGL显示
ply的文件格式比较简单,我们只需要对其中的信息进行提取,在调用openGL中相应的函数就可以实现显示ply模型了。
代码:
1 #ifndef PLYREADER_H_ 2 #define PLYREADER_H_ 3 4 #include <GL/glut.h> 5 #include <GL/glu.h> 6 #include <GL/gl.h> 7 #include <vector> 8 using namespace std; 9 10 struct SModelData 11 { 12 vector <float> vecFaceTriangles; // = face * 9 13 vector <float> vecFaceTriangleColors; // = face * 9 14 int iTotalConnectedTriangles; 15 }; 16 17 class CPLYLoader 18 { 19 public: 20 CPLYLoader(); 21 bool LoadModel(char * filename); 22 void Draw(); 23 private: 24 float * mp_vertexXYZ; 25 float * mp_vertexRGB; 26 int m_totalConnectedQuads; 27 int m_totalConnectedPoints; 28 int m_totalFaces; 29 SModelData m_ModelData; 30 }; 31 32 #endif
1 #include "stdafx.h" 2 #include "PLYLoader.h" 3 4 CPLYLoader::CPLYLoader() 5 { 6 this->m_totalConnectedQuads = 0; 7 this->m_totalConnectedPoints = 0; 8 this->m_ModelData.iTotalConnectedTriangles = 0; 9 } 10 11 bool CPLYLoader::LoadModel(char * filename) 12 { 13 printf("Loading %s...\n", filename); 14 char * pch = strstr(filename, ".ply"); 15 if (pch != NULL) 16 { 17 FILE * file = fopen(filename, "r"); 18 if (!file) 19 { 20 printf("load PLY file %s failed\n", filename); 21 return false; 22 } 23 fseek(file, 0, SEEK_END); 24 long fileSize = ftell(file); 25 try 26 { 27 mp_vertexXYZ = (float*)malloc(fileSize); 28 mp_vertexRGB = (float*)malloc(fileSize); 29 } 30 catch (char *) 31 { 32 return false; 33 } 34 if (mp_vertexXYZ == NULL || mp_vertexRGB == NULL) return false; 35 fseek(file, 0, SEEK_SET); 36 if (file) 37 { 38 char buffer[1000]; 39 fgets(buffer, 300, file); 40 //READ HEADER 41 while (strncmp("element vertex", buffer, strlen("element vertex")) != 0) 42 { 43 fgets(buffer, 300, file); 44 } 45 strcpy(buffer, buffer + strlen("element vertex")); 46 sscanf(buffer, "%i", &this->m_totalConnectedPoints); 47 printf("first we get %d vertexs\n", this->m_totalConnectedPoints); 48 //Find the number of vertexes 49 fseek(file, 0, SEEK_SET); 50 while (strncmp("element face", buffer, strlen("element face")) != 0) 51 { 52 fgets(buffer, 300, file); 53 } 54 strcpy(buffer, buffer + strlen("element face")); 55 sscanf(buffer, "%i", &this->m_totalFaces); 56 printf("second we get %d faces\n", this->m_totalFaces); 57 //Go to end_header 58 while (strncmp("end_header", buffer, strlen("end_header")) != 0) 59 { 60 fgets(buffer, 300, file); 61 } 62 //Read vertices 63 int i = 0; 64 for (int iterator = 0; iterator < this->m_totalConnectedPoints; iterator++) 65 { 66 fgets(buffer, 300, file); 67 sscanf(buffer, "%f %f %f", &mp_vertexXYZ[i], &mp_vertexXYZ[i + 1], &mp_vertexXYZ[i + 2]); 68 i += 3; 69 } 70 //Read faces 71 for (int iterator = 0; iterator < this->m_totalFaces; iterator++) 72 { 73 fgets(buffer, 300, file); 74 //Triangular patch 75 if (buffer[0] == '3') 76 { 77 int vertex1 = 0, vertex2 = 0, vertex3 = 0; 78 buffer[0] = ' '; 79 sscanf(buffer, "%i%i%i", &vertex1, &vertex2, &vertex3); 80 //point 81 m_ModelData.vecFaceTriangles.push_back(mp_vertexXYZ[3 * vertex1]); 82 m_ModelData.vecFaceTriangles.push_back(mp_vertexXYZ[3 * vertex1 + 1]); 83 m_ModelData.vecFaceTriangles.push_back(mp_vertexXYZ[3 * vertex1 + 2]); 84 m_ModelData.vecFaceTriangles.push_back(mp_vertexXYZ[3 * vertex2]); 85 m_ModelData.vecFaceTriangles.push_back(mp_vertexXYZ[3 * vertex2 + 1]); 86 m_ModelData.vecFaceTriangles.push_back(mp_vertexXYZ[3 * vertex2 + 2]); 87 m_ModelData.vecFaceTriangles.push_back(mp_vertexXYZ[3 * vertex3]); 88 m_ModelData.vecFaceTriangles.push_back(mp_vertexXYZ[3 * vertex3 + 1]); 89 m_ModelData.vecFaceTriangles.push_back(mp_vertexXYZ[3 * vertex3 + 2]); 90 //color 91 m_ModelData.vecFaceTriangleColors.push_back(1.0); 92 m_ModelData.vecFaceTriangleColors.push_back(1.0); 93 m_ModelData.vecFaceTriangleColors.push_back(1.0); 94 m_ModelData.vecFaceTriangleColors.push_back(1.0); 95 m_ModelData.vecFaceTriangleColors.push_back(1.0); 96 m_ModelData.vecFaceTriangleColors.push_back(1.0); 97 m_ModelData.vecFaceTriangleColors.push_back(1.0); 98 m_ModelData.vecFaceTriangleColors.push_back(1.0); 99 m_ModelData.vecFaceTriangleColors.push_back(1.0); 100 m_ModelData.iTotalConnectedTriangles += 3; 101 } 102 } 103 fclose(file); 104 printf("%s Loaded!\n", filename); 105 return true; 106 } 107 else 108 { 109 printf("File can't be opened\n"); 110 return false; 111 } 112 } 113 else 114 { 115 printf("File does not have a ply extension.\n"); 116 return false; 117 } 118 } 119 120 void CPLYLoader::Draw() //implemented in GLPainter, not called again 121 { 122 glVertexPointer(3, GL_FLOAT, 0, m_ModelData.vecFaceTriangles.data()); 123 glColorPointer(3, GL_FLOAT, 0, m_ModelData.vecFaceTriangleColors.data()); 124 glDrawArrays(GL_TRIANGLES, 0, m_ModelData.iTotalConnectedTriangles); 125 }
1 #include "stdafx.h" 2 #include "PlyLoader.h" 3 #include <gl/glut.h> 4 5 CPLYLoader plyLoader; 6 7 void init() 8 { 9 glClearColor(0, 0, 0, 0); 10 glEnableClientState(GL_VERTEX_ARRAY); 11 glEnable(GL_COLOR_ARRAY); 12 plyLoader.LoadModel("dragon.ply"); 13 } 14 15 void display() 16 { 17 glClear(GL_COLOR_BUFFER_BIT); 18 plyLoader.Draw(); 19 glFlush(); 20 } 21 22 int _tmain(int argc, _TCHAR* argv[]) 23 { 24 glutInit(&argc, (char **)argv); 25 glutInitWindowSize(500, 500); 26 glutInitWindowPosition(100, 100); 27 glutCreateWindow("load model"); 28 init(); 29 glutDisplayFunc(display); 30 glutMainLoop(); 31 return 0; 32 }
代码参考来源于互联网。