Changing Coordinate Handedness
From Ogre Wiki
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();
}

