通过调用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" #includeCPLYLoader::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++实习时所写,逻辑格式问题较多,如有疑问请联系笔者,
该代码借鉴网络上部分代码,如有侵权,请联系删除。



