Recently, I want to convert meshlab's ply model to ogre's mesh model. The initial idea is:
(1) convert the ply model to the OBJ model supported by Maya in meshlab;
(2) Use the plug-in to export the OBJ model to the mesh model in Maya.
The above idea is feasible, but after export, it is found that although the number of patches has not changed, the number of vertices has increased a lot. Since each vertex is precisely controlled, such an export is of no value. After repeated consideration, I decided to write a small program to convert ply directly into mesh.
First, I implemented the export of ply data with vertex and index as mesh models.
The Code is as follows:
/* * File: CxMesh.h * Author: zhuxiaoyang (cgnerds@gmail.com) * * Created on July 25th, 2011, PM 7:00 */#ifndef __CxMesh_H__#define __CxMesh_H__#include <Ogre.h>#include <fstream>using namespace Ogre;using namespace std;class CxMesh{private:MeshPtr mesh;SubMesh *subMesh;String meshName;int numFaces;int numVertices;float* vertices;int* faces;HardwareVertexBufferSharedPtr posVertexBuffer;HardwareIndexBufferSharedPtr indexBuffer;public:CxMesh(const String& meshName);virtual ~CxMesh();// Read and write ply filebool cxReadPly(const String fileName);};#endif // __CxMesh_H__
#include "CxMesh.h"CxMesh::CxMesh(const String& meshName){this->meshName = meshName;numFaces = 0;numVertices = 0;vertices = NULL;}CxMesh::~CxMesh(){if(vertices)delete[] vertices;MeshManager::getSingleton().remove(meshName);}bool CxMesh::cxReadPly(const String fileName) {// Open the .ply file for readingifstream fin( fileName.c_str() );if(!fin){ String errMsg = "//** Error opening ply file for input!"; Ogre::LogManager::getSingleton().logMessage(errMsg);return false;}// Analysing the fileString plyStr;while( getline(fin, plyStr) ){if(plyStr == "end_header")break;if( plyStr.substr(0, 7) == "element" ){if( plyStr.substr(8, 6) == "vertex" )numVertices = atoi( plyStr.substr(15,8).c_str() ); //** the length of the substr may changeelse if(plyStr.substr(8, 4) == "face") numFaces = atoi( plyStr.substr(13,8).c_str() );}}// Read vertex data from the filevertices = new float[numVertices*3];for(int i = 0; i < numVertices; ++i){fin>>vertices[i * 3 + 0] >>vertices[i * 3 + 1] >>vertices[i * 3 + 2];}// Read face data from the filefaces = new int[numFaces*3];int temp;for(int i = 0; i < numFaces; ++i){fin>>temp>>faces[i * 3 + 0] >>faces[i * 3 + 1] >>faces[i * 3 + 2];}// Close the filefin.close();// Create mesh and submeshmesh = MeshManager::getSingleton().createManual(meshName,ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);subMesh = mesh->createSubMesh();// Vertex Buffermesh->sharedVertexData = new VertexData();mesh->sharedVertexData->vertexCount = numVertices;VertexDeclaration* vdecl = mesh->sharedVertexData->vertexDeclaration;VertexBufferBinding* vbind = mesh->sharedVertexData->vertexBufferBinding;vdecl->addElement(0, 0, VET_FLOAT3, VES_POSITION);// Prepare buffer for positions posVertexBuffer = HardwareBufferManager::getSingleton().createVertexBuffer( 3*sizeof(float),numVertices,HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE);posVertexBuffer->writeData(0, posVertexBuffer->getSizeInBytes(), vertices, true);vbind->setBinding(0, posVertexBuffer);// Prepare buffer for indicesindexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer(HardwareIndexBuffer::IT_32BIT,3*numFaces,HardwareBuffer::HBU_STATIC, true);// Upload the index data to the cardindexBuffer->writeData(0, indexBuffer->getSizeInBytes(), faces, true);// Set parameters of the submeshsubMesh->useSharedVertices = true;subMesh->indexData->indexBuffer = indexBuffer;subMesh->indexData->indexStart = 0;subMesh->indexData->indexCount = 3*numFaces;mesh->_setBounds( AxisAlignedBox(-100, -100, -100, 100, 100, 100) );// Notify -Mesh object that it has been loadedmesh->load();mesh->touch();Ogre::StringStream ss;ss<<setprecision(10)<<"//** The vertex count is "<<numVertices <<" ** the index count is " <<numFaces <<"The first vertex is "<<vertices[0]<<" "<<vertices[1]<<" "<<vertices[2] <<"**The last vertex is"<<vertices[(numVertices-1)*3+0]<<" " <<vertices[(numVertices-1)*3+1]<<" "<<vertices[(numVertices-1)*3+2] <<"The first face is "<<faces[0]<<" "<<faces[1]<<" "<<faces[2] <<"**The last vertex is"<<faces[(numFaces-1)*3+0]<<" " <<faces[(numFaces-1)*3+1]<<" "<<faces[(numFaces-1)*3+2];Ogre::LogManager::getSingleton().logMessage( ss.str() );return true;}
When running the program, you can call the following code:
//** Read a .ply file and convert it to mesh String meshMocap = "meshMocap";CxMesh mMocap = new CxMesh( meshMocap );mMocap->cxReadPly("mocap.ply");// Add a model to the sceneOgre::SceneNode* mModelNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("ModelNode");Ogre::Entity* mModel = mSceneMgr->createEntity("MyModel", meshMocap); mModelNode->attachObject(mModel);mModelNode->scale(0.5, 0.5, 0.5);
In this way, you can see the model in the program.