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

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

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

#include <iostream>
#include <cstdlib>
#include<string>
#include <liblas/liblas.hpp>
#include <pcl/io/io.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/io/ply_io.h>
#include<pcl/PCLPointCloud2.h>
#include <pcl/io/obj_io.h>


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<pcl::PointXYZRGB> 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<float*>(&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 <GL/glut.h>
#include <GL/glu.h>
#include <GL/gl.h>
#include <vector>
#include <Windows.h>
#include <cmath>

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 <iostream>

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 failed\n", 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 opened\n");
		}
	}
	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 <stdio.h>
#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++实习时所写,逻辑格式问题较多,如有疑问请联系笔者,

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

  • 9
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
要在QT C++显示可控制的3D模型,您可以使用Qt 3D Studio。Qt 3D Studio是一个可视化工具,可以创建3D用户界面,其包括3D模型、动画、交互和逻辑。使用此工具,您可以在QT应用程序嵌入3D模型。 以下是一些步骤,可以帮助您显示可控制的3D模型: 1. 下载并安装Qt 3D Studio 2. 在Qt Creator创建一个新的Qt Quick项目 3. 在项目文件夹创建一个名为"3D"的新文件夹 4. 将您的3D模型文件(例如.obj或.fbx)复制到该文件夹 5. 在Qt 3D Studio打开您的3D模型文件,并将其导出到3D文件夹 6. 在Qt Creator创建一个新的QML文件,并在其添加以下代码: ``` import Qt3D.Core 2.0 import Qt3D.Render 2.0 import Qt3D.Input 2.0 import QtQuick 2.0 Entity { id: root Camera { id: camera projectionType: CameraLens.PerspectiveProjection fieldOfView: 45 aspectRatio: 16/9 nearPlane : 0.1 farPlane : 1000.0 position: Qt.vector3d(0.0, 0.0, 40.0) upVector: Qt.vector3d(0.0, 1.0, 0.0) viewCenter: Qt.vector3d(0.0, 0.0, 0.0) } OrbitCameraController { camera: camera } RenderSettings { activeFrameGraph: ForwardRenderer { camera: camera } } components: [ // Add the 3D model SceneLoader { id: sceneLoader source: "3D/your_model_file_name.qml" } ] } ``` 7. 将上面的代码的“your_model_file_name.qml”替换为您的模型文件的名称。 8. 运行您的QT应用程序,您现在应该能够看到您的3D模型,并可以使用鼠标控制它的旋转和缩放。 希望这可以帮助您开始显示可控制的3D模型

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东北大马猴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值