1. 程式人生 > >OpenGL讀取PLY模型檔案並繪製 Read and draw ply model by OpenGL

OpenGL讀取PLY模型檔案並繪製 Read and draw ply model by OpenGL

Ply檔案由MeshLab匯出生成,格式可能和其他軟體匯出的有出入。

本來想把模型檔案貼上來,但是找了一下好像不能上傳,希望著可留言。

這裡貼一下模型檔案的開頭部分。

-------------------------------------------------------

ply
format ascii 1.0
comment VCGLIB generated
element vertex 6479
property float x
property float y
property float z
property float nx
property float ny
property float nz
property int flags
property uchar red
property uchar green
property uchar blue
property uchar alpha
element face 12954
property list uchar int vertex_indices
property int flags
end_header
0.0363526 0.0894518 0.0166275 -2.58589 -5.26492 -2.22414 0 175 160 84 255 
0.0389934 0.088225 0.0166275 -2.52566 -5.33 -2.15753 0 170 156 88 255 
0.0389934 0.0894518 0.0138336 -2.41584 -5.1918 -2.5521 0 146 145 86 255 
0.0340731 0.0894518 0.0200012 -2.865 -5.39322 -1.43764 0 174 151 78 255 
0.0356197 0.0886338 0.0200012 -2.74755 -5.42387 -1.53245 0 168 145 74 255 
0.0356197 0.0894518 0.0175829 -2.64306 -5.36739 -1.90754 0 171 156 75 255 

......

-------------------------------------------------------

PlyLoader.h

#ifndef PLYREADER_H_
#define PLYREADER_H_

#include <GL/glut.h>
#include <GL/glu.h>
#include <GL/gl.h>
#include <vector>
#include <iostream>
using namespace std;

struct SModelData
{
	vector <float> vecFaceTriangles; // = face * 9
	vector <float> vecFaceTriangleColors; // = face * 9
	vector <float> vecNormals; // = face * 9
	int iTotalConnectedTriangles;
};

class CPLYLoader 
{
public:
	CPLYLoader();
	int LoadModel(char *filename);
	void Draw();
	
private:
	float* mp_vertexXYZ;
	float* mp_vertexNorm;
	float* mp_vertexRGB;
	int m_totalConnectedQuads;	
	int m_totalConnectedPoints;
	int m_totalFaces;
	SModelData m_ModelData;
};

#endif


PlyLoader.cpp

#include "PLYLoader.h"

CPLYLoader::CPLYLoader()
{
	this->m_totalConnectedQuads = 0;
	this->m_totalConnectedPoints = 0;
	m_ModelData.iTotalConnectedTriangles = 0;
}

int CPLYLoader::LoadModel(char* filename)
{
	printf("Loading %s...\n",filename);
    char* pch = strstr(filename,".ply");
 
    if (pch != NULL)
    {
	   FILE* file = fopen(filename,"r");
	   if (!file)
	   {
		   printf("load PLY file %s failed\n",filename);
		   return false;
	   }
		fseek(file,0,SEEK_END);
		long fileSize = ftell(file);
 
		try
		{
			mp_vertexXYZ = (float*) malloc (ftell(file));
			mp_vertexNorm = (float*) malloc (ftell(file));
			mp_vertexRGB = (float*) malloc(ftell(file));
		}
		catch (char* )
		{
			return -1;
		}
		if (mp_vertexXYZ == NULL) return -1;
		if (mp_vertexNorm == NULL) return -2;
		if (mp_vertexRGB == NULL) return -3;
		fseek(file,0,SEEK_SET); 
 
       if (file)
       {
			int i = 0;   
			int temp = 0;
			int quads_index = 0;
            int triangle_index = 0;
			int normal_index = 0;
			int colorIndex = 0;
			char buffer[1000];
 
 
			fgets(buffer,300,file);			// ply
 
 
			// READ HEADER
			// -----------------
 
			// Find number of vertexes
			while (  strncmp( "element vertex", buffer,strlen("element vertex")) != 0  )
			{
				fgets(buffer,300,file);			// format
			}
			strcpy(buffer, buffer+strlen("element vertex"));
			sscanf(buffer,"%i", &this->m_totalConnectedPoints);
 
 
			// Find number of vertexes
			fseek(file,0,SEEK_SET);
			while (  strncmp( "element face", buffer,strlen("element face")) != 0  )
			{
				fgets(buffer,300,file);			// format
			}
			strcpy(buffer, buffer+strlen("element face"));
			sscanf(buffer,"%i", &this->m_totalFaces);
 
 
			// go to end_header
			while (  strncmp( "end_header", buffer,strlen("end_header")) != 0  )
			{
				fgets(buffer,300,file);			// format
			}
 
			//----------------------
 
 
			// read vertices
			i =0;
			for (int iterator = 0; iterator < this->m_totalConnectedPoints; iterator++)//3488
			{
				char tmp[1];
				fgets(buffer,300,file);
 
				sscanf(buffer,"%f %f %f %f %f %f %c %f %f %f", &mp_vertexXYZ[i], &mp_vertexXYZ[i+1], &mp_vertexXYZ[i+2],
					&mp_vertexNorm[i], &mp_vertexNorm[i+1], &mp_vertexNorm[i+2],
					tmp,
					&mp_vertexRGB[i], &mp_vertexRGB[i+1],  &mp_vertexRGB[i+2]);
				i += 3;
			}
 
			// read faces
			i =0;
			for (int iterator = 0; iterator < this->m_totalFaces; iterator++)//6920
			{
				fgets(buffer,300,file);
 
					if (buffer[0] == '3')
					{
						int vertex1 = 0, vertex2 = 0, vertex3 = 0;
						buffer[0] = ' ';
						sscanf(buffer,"%i%i%i", &vertex1,&vertex2,&vertex3 );//number of vertex eg:5,7,6


						m_ModelData.vecFaceTriangles.push_back( mp_vertexXYZ[3*vertex1]);
						m_ModelData.vecFaceTriangles.push_back( mp_vertexXYZ[3*vertex1+1]);
						m_ModelData.vecFaceTriangles.push_back( mp_vertexXYZ[3*vertex1+2]);
						m_ModelData.vecFaceTriangles.push_back( mp_vertexXYZ[3*vertex2]);
						m_ModelData.vecFaceTriangles.push_back( mp_vertexXYZ[3*vertex2+1]);
						m_ModelData.vecFaceTriangles.push_back( mp_vertexXYZ[3*vertex2+2]);
						m_ModelData.vecFaceTriangles.push_back( mp_vertexXYZ[3*vertex3]);
						m_ModelData.vecFaceTriangles.push_back( mp_vertexXYZ[3*vertex3+1]);
						m_ModelData.vecFaceTriangles.push_back( mp_vertexXYZ[3*vertex3+2]);


						m_ModelData.vecFaceTriangleColors.push_back( mp_vertexRGB[3*vertex1]  / 255.0f);
						m_ModelData.vecFaceTriangleColors.push_back( mp_vertexRGB[3*vertex1+1]/ 255.0f);
						m_ModelData.vecFaceTriangleColors.push_back( mp_vertexRGB[3*vertex1+2]/ 255.0f);
						m_ModelData.vecFaceTriangleColors.push_back( mp_vertexRGB[3*vertex2]  / 255.0f);
						m_ModelData.vecFaceTriangleColors.push_back( mp_vertexRGB[3*vertex2+1]/ 255.0f);
						m_ModelData.vecFaceTriangleColors.push_back( mp_vertexRGB[3*vertex2+2]/ 255.0f);
						m_ModelData.vecFaceTriangleColors.push_back( mp_vertexRGB[3*vertex3]  / 255.0f);
						m_ModelData.vecFaceTriangleColors.push_back( mp_vertexRGB[3*vertex3+1]/ 255.0f);
						m_ModelData.vecFaceTriangleColors.push_back( mp_vertexRGB[3*vertex3+2]/ 255.0f);
 
						m_ModelData.vecNormals.push_back( mp_vertexNorm[3*vertex1]);
						m_ModelData.vecNormals.push_back( mp_vertexNorm[3*vertex1+1]);
						m_ModelData.vecNormals.push_back( mp_vertexNorm[3*vertex1+2]);
						m_ModelData.vecNormals.push_back( mp_vertexNorm[3*vertex2]);
						m_ModelData.vecNormals.push_back( mp_vertexNorm[3*vertex2+1]);
						m_ModelData.vecNormals.push_back( mp_vertexNorm[3*vertex2+2]);
						m_ModelData.vecNormals.push_back( mp_vertexNorm[3*vertex3]);
						m_ModelData.vecNormals.push_back( mp_vertexNorm[3*vertex3+1]);
						m_ModelData.vecNormals.push_back( mp_vertexNorm[3*vertex3+2]);

						triangle_index += 9;
						m_ModelData.iTotalConnectedTriangles += 3;
					}
 
 
					i += 3;
			}
 
			fclose(file);
			printf("%s Loaded!\n",filename);
		
		}
 
      else 
		{ 
		  printf("File can't be opened\n"); 
		}
    }	
	else 
	{
      printf("File does not have a .PLY extension. ");    
	}   

	return 0;
}
 

void CPLYLoader::Draw() //implemented in GLPainter, not called again
{
	if (m_ModelData.vecFaceTriangleColors.empty())
	{
		cout << "model data is null"<<endl;
		exit(-1);
	}
	
	glEnableClientState(GL_VERTEX_ARRAY);	
 	glEnableClientState(GL_NORMAL_ARRAY);
	glEnableClientState(GL_COLOR_ARRAY);
	glVertexPointer(3,GL_FLOAT,	0,m_ModelData.vecFaceTriangles.data());	
	glColorPointer(3,GL_FLOAT,0,m_ModelData.vecFaceTriangleColors.data());
	glNormalPointer(GL_FLOAT, 0, m_ModelData.vecNormals.data());
	glDrawArrays(GL_TRIANGLES, 0, m_ModelData.iTotalConnectedTriangles);
	glDisableClientState(GL_VERTEX_ARRAY);    
	glDisableClientState(GL_NORMAL_ARRAY);
	glDisableClientState(GL_COLOR_ARRAY);
}


Main.cpp

#include "PLYLoader.h"
int width = 640;
int height = 480;

CPLYLoader plyLoader;

void Initialize()
{
	glClearColor(0.0, 0.0, 0.0, 0.0);
	glEnable( GL_DEPTH_TEST );
	plyLoader.LoadModel("bird.ply");
}


void Reshape(int w, int h)
{
	width = w;
	height = h;
	glViewport(0, 0, width, height);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45.0, (double)width / (double)height, 1.0, 1000.0);
}

void Display()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glViewport(0, 0, width, height);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glTranslatef(0.7, -0.3, 0);
	glRotatef(280,1,0,0);
	glRotatef(80,0,0,1);
	glScalef(5, 5, 5);
	plyLoader.Draw();
	glutSwapBuffers();
}

int main( int argc, char **argv )
{
	glutInit(&argc, argv);
	glutInitWindowPosition(0, 0);
	glutInitWindowSize(width, height);
	glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH );
	glutCreateWindow("Load Model");
	glutDisplayFunc(Display);
	glutReshapeFunc(Reshape);

	Initialize();

	glutMainLoop();

	return 0;
}

結果