• 二进制格式 PLY 模型文件的读取与渲染


    PLY 文件头部信息:

    ply
    format binary_little_endian 1.0
    comment VCGLIB generated
    element vertex 13469
    property float x
    property float y
    property float z
    property float nx
    property float ny
    property float nz
    property uchar red
    property uchar green
    property uchar blue
    property uchar alpha
    element face 26934
    property list uchar int vertex_indices
    end_header
    

    完整可运行的 C++ 代码(基于 GLUT)

    #define _CRT_SECURE_NO_WARNINGS
    #include <iostream>
    #include <vector>
    #include <stdio.h>
    #include <stdlib.h>
    #include <GL/glut.h>
    #include <cstdlib>
    using namespace std;
    
    const int TRANSFORM_NONE = 0;
    const int TRANSFORM_ROTATE = 1;
    const int TRANSFORM_SCALE = 2;
    const int TRANSFORM_TRANSLATE = 3;
    static int press_x, press_y;
    
    const int LIGHT_NUM = 3;
    int current_light = 0;
    static float x_angle = 0.0;
    static float y_angle = 0.0;
    static float scale_size = 1;
    static float x_dist = 0.0;
    static float y_dist = 0.0;
    static int obj_mode = 0;
    static int xform_mode = 0;
    static int proj_mode = 0;
    
    // 存储定点信息
    struct Vertex
    {
    	double x, y, z;
    	double r, g, b, a;
    	double nx, ny, nz;
    };
    
    // 存储与表面相关的顶点
    struct Face
    {
    	int v1, v2, v3;
    };
    
    vector<Vertex> vertices;
    vector<Face>   faces;
    
    // 加载 PLY 文件;此处为了方便硬编码有关格式;格式参考:http://paulbourke.net/dataformats/ply/
    bool load_ply()
    {
    	char fname[] = "data.ply";
    	FILE* f = fopen(fname, "rb");
    	if (f == NULL)
    	{
    		cout << "file " << fname << " does not exist" << endl;
    		return false;
    	}
    	int counter = 0;
    	while (counter < 17)
    	{
    		char c;
    		fread((void*)(&c), sizeof(c), 1, f);
    		if (c == '
    ') {
    			counter++;
    		}
    	}
    	int vertex_num = 13469;
    	int face_num = 26934;
    	for (int i = 0; i < vertex_num; i++) {
    		float x, y, z;
    		fread((void*)(&x), 4, 1, f);
    		fread((void*)(&y), 4, 1, f);
    		fread((void*)(&z), 4, 1, f);
    		float nx, ny, nz;
    		fread((void*)(&nx), 4, 1, f);
    		fread((void*)(&ny), 4, 1, f);
    		fread((void*)(&nz), 4, 1, f);
    		unsigned char r, g, b, a;
    		fread((void*)(&r), 1, 1, f);
    		fread((void*)(&g), 1, 1, f);
    		fread((void*)(&b), 1, 1, f);
    		fread((void*)(&a), 1, 1, f);
    		Vertex vertex;
    		vertex.x = x / 1000;
    		vertex.y = y / 1000;
    		vertex.z = z / 1000;
    		vertex.nx = nx;
    		vertex.ny = ny;
    		vertex.nz = nz;
    		vertex.r = r;
    		vertex.g = g;
    		vertex.b = b;
    		vertex.a = a;
    		vertices.push_back(vertex);
    	}
    	for (int i = 0; i < face_num; i++) {
    		unsigned char n;
    		int v1, v2, v3;
    		fread((unsigned char*)(&n), 1, 1, f);
    		fread((void*)(&v1), 4, 1, f);
    		fread((void*)(&v2), 4, 1, f);
    		fread((void*)(&v3), 4, 1, f);
    		Face face;
    		face.v1 = v1;
    		face.v2 = v2;
    		face.v3 = v3;
    		faces.push_back(face);
    	}
    	fclose(f);
    	return true;
    }
    
    void reshape(int w, int h)
    {
    	glViewport(0, 0, (GLsizei)w, (GLsizei)h);
    	glutPostRedisplay();
    }
    
    void display(void)
    {
    	glEnable(GL_DEPTH_TEST);
    	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    	glShadeModel(GL_SMOOTH);
    	glMatrixMode(GL_PROJECTION);
    	glLoadIdentity();
    	gluPerspective(60, 1, 0.1, 100);
    	glMatrixMode(GL_MODELVIEW);
    	glLoadIdentity();
    	gluLookAt(0, 0, 3, 0, 0, 0, 0, 1, 0);
    
    	// 设置光源
    	GLfloat light_position[] = { 0.0, 0.0, 1.0, 1.0 };
    	GLfloat light_direction[] = { 0.0, 0.0, -1.0 };
    	GLfloat white_color[] = { 1.0, 1.0, 1.0, 1.0 };
    	GLfloat red_color[] = { 1.0, 0.0, 0.0, 1.0 };
    	GLfloat green_color[] = { 0.0, 1.0, 0.0, 1.0 };
    	GLfloat blue_color[] = { 0.0, 0.0, 1.0, 1.0 };
    	GLfloat exponent[] = { 10.0f };
    	GLfloat cutoff[] = { 20.0f };
    	glLightfv(GL_LIGHT0, GL_POSITION, light_position);
    	switch (current_light)
    	{
    	case 1:
    		cutoff[0] = 45;
    		exponent[0] = 20;
    		glLightfv(GL_LIGHT0, GL_SPOT_EXPONENT, exponent);
    		glLightfv(GL_LIGHT0, GL_SPOT_CUTOFF, cutoff);
    		glLightfv(GL_LIGHT0, GL_SPECULAR, white_color);
    		break;
    	case 2:
    		glLightfv(GL_LIGHT0, GL_SPECULAR, green_color);
    		glLightfv(GL_LIGHT0, GL_DIFFUSE, green_color);
    		glLightfv(GL_LIGHT0, GL_AMBIENT, green_color);
    		glLightfv(GL_LIGHT0, GL_SPOT_EXPONENT, exponent);
    		glLightfv(GL_LIGHT0, GL_SPOT_CUTOFF, cutoff);
    		glLightfv(GL_LIGHT0, GL_SPECULAR, white_color);
    		break;
    	default:
    		exponent[0] = 0;
    		cutoff[0] = 180;
    		glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light_direction);
    		glLightfv(GL_LIGHT0, GL_SPOT_EXPONENT, exponent);
    		glLightfv(GL_LIGHT0, GL_SPOT_CUTOFF, cutoff);
    		glLightfv(GL_LIGHT0, GL_SPECULAR, white_color);
    		glLightfv(GL_LIGHT0, GL_DIFFUSE, white_color);
    		glLightfv(GL_LIGHT0, GL_AMBIENT, white_color);
    		glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 1.0);
    		glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.0);
    		glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.0);
    		break;
    	}
    
    	glEnable(GL_LIGHT0);
    	glEnable(GL_LIGHTING);
    
    	glTranslatef(x_dist, -y_dist, 0);
    	glRotatef(x_angle, 0, 1, 0);
    	glRotatef(y_angle, 1, 0, 0);
    	glScalef(scale_size, scale_size, scale_size);
    	glEnable(GL_LIGHTING);
    
    
    	for (int i = 0; i < (int)faces.size(); i++)
    	{
    		Face f = faces[i];
    		Vertex v1 = vertices[f.v1];
    		Vertex v2 = vertices[f.v2];
    		Vertex v3 = vertices[f.v3];
    
    		glBegin(GL_TRIANGLES);
    		glColor3f(1, 0, 0);
    		glNormal3f(v1.nx, v1.ny, v1.nz);
    		glVertex3f(v1.x, v1.y, v1.z);
    		glNormal3f(v2.nx, v2.ny, v2.nz);
    		glVertex3f(v2.x, v2.y, v2.z);
    		glNormal3f(v3.nx, v3.ny, v3.nz);
    		glVertex3f(v3.x, v3.y, v3.z);
    		glEnd();
    
    	}
    	glutSwapBuffers();
    }
    
    
    void mouse(int button, int state, int x, int y)
    {
    	if (state == GLUT_DOWN)
    	{
    		press_x = x; press_y = y;
    		if (button == GLUT_LEFT_BUTTON)
    			xform_mode = TRANSFORM_ROTATE;
    		else if (button == GLUT_MIDDLE_BUTTON)
    			xform_mode = TRANSFORM_TRANSLATE;
    		else if (button == GLUT_RIGHT_BUTTON)
    			xform_mode = TRANSFORM_SCALE;
    	}
    	else if (state == GLUT_UP)
    	{
    		xform_mode = TRANSFORM_NONE;
    	}
    }
    
    void mouseMotion(int x, int y)
    {
    	if (xform_mode == TRANSFORM_ROTATE)
    	{
    		x_angle += (x - press_x) / 5.0;
    
    		if (x_angle > 180)
    			x_angle -= 360;
    		else if (x_angle < -180)
    			x_angle += 360;
    
    		press_x = x;
    
    		y_angle += (y - press_y) / 5.0;
    
    		if (y_angle > 180)
    			y_angle -= 360;
    		else if (y_angle < -180)
    			y_angle += 360;
    
    		press_y = y;
    	}
    	else if (xform_mode == TRANSFORM_SCALE)
    	{
    		float old_size = scale_size;
    
    		scale_size *= (1 + (y - press_y) / 60.0);
    
    		if (scale_size < 0)
    			scale_size = old_size;
    		press_y = y;
    	}
    	else if (xform_mode == TRANSFORM_TRANSLATE)
    	{
    		x_dist += (x - press_x) / 50.0;
    		press_x = x;
    
    		y_dist += (y - press_y) / 50.0;
    		press_y = y;
    	}
    
    	// force the redraw function
    	glutPostRedisplay();
    }
    
    void keyboard(unsigned char key, int x, int y)
    {
    	switch (key)
    	{
    	case 'l':
    		current_light++;
    		current_light %= LIGHT_NUM;
    		cout << "Change light source:" << current_light << endl;
    		break;
    	case 'd':
    		x_dist += 0.05;
    		break;
    	case 'a':
    		x_dist -= 0.05;
    		break;
    	case 's':
    		y_dist += 0.05;
    		break;
    	case 'w':
    		y_dist -= 0.05;
    		break;
    	}
    	glutPostRedisplay();
    }
    
    
    int main(int argc, char** argv)
    {
    	cout << "Help:
    1. Press W A S D to move model.
    2. Press L to change light source.
    3. Drag mouse's left button to rotate model.
    4. Drag mouse's right button to move model." << endl;
    	glutInit(&argc, argv);
    	glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
    	glutInitWindowSize(600, 600);
    	glutInitWindowPosition(100, 100);
    	glutCreateWindow("Team Project");
    	if (!load_ply())
    	{
    		cerr << "Load ply file failed!" << endl;
    		return -1;
    	}
    	glClearColor(0.0, 0.0, 0.0, 0.0);
    	glutDisplayFunc(display);
    	glutMouseFunc(mouse);
    	glutMotionFunc(mouseMotion);
    	glutKeyboardFunc(keyboard);
    	glutReshapeFunc(reshape);
    	glutMainLoop();
    	return 1;
    }
    
  • 相关阅读:
    架构师养成记--34.Redis持久化
    架构师养成记--33.Redis哨兵、redis简单事务
    js获取当前项目根路径URL (转自CSDN 红领巾-sunlight)
    架构师养成记--32.Redis高级(安全 主从复制)
    架构师养成记--31.Redis的几种类型
    架构师养成记--30.Redis环境搭建
    oracle split(转自--博客园 linbo.yang)
    架构师养成记--29.redis开篇
    129、Java面向对象之static关键字一(修改static变量)
    128、Java面向对象之对象的比较
  • 原文地址:https://www.cnblogs.com/justsong/p/12219716.html
Copyright © 2020-2023  润新知