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;
}

 

結果

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章