處理Maya、3D Max模型時,我們首先需要處理頂點/索引資料。這裡分兩步進行:
(1)得到頂點/索引資料
這裡可以參考OGRE官網上的代碼,需要注意的是官網上參數Mesh為指針類型,而今Mesh已經有了MeshPtr類作為Mesh的指針。代碼如下:
void getMeshInfo(const Ogre::MeshPtr mesh,
size_t &vertex_count,
Ogre::Vector3* &vertices,
size_t &index_count,
unsigned long* &indices,
const Ogre::Vector3 &position = Vector3::ZERO,
const Ogre::Quaternion &orient = Quaternion::IDENTITY,
const Ogre::Vector3 &scale = Vector3::UNIT_SCALE)
{
bool added_shared = false;
size_t current_offset = 0;
size_t shared_offset = 0;
size_t next_offset = 0;
size_t index_offset = 0;
vertex_count = index_count = 0;
// Calculate how many vertices and indices we're going to need
for(unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i)
{
Ogre::SubMesh* submesh = mesh->getSubMesh(i);
// We noly need to add the shared vertices once
if(submesh->useSharedVertices)
{
if(!added_shared)
{
vertex_count += mesh->sharedVertexData->vertexCount;
added_shared = true;
}
}
else
{
vertex_count += submesh->vertexData->vertexCount;
}
// Add the indices
index_count += submesh->indexData->indexCount;
}
// Allocate space for the vertices and indices
vertices = new Ogre::Vector3[vertex_count];
indices = new unsigned long[index_count];
added_shared = false;
// Run through the submeshes again, adding the data into arrays
for(unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i)
{
Ogre::SubMesh* submesh = mesh->getSubMesh(i);
Ogre::VertexData* vertex_data = submesh->useSharedVertices ? mesh->sharedVertexData : submesh->vertexData;
if( (!submesh->useSharedVertices) || (submesh->useSharedVertices && !added_shared) )
{
if(submesh->useSharedVertices)
{
added_shared = true;
shared_offset = current_offset;
}
const Ogre::VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
Ogre::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());
unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
float* pReal;
for(size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize())
{
posElem->baseVertexPointerToElement(vertex, &pReal);
Ogre::Vector3 pt(pReal[0], pReal[1], pReal[2]);
vertices[current_offset + j] = (orient * (pt * scale)) + position;
}
vbuf->unlock();
next_offset += vertex_data->vertexCount;
}
Ogre::IndexData* index_data = submesh->indexData;
size_t numTris = index_data->indexCount / 3;
Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;
bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT);
unsigned long* pLong = static_cast<unsigned long*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
unsigned short* pShort = reinterpret_cast<unsigned short*>(pLong);
size_t offset = (submesh->useSharedVertices) ? shared_offset : current_offset;
if(use32bitindexes)
{
for(size_t k = 0; k < numTris * 3; ++k)
{
indices[index_offset++] = pLong[k] + static_cast<unsigned long>(offset);
}
}
else
{
for(size_t k = 0; k < numTris * 3; ++k)
{
indices[index_offset++] = static_cast<unsigned long>(pShort[k]) + static_cast<unsigned long>(offset);
}
}
ibuf->unlock();
current_offset = next_offset;
}
}
該函數使用方法如下:
Entity* mEye = mSceneMgr->createEntity("MyEye", "eye.mesh");
//get the mesh info
size_t vertex_count, index_count;
Vector3* vertices;
unsigned long* indices;
getMeshInfo(mEye->getMesh(), vertex_count, vertices, index_count, indices);
Ogre::String output;
stringstream ss;
ss<<"***************Vertices in mesh: ";
ss<<vertices[0].x <<" "<<vertices[0].y <<" "<<vertices[0].z <<" ";
ss<<"***************";
output = ss.str();
LogManager::getSingleton().logMessage(output);
這樣就可以在Ogre.log中看到輸出資訊了。
(2)修改頂點/索引資料并再次渲染模型
void updateMesh(const MeshPtr mesh)
{
bool added_shared = false;
size_t current_offset = 0;
size_t shared_offset = 0;
size_t next_offset = 0;
// foreach SubMesh
for (unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i)
{
Ogre::SubMesh* submesh = mesh->getSubMesh(i);
Ogre::VertexData* vertex_data = submesh->useSharedVertices ? mesh->sharedVertexData : submesh->vertexData;
if ((!submesh->useSharedVertices) || (submesh->useSharedVertices && !added_shared))
{
if (submesh->useSharedVertices)
{
added_shared = true;
shared_offset = current_offset;
}
// the real vertex data is wrapped into lots of classes
const Ogre::VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
Ogre::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());
unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_NORMAL));
float* pReal;
for (size_t j = 0; j < vertex_data->vertexCount; j++, vertex += vbuf->getVertexSize())
{
// get vertex data
posElem->baseVertexPointerToElement(vertex, &pReal);
// modify vertex data
pReal[2] += 0.0001;
}
vbuf->unlock();
next_offset += vertex_data->vertexCount;
}
}
}