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

在前一篇文章中,介绍了将ply文件的顶点和纹理数据转化成mesh文件的方法,但还没有纹理数据,这篇文章给出的是添加纹理的方法。代码如下:

/*
 * File:   CxMesh.h
 * Author: zhuxiaoyang ([email protected])
 *
 * Created on Aug 5th, 2011, PM 3:00
 */
#ifndef __CxMesh_H__
#define __CxMesh_H__

#include <Ogre.h>
#include <fstream>

using namespace Ogre;
using namespace std;

class CxMesh
{
public:
	MeshPtr mesh;
	SubMesh *subMesh;
	String meshName;
	int numFaces;
	int numVertices;
	float* vertices;
	int*   faces;
	float* texcoords;
	bool hasTexture;

	HardwareVertexBufferSharedPtr posVertexBuffer;
	HardwareVertexBufferSharedPtr texcoordsVertexBuffer;
	HardwareIndexBufferSharedPtr indexBuffer;

public:
	CxMesh(const String& meshName);
	virtual ~CxMesh();

	// Read and write ply file
	bool cxReadPly(const String fileName);
	bool cxComposeMesh(void);
};


#endif // __CxMesh_H__

#include "CxMesh.h"

CxMesh::CxMesh(const String& meshName)
{
	this->meshName    = meshName;

	// for the head
	numFaces    = 0;
	numVertices = 0;
	vertices  = NULL;
	faces     = NULL;
	texcoords = NULL;
}

CxMesh::~CxMesh()
{
	// for the head
	if(vertices)
		delete[] vertices;
	if(faces)
		delete[] faces;
	if(texcoords)
		delete[] texcoords;

	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,6).c_str() ); //** the length of the substr may change
			else if(plyStr.substr(8, 4) == "face")
			    numFaces = atoi( plyStr.substr(13,6).c_str() );
		}
		if(plyStr.substr(0,7) == "comment" && plyStr.substr(8, 11) == "TextureFile")
			hasTexture = true;
	}

	// 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];
	texcoords = new float[numVertices*2];
	int nF, nT;
	if(hasTexture)
	{
		for(int i = 0; i < numFaces ; ++i)
	    {
			fin>>nF>>faces[i * 3 + 0]
				   >>faces[i * 3 + 1]
				   >>faces[i * 3 + 2];
			fin>>nT>>texcoords[ faces[i * 3 + 0] * 2 + 0 ]
			       >>texcoords[ faces[i * 3 + 0] * 2 + 1 ]
				   >>texcoords[ faces[i * 3 + 1] * 2 + 0 ]
			       >>texcoords[ faces[i * 3 + 1] * 2 + 1 ]
				   >>texcoords[ faces[i * 3 + 2] * 2 + 0 ]
			       >>texcoords[ faces[i * 3 + 2] * 2 + 1 ];
		   texcoords[ faces[i * 3 + 0] * 2 + 1 ] = 1.0f - texcoords[ faces[i * 3 + 0] * 2 + 1 ];
		   texcoords[ faces[i * 3 + 1] * 2 + 1 ] = 1.0f - texcoords[ faces[i * 3 + 1] * 2 + 1 ];
		   texcoords[ faces[i * 3 + 2] * 2 + 1 ] = 1.0f - texcoords[ faces[i * 3 + 2] * 2 + 1 ];
	    }
	}
	else
	{
		for(int i = 0; i < numFaces; ++i)
		{
			fin>>nF>>faces[i * 3 + 0]
				   >>faces[i * 3 + 1]
				   >>faces[i * 3 + 2];
		}
	}
	// Close the file
	fin.close();

	return true;
}

bool CxMesh::cxComposeMesh()
{
	// 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);
	if(hasTexture)
	    vdecl->addElement(1, 0, VET_FLOAT2, VES_TEXTURE_COORDINATES);

	// 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 texture coordinates
	if(hasTexture)
	{
		texcoordsVertexBuffer = 
			HardwareBufferManager::getSingleton().createVertexBuffer(
				2*sizeof(float),
				numVertices,
				HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY);
		texcoordsVertexBuffer->writeData(0, texcoordsVertexBuffer->getSizeInBytes(), texcoords, true);
		vbind->setBinding(1, texcoordsVertexBuffer);
	}

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

	return true;
}

调用该类的示例如下:

String  meshMocap    = "meshMocap";
CxMesh* mMocap = new CxMesh(meshMocap);
mMocap->cxReadPly(m_szAvatarModel);
mMocap->cxComposeMesh();

// Create a model
SceneNode* mModelNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("ModelNode");
Entity*    mModel     = mSceneMgr->createEntity("MyModel", meshMocap);
mModel->setMaterialName("Havok/Head");
mModelNode->attachObject(mModel);
其中材质的名称是Havok/Head,可以自己编写。


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