In the previous article, we introduced how to convert vertices and texture data of ply files into mesh files, but there is no texture data yet. This article describes how to add textures. The Code is as follows:
/* * File: CxMesh.h * Author: zhuxiaoyang (cgnerds@gmail.com) * * 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 filebool cxReadPly(const String fileName);bool cxComposeMesh(void);};#endif // __CxMesh_H__
#include "CxMesh.h"CxMesh::CxMesh(const String& meshName){this->meshName = meshName;// for the headnumFaces = 0;numVertices = 0;vertices = NULL;faces = NULL;texcoords = NULL;}CxMesh::~CxMesh(){// for the headif(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 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,6).c_str() ); //** the length of the substr may changeelse 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 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];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 filefin.close();return true;}bool CxMesh::cxComposeMesh(){// 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);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 coordinatesif(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 indicesindexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer(HardwareIndexBuffer::IT_32BIT,3*numFaces,HardwareBuffer::HBU_STATIC, true);indexBuffer->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();return true;}
An example of calling this class is as follows:
String meshMocap = "meshMocap";CxMesh* mMocap = new CxMesh(meshMocap);mMocap->cxReadPly(m_szAvatarModel);mMocap->cxComposeMesh();// Create a modelSceneNode* mModelNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("ModelNode");Entity* mModel = mSceneMgr->createEntity("MyModel", meshMocap);mModel->setMaterialName("Havok/Head");mModelNode->attachObject(mModel);
The material name is Havok/head, which can be edited by yourself.