RetrieveVertexData         Retrieving vertex data from a mesh

This example is taken from monster's OgreODE project. The full source can be found under ogreaddons/ogreode in the Ogre SVN.
It has been adopted, so that it can be used separately. Just copy/paste it into your own project.

Note that this code assumes sizeof(long) == sizeof(uint32_t), which is not true on AMD64 Linux.

A port to Mogre can be found in this article.

## Original version

```void getMeshInformation(Mesh* mesh,size_t &vertex_count,Vector3* &vertices,
size_t &index_count, unsigned* &indices,
const Vector3 &position = Vector3::ZERO,
const Quaternion &orient = Quaternion::IDENTITY,const Vector3 &scale = Vector3::UNIT_SCALE)
{
vertex_count = index_count = 0;

bool added_shared = false;
size_t current_offset = vertex_count;
size_t shared_offset = vertex_count;
size_t next_offset = vertex_count;
size_t index_offset = index_count;
size_t prev_vert = vertex_count;
size_t prev_ind = index_count;

// Calculate how many vertices and indices we're going to need
for(int i = 0;i < mesh->getNumSubMeshes();i++)
{
SubMesh* submesh = mesh->getSubMesh(i);

// We only need to add the shared vertices once
if(submesh->useSharedVertices)
{
{
VertexData* vertex_data = mesh->sharedVertexData;
vertex_count += vertex_data->vertexCount;
}
}
else
{
VertexData* vertex_data = submesh->vertexData;
vertex_count += vertex_data->vertexCount;
}

// Add the indices
Ogre::IndexData* index_data = submesh->indexData;
index_count += index_data->indexCount;
}

// Allocate space for the vertices and indices
vertices = new Vector3[vertex_count];
indices = new unsigned[index_count];

// Run through the submeshes again, adding the data into the arrays
for(int i = 0;i < mesh->getNumSubMeshes();i++)
{
SubMesh* submesh = mesh->getSubMesh(i);

Ogre::VertexData* vertex_data = submesh->useSharedVertices ? mesh->sharedVertexData : submesh->vertexData;
{
if(submesh->useSharedVertices)
{
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));
Ogre::Real* pReal;

for(size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize())
{
posElem->baseVertexPointerToElement(vertex, &pReal);

Vector3 pt;

pt.x = (*pReal++);
pt.y = (*pReal++);
pt.z = (*pReal++);

pt = (orient * (pt * scale)) + position;

vertices[current_offset + j].x = pt.x;
vertices[current_offset + j].y = pt.y;
vertices[current_offset + j].z = pt.z;
}
vbuf->unlock();
next_offset += vertex_data->vertexCount;
}

Ogre::IndexData* index_data = submesh->indexData;

size_t numTris = index_data->indexCount / 3;
unsigned short* pShort;
unsigned int* pInt;
Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;
bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT);
if (use32bitindexes) pInt = static_cast<unsigned int*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
else pShort = static_cast<unsigned short*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));

for(size_t k = 0; k < numTris; ++k)
{
size_t offset = (submesh->useSharedVertices)?shared_offset:current_offset;

unsigned int vindex = use32bitindexes? *pInt++ : *pShort++;
indices[index_offset + 0] = vindex + offset;
vindex = use32bitindexes? *pInt++ : *pShort++;
indices[index_offset + 1] = vindex + offset;
vindex = use32bitindexes? *pInt++ : *pShort++;
indices[index_offset + 2] = vindex + offset;

index_offset += 3;
}
ibuf->unlock();
current_offset = next_offset;
}
}```

Example usage:

```Entity *ent = mSceneMgr->createEntity("head", "ogrehead.mesh");

size_t vertex_count,index_count;
Vector3* vertices;
unsigned* indices;

getMeshInformation(ent->getMesh(),vertex_count,vertices,index_count,indices);

LogManager::getSingleton().logMessage(LML_NORMAL,"Vertices in mesh: %u",vertex_count);
LogManager::getSingleton().logMessage(LML_NORMAL,"Triangles in mesh: %u",index_count / 3);

delete[] vertices;
delete[] indices;```

## Optimized version

Below is a modified version of getMeshInformation(). It was based on "Monsters" function. This modified version does exactly the same like the one above, but is slightly modified to be more understandable, has a few fixes and a few speed optimizations.
I just thought I share it back to the community, so here it is:

```void getMeshInformation(const Ogre::Mesh* const mesh,
size_t &vertex_count,
Ogre::Vector3* &vertices,
size_t &index_count,
unsigned long* &indices,
const Ogre::Vector3 &position,
const Ogre::Quaternion &orient,
const Ogre::Vector3 &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 only need to add the shared vertices once
if(submesh->useSharedVertices)
{
{
vertex_count += mesh->sharedVertexData->vertexCount;
}
}
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];

// Run through the submeshes again, adding the data into the 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)
{
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 =

// There is _no_ baseVertexPointerToElement() which takes an Ogre::Real or a double
//  as second argument. So make it float, to avoid trouble when Ogre::Real will
//  be comiled/typedefed as double:
//Ogre::Real* pReal;
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;
}
}```

### Online Users

24 online users