This function will change the handedness of a loaded mesh. For this to work, the mesh must have read- and writeable
hardware buffers (which is the default, if you load the model using SceneManager::createEntity(String, String)). This
snippet will reverse the Z axis, although reversing any axis would be enough to change handedness, inverting z should
be the most common use case.
Furthermore, the LOD levels will be removed, since they are no longer correct.
Copy to clipboard
void invertZ(Ogre::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); // reverse Z pReal[2] = -pReal[2]; } vbuf->unlock(); next_offset += vertex_data->vertexCount; } // reverse the triangles, otherwise they will be facing the wrong direction // again we need to unwrap the data 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_NORMAL)); unsigned short* pShort = reinterpret_cast<unsigned short*>(pLong); // the data is ready, do the swapping if (use32bitindexes) { for (size_t k = 0; k < numTris * 3; k += 3) { unsigned long swapSpace = pLong[k + 2]; pLong[k + 2] = pLong[k + 1]; pLong[k + 1] = swapSpace; } } else { for (size_t k = 0; k < numTris * 3; k += 3) { unsigned short swapSpace = pShort[k + 2]; pShort[k + 2] = pShort[k + 1]; pShort[k + 1] = swapSpace; } } ibuf->unlock(); current_offset = next_offset; } // Adjust the bounding box Ogre::AxisAlignedBox box = mesh->getBounds(); Ogre::Vector3 min = box.getMinimum(); Ogre::Vector3 max = box.getMaximum(); box.setExtents(min.x, min.y, -max.z, max.x, max.y, -min.z); mesh->_setBounds(box); // Remove LOD Levels mesh->removeLodLevels(); }