載入PLY模型 C++

之前在網上查找了很長一段時間關於ply模型載入的資料,發現對鹿鹿鹿有用的實在太少,有個挺火的代碼各個網站都有轉載,但可惜的是鹿鹿鹿沒有他的bird.ply模型,並且他代碼也不是純C++的,有很多C的東西。昨天偶然翻牆到一個貌似臺灣的博客,貼出了源代碼,試了試沒想到還跑出來了。所以這裏分享一下,希望給也在尋找ply模型載入的小夥伴一點幫助。代碼來自痞客邦裏面名叫tinylin的博主,轉載請聲明。

/*
   2: 操作說明:
   3: 鍵盤按下
   4: r=會變成紅色          
   5: g=會變成綠色
   6: b=會變成藍色
   7: p=ploygon組成
   8: l=line組成
   9: model本身會自動旋轉 
  10: */
#include <iostream>
#include <fstream>
#include <string>
#include <GL/glut.h>
#include <math.h>

using namespace std;
 
void LoadPly(char *file_name,int style);//讀取並畫出ply函式 
double r_ang=0.5;//旋轉角度變數 
double R=255.0, G=0.0, B=0.0;//顏色儲存變數 
int style=GL_POLYGON;//畫出model的方式 

/*lighting 變數*/
const GLfloat light_ambient[]  = { 0.0f, 0.0f, 0.0f, 1.0f };
const GLfloat light_diffuse[]  = { 1.0f, 1.0f, 1.0f, 1.0f };
const GLfloat light_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
const GLfloat light_position[] = { 2.0f, 5.0f, 15.0f, 0.0f };

const GLfloat mat_ambient[]    = { 0.0f, 0.0f, 0.0f, 1.0f };
const GLfloat mat_diffuse[]    = { 0.8f, 0.8f, 0.8f, 1.0f };
const GLfloat mat_specular[]   = { 1.0f, 1.0f, 1.0f, 1.0f };
const GLfloat high_shininess[] = { 1.0f };

void LoadPly(char *file_name,int style)
{
	ifstream fin ( file_name, ios_base::in );//開檔 

	if ( !fin.is_open ( ) )
	{ 
		cout << "Cannot read the file." << endl;
		cout << "Please check again." << endl;
		exit(0);
        }

	string str;
	int vertex, face;
	char ch;
 /*讀取header*/

	while ( !fin.eof ( ) )
	{
		fin.get ( ch );
		if( ch != ' ' && ch != '\t' && ch != '\n' )
		{
			str.push_back ( ch );   
		}
		else
		{
		//取得vertex個數 
			if(str == "vertex")
			{
				str.clear ( );
				getline ( fin, str, '\n' ); 
				vertex = atoi(str.c_str());       
			}
		//取得face個數 
			else if(str == "face")
			{
				str.clear ( );
				getline ( fin, str, '\n' );  
				face = atoi(str.c_str());             
			}
			else if(str == "end_header")
			{
				str.clear ( );     
				break;     
			}
			else
				str.clear ( );             
		}
	} 

	//動態產生array 
	double *vertex_arrayX = new double[vertex];
	double *vertex_arrayY = new double[vertex];
	double *vertex_arrayZ = new double[vertex];

	int pos = 0;
	int counter = 0;
	double number;
	double max_edge = 0;
	static double temp_max = 0;

	/*讀取Vertex*/ 
	while ( !fin.eof ( ) )
	{
		fin.get ( ch );
		if( ch != ' ' && ch != '\t' && ch != '\n' )
			str.push_back ( ch );

		else
		{ 
			if(counter == vertex)	break;  
			/*儲存vertex資料*/
			if(str == "")	continue;

			else if(pos%3 == 0)
			{
				number = atof(str.c_str());               
				vertex_arrayX[counter] = number; 
				str.clear ( );        
			}
			else if(pos%3 == 1)
			{
				number = atof(str.c_str());                   
				vertex_arrayY[counter] = number;   
				str.clear ( );      
			}
			else if(pos%3 == 2)
			{
				number = atof(str.c_str());                   
				vertex_arrayZ[counter] = number;  
				str.clear ( );  
				counter++;     
			}
			pos++;    

			//紀錄最大的邊 
			if(abs((int)number) > max_edge) 
				max_edge = abs((int)number);      
		}   
	}

	int point[4];
	int i = 0;
	counter = 0;    
	/*畫Polygon*/  
	while ( !fin.eof ( ) )
	{
		fin.get ( ch );
		if( ch != ' ' && ch != '\t' && ch != '\n' )
			str.push_back ( ch );
		else
		{
			if(counter == face)		break;  
			if(ch == '\n')
			{
				// 計算法線向量 (打光)    
				GLfloat vc1[3],vc2[3];
				GLfloat a,b,c;
				GLdouble r;                   
				vc1[0]= vertex_arrayX[point[2]] - vertex_arrayX[point[1]]; 
				vc1[1]= vertex_arrayY[point[2]] - vertex_arrayY[point[1]]; 
				vc1[2]= vertex_arrayZ[point[2]] - vertex_arrayZ[point[1]];                
				vc2[0]= vertex_arrayX[point[3]] - vertex_arrayX[point[1]]; 
				vc2[1]= vertex_arrayY[point[3]] - vertex_arrayY[point[1]]; 
				vc2[2]= vertex_arrayZ[point[3]] - vertex_arrayZ[point[1]];                
				a = vc1[1] * vc2[2] - vc2[1] * vc1[2];
				b = vc2[0] * vc1[2] - vc1[0] * vc2[2];
				c = vc1[0] * vc2[1] - vc2[0] * vc1[1];
				r = sqrt( a * a + b* b + c * c);                
				float nor[3];        
				nor[0] = a / r;
				nor[1] = b / r;
				nor[2] = c / r;

				glNormal3f(nor[0],nor[1],nor[2]); 
				//畫出所有face
				glBegin(style); 

				for(int i=1;i<=point[0];i++)    
					glVertex3f(vertex_arrayX[point[i]], vertex_arrayY[point[i]],vertex_arrayZ[point[i]]);  
				glEnd();

				counter++;                    
			}
			else if(str == "")	continue;            

			else 
			{                 
				point[i%4] = atoi(str.c_str());                 
				i++;              
				str.clear ( );       
			}         
		}
	}
    fin.close();    
   //調整視角
   if(max_edge > temp_max)
   {
        glLoadIdentity ();            
        glOrtho(-(max_edge*2), (max_edge*2), -(max_edge*2), (max_edge*2), -(max_edge*2), (max_edge*2)); 
    }
    temp_max = max_edge;     
 }
  
 void display()
 {     
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);      
    glRotatef(r_ang, 0.0, 1.0, 1.0);   
    glColor3f(R,G,B);       
    LoadPly("ant.ply",style);    
    glFlush(); 
    glutSwapBuffers();       
 }

 void init()
 {
  glClearColor (0.0, 0.0, 0.0, 1.0);      
  glLoadIdentity ();    
  glOrtho(-5.0, 5.0, -5.0, 5.0, -5.0, 5.0);   
 }

 void keyboard(unsigned char key, int x, int y)
 {
   //按esc離開
	switch (key) 
	{
	case 27 : exit(0);
		break;
	case 'r': R=255;G=0;B=0;   
		break; 
	case 'g': R=0;G=255;B=0;   
		break;
	case 'b': R=0;G=0;B=255;  
		break;
	case 'p': style = GL_POLYGON;
		break;
	case 'l': style = GL_LINES;          
		break;                               
	}
	glutPostRedisplay();   
 }

 void idle(void)
 {
    glutPostRedisplay();
 }
  
 int main(int argc, char** argv)
 {
    glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize (600, 600); 
    glutInitWindowPosition (300, 50);  
    glutCreateWindow("Load Ply Model");  
    glutDisplayFunc(display);
    glutIdleFunc(idle);
    glutKeyboardFunc(keyboard);//偵測keyboard
    init();     
    //使用lighting 相關函式
    glEnable(GL_CULL_FACE);
    glCullFace(GL_BACK);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LESS);
    glEnable(GL_LIGHT0);
    glEnable(GL_NORMALIZE);
    glEnable(GL_COLOR_MATERIAL);
    glEnable(GL_LIGHTING);
    glLightfv(GL_LIGHT0, GL_AMBIENT,  light_ambient);
    glLightfv(GL_LIGHT0, GL_DIFFUSE,  light_diffuse);
    glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
    glLightfv(GL_LIGHT0, GL_POSITION, light_position);
    glMaterialfv(GL_FRONT, GL_AMBIENT,   mat_ambient);
    glMaterialfv(GL_FRONT, GL_DIFFUSE,   mat_diffuse);
    glMaterialfv(GL_FRONT, GL_SPECULAR,  mat_specular);
    glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess);    
      
    glutMainLoop();
  
    return EXIT_SUCCESS;
 }


發佈了7 篇原創文章 · 獲贊 39 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章