MeshLab的ply模型转化为Ogre所需的mesh模型(一)

最近希望将MeshLab的ply模型转化为Ogre的mesh模型,最初的思路是:

(1)在MeshLab中将ply模型转化为Maya支持的obj模型;

(2)利用插件,在Maya中将obj模型导出为mesh模型。

上述思路是可行的,但导出后发现虽然面片数目没变,但顶点数目增加了很多。由于精确控制到每个顶点,故这样的导出是没有价值的。经过再三考虑,我决定自己写一个小程序,能将ply直接转化为mesh。

我首先实现的是将只有顶点(vertex)和索引(index)的ply数据导出为mesh模型。

代码如下:

/*
 * File:   CxMesh.h
 * Author: zhuxiaoyang ([email protected])
 *
 * 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 file
	bool 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 reading
	ifstream fin( fileName.c_str() );
	if(!fin)
	{
	    String errMsg = "//** Error opening ply file for input!";
	    Ogre::LogManager::getSingleton().logMessage(errMsg);
		return false;		
	}

	// Analysing the file
	String 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 change
			else if(plyStr.substr(8, 4) == "face")
			    numFaces = atoi( plyStr.substr(13,8).c_str() );
		}
	}
	// Read vertex data from the file
	vertices = 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 file
	faces = 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 file
	fin.close();

	// Create mesh and submesh
	mesh = MeshManager::getSingleton().createManual(meshName,
		ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
	subMesh = mesh->createSubMesh();

	// Vertex Buffer
	mesh->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 indices
	indexBuffer = 
		HardwareBufferManager::getSingleton().createIndexBuffer(
		HardwareIndexBuffer::IT_32BIT,
		3*numFaces,
		HardwareBuffer::HBU_STATIC, true);

	// Upload the index data to the card
	indexBuffer->writeData(0, indexBuffer->getSizeInBytes(), faces, true);

	// Set parameters of the submesh
	subMesh->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 loaded
	mesh->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;
}
程序运行时,可调用如下代码:

	//** 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 scene
	Ogre::SceneNode* mModelNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("ModelNode");
	Ogre::Entity* mModel = mSceneMgr->createEntity("MyModel", meshMocap); 
        mModelNode->attachObject(mModel);
	mModelNode->scale(0.5, 0.5, 0.5);
这样就可以在程序中看到模型了。

MeshLab的ply模型转化为Ogre所需的mesh模型(一)_第1张图片


你可能感兴趣的:(String,upload,File,buffer,Parameters,float)