天天看點

Ogre 處理頂點/索引資料

處理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;

}

}