栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

c++实习项目3D模型显示系统

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

c++实习项目3D模型显示系统

        通过调用pcl相关库及函数,将pcd、obj、las、ply格式3D文件统一转换成ply点云格式文件进行存储及显示,调用OpenGL相关函数进行三维显示及鼠标、键盘的简单操作。

1、transform.h(建立一个抽象类Modelloader,由三个子类分别继承,使其读取转换不同的3D文件)

#include 
#include 
#include
#include 
#include 
#include 
#include 
#include 
#include
#include 


using namespace pcl;
using namespace pcl::io;
using namespace std;

class ModelLoader {

public:
	string filename;
	string savefilename;
	ModelLoader(string filename="", string savefilename="") {

		this->filename = filename;
		this->savefilename = savefilename;

	}
	virtual void  TO_PLY(){}
	~ModelLoader() {

		this->filename = "";

	}

};

class LasLoader:public ModelLoader {

public:
	LasLoader(string filename="",string savefilename="") :ModelLoader(filename,savefilename) {}
	void TO_PLY();

};
class PCDLoader :public ModelLoader {

public:
	PCDLoader(string filename = "", string savefilename = "") :ModelLoader(filename, savefilename) {}
	void TO_PLY();

};
class OBJLoader :public ModelLoader {
public:
	OBJLoader(string filename = "", string savefilename = "") :ModelLoader(filename, savefilename) {}
	void TO_PLY();
};

2、LAS_to_PLY.cpp

#include "transform.h"
void LasLoader::TO_PLY()
{
	
	std::ifstream ifs; 
	ifs.open(this->filename, ios::in | ios::binary);
	liblas::ReaderFactory f;
	liblas::Reader reader = f.CreateWithStream(ifs);

	unsigned long int nbPoints = reader.GetHeader().GetPointRecordsCount();

	pcl::PointCloud cloud;
	cloud.width = nbPoints;
	cloud.height = 1;
	cloud.is_dense = false;
	cloud.points.resize(cloud.width * cloud.height);

	int i = 0;
	uint16_t r1, g1, b1;
	int r2, g2, b2;
	uint32_t rgb;

	while (reader.ReadNextPoint())
	{
		
		cloud.points[i].x = (reader.GetPoint().GetX());
		cloud.points[i].y = (reader.GetPoint().GetY());
		cloud.points[i].z = (reader.GetPoint().GetZ());


		r1 = (reader.GetPoint().GetColor().GetRed());
		g1 = (reader.GetPoint().GetColor().GetGreen());
		b1 = (reader.GetPoint().GetColor().GetBlue());
		r2 = ceil(((float)r1 / 65536) * (float)256);
		g2 = ceil(((float)g1 / 65536) * (float)256);
		b2 = ceil(((float)b1 / 65536) * (float)256);
		rgb = ((int)r2) << 16 | ((int)g2) << 8 | ((int)b2);
		cloud.points[i].rgb = *reinterpret_cast(&rgb);

		i++;
	}

	pcl::io::savePLYFileASCIi(this->savefilename, cloud);
}

3、OBJ_to_PLY.cpp

#include "transform.h"

int OBJtoPLYconvertor(string& input_filename, string& output_filename)
{
	pcl::PCLPointCloud2 cloud;



	if (loadOBJFile(input_filename, cloud) < 0)
	{
		cout << "Error: cannot load the PCD file!!!" << endl;
		return -1;
	}

	PLYWriter  writer;
	writer.writeASCIi(output_filename, cloud, Eigen::Vector4f::Zero(), Eigen::Quaternionf::Identity(), 40, true);
	return 0;

}

void OBJLoader::TO_PLY()
{
	
	OBJtoPLYconvertor(this->filename, this->savefilename);

}

4、PCD_to_PLY.cpp

#include "transform.h"

int PCDtoPLYconvertor(string& input_filename, string& output_filename)
{
	pcl::PCLPointCloud2 cloud;

	

	if (loadPCDFile(input_filename, cloud) < 0)
	{
		cout << "Error: cannot load the PCD file!!!" << endl;
		return -1;
	}

	PLYWriter  writer;
	writer.writeASCIi(output_filename, cloud, Eigen::Vector4f::Zero(), Eigen::Quaternionf::Identity(), 20, true);
	return 0;

}

void PCDLoader::TO_PLY()
{
	
	
	PCDtoPLYconvertor(this->filename, this->savefilename);

}

5、PLYloader.h(将文件格式转换为ply后统一由一个plyloader类读取ps:提前声明了一些参数。)

#define PLYREADER_H_

#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

static int mousetate = 0;//鼠标当前的状态
static int mousestate1 = 0;
static int mousestate2 = 0;
static GLfloat Oldx = 0.0; // 点击之前的位置
static GLfloat Oldy = 0.0;

static float xRotate = 0.0f;
static float yRotate = 0.0f;
static float scale = 1;
static float timesx = 0.0f;
static float timesy = 0.0f;

static float cx = 0.0f;
static float cy = 0.0f;
static float cz = 0.0f;

void onMouse(int button, int state, int x, int y);
void onMouseMove(int x, int y);
void mySpecial(int key, int x, int y);



class CPLYLoader
{
public:
	CPLYLoader();
	int LoadModel(char* filename);
	void Draw();
	
private:
	GLfloat* mp_vertexXYZ;


	int m_totalConnectedPoints;

};

6、PLYloader.cpp

#include "PLYLoader.h"
#include 

CPLYLoader::CPLYLoader()
{
	this->m_totalConnectedPoints = 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 failedn", filename);
			return false;
		}
		fseek(file, 0, SEEK_END);
		long fileSize = ftell(file);

		try
		{
			mp_vertexXYZ = (GLfloat*)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;
		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);



			while (strncmp("element vertex", buffer, strlen("element vertex")) != 0)
			{
				fgets(buffer, 300, file);
			}
			strcpy(buffer, buffer + strlen("element vertex"));
			sscanf(buffer, "%i", &this->m_totalConnectedPoints);


			cout << this->m_totalConnectedPoints << endl;


			fseek(file, 0, SEEK_SET);

			while (strncmp("end_header", buffer, strlen("end_header")) != 0)
			{
				fgets(buffer, 300, file);	
			}




		
			i = 0;
			for (int iterator = 0; iterator < this->m_totalConnectedPoints; iterator++)
			{
				char tmp[1];
				fgets(buffer, 300, file);

				sscanf(buffer, "%f %f %f ", &mp_vertexXYZ[i], &mp_vertexXYZ[i + 1], &mp_vertexXYZ[i + 2]);
				i += 3;
			}

			i = 0;

			fclose(file);
			printf("%s Loaded!n", filename);

		}

		else
		{
			printf("File can't be openedn");
		}
	}
	else
	{
		printf("File does not have a .PLY extension. ");
	}

	return 0;
}


void CPLYLoader::Draw() 
{
	
	glEnableClientState(GL_VERTEX_ARRAY);
	glColor3f(0.0f, 0.0f, 0.0f);

	glVertexPointer(3, GL_FLOAT, 0, mp_vertexXYZ);
	glDrawArrays(GL_POINTS, 0, this->m_totalConnectedPoints);

	glDisableClientState(GL_VERTEX_ARRAY);

	
	}

7、main.cpp

#include "transform.h"
#include 
#include "PLYloader.h"




int width = 640;
int height = 480;
static bool sign = false;
static string p,t;
static char  ptr[100]; 


void onMouse(int button, int state, int x, int y)
{
	if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
		cout << "LEFT_DOWN" << endl;
		mousetate = 1;

	}
	else
		mousetate = 0;
	if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
	{
		mousestate1 = 1;
	}
	else
		mousestate1 = 0;
	if (button == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN)
	{
		mousestate2 = 1;

	}
	else
		mousestate2 = 0;
	if (state == GLUT_UP && button == 3) {

		cout << "WHEEL_UP" << endl;
		scale += 0.02;


	}
	else if (state == GLUT_UP && button == 4)
	{
		cout << "WHEEL_DOWN" << endl;
		scale -= 0.02;


	}

	glutPostRedisplay();
}
void onMouseMove(int x, int y) {
	timesx = timesy = 0;
	if (mousetate) {

		yRotate += (x - Oldx) * 0.4f;
		
	}

	if (mousestate1){

		xRotate += (y - Oldy) * 0.4f;

		}
	Oldx = x;
	Oldy = y;
	if (mousestate2)
	{
		timesx = x;
		timesy = y;
	}
	glutPostRedisplay();
	

}
void mySpecial(int key, int x, int y) {
	switch (key) {
		//cx = cy = cz = 0;
		
	case GLUT_KEY_F1://按F1主视图
		xRotate = 0;
		yRotate = 0;
		timesx = timesy = 0;
		break;
	case GLUT_KEY_F2:
		xRotate = 92.001;
		yRotate = 0;
		timesx = timesy = 0;
		break;
	case GLUT_KEY_F3:
		xRotate = 0;
		yRotate = 270.4;
		timesx = timesy = 0;
		break;
	default:
		break;
	}
	glutPostRedisplay();
}

CPLYLoader plyLoader;
void Initialize()
{
	glClearColor(1.0, 1.0, 1.0, 0.0);
	glEnable(GL_DEPTH);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(65, 1, 1, 50);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt(12, 12, 20, 0, 0, 0, 0, 1, 0);

	
}

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);
		//gluLookAt(0.0f, 0.0f, 0.0f, cx, cy, cz,0,0,0);
		glViewport(0, 0, width, height);
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		glRotatef(yRotate, 0, 1,0 );
		glRotatef(xRotate, 1, 0, 0);
		glTranslatef(timesx*0.001f, -timesy*0.001f, 0.0f);
		cout << "沿x轴旋转" << xRotate << "沿y轴旋转" << yRotate << endl;
		glScalef(scale, scale, scale);
		plyLoader.Draw();
		glutSwapBuffers();

	
}
int main(int argc, char** argv)
{
	ModelLoader* model;
		cout << "输入要处理的文件路径!" << endl;
		cin >> p;
		
		char str[100];
		p.copy(str, p.size(), 0);
		char* q = str;
		if (strstr(q, "las"))
		{
			cout << "输入要存储的文件路径" << endl;
			cin >> t;
			model = new LasLoader(p,t);
			model->TO_PLY();
		

		}
		else if (strstr(q, "pcd"))
		{
			cout << "输入要存储的文件路径" << endl;
			cin >> t;
			model = new PCDLoader(p,t);
			model->TO_PLY();
			
		}
		else if (strstr(q, "obj"))
		{
			cout << "输入要存储的文件路径" << endl;
			cin >> t;
			model = new OBJLoader(p,t);
			model->TO_PLY();
			
		}
		else if (strstr(q, "ply"))
		{
			model = new ModelLoader();
			model->savefilename = p;
			
		}
		else {

			cout << "该文件类型暂不能处理!" << endl;
		}
	

		
		strcpy(ptr, model->savefilename.c_str());
		plyLoader.LoadModel(ptr);

		glutInit(&argc, argv);
		glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
		glutInitWindowSize(600, 800);
		glutInitWindowPosition(100, 100);


		
		glutCreateWindow("F1、F2、F3分别进行模型三视图展示,鼠标左右键拖住旋转,鼠标滑轮放缩,鼠标中键拖住平移。");
		Initialize();


		glutMouseFunc(OnMouse);
		glutMotionFunc(onMouseMove);
		glutSpecialFunc(mySpecial);
		glutDisplayFunc(Display);
		glutReshapeFunc(Reshape);



		glutMainLoop();
		
	
	
		return 0;
	
}

    该代码为笔者c++实习时所写,逻辑格式问题较多,如有疑问请联系笔者,

该代码借鉴网络上部分代码,如有侵权,请联系删除。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/290894.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号