Changing Coordinate Handedness         Function to change the handedness of a loaded mesh

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.

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();
}