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.
Table of contents
Original version
Copy to clipboard
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) { if(!added_shared) { VertexData* vertex_data = mesh->sharedVertexData; vertex_count += vertex_data->vertexCount; added_shared = true; } } 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]; added_shared = false; // 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)||(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)); 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:
Copy to clipboard
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:
Copy to clipboard
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) { 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 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) { 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)); // 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; } }