//----------------------------------------------------------------------- void InstanceManager::unshareVertices(const Ogre::MeshPtr &mesh) { // Retrieve data to copy bone assignments const Mesh::VertexBoneAssignmentList& boneAssignments = mesh->getBoneAssignments(); Mesh::VertexBoneAssignmentList::const_iterator it = boneAssignments.begin(); Mesh::VertexBoneAssignmentList::const_iterator end = boneAssignments.end(); size_t curVertexOffset = 0; // Access shared vertices VertexData* sharedVertexData = mesh->sharedVertexData; for (size_t subMeshIdx = 0; subMeshIdx < mesh->getNumSubMeshes(); subMeshIdx++) { SubMesh *subMesh = mesh->getSubMesh(subMeshIdx); IndexData *indexData = subMesh->indexData; HardwareIndexBuffer::IndexType idxType = indexData->indexBuffer->getType(); IndicesMap indicesMap = (idxType == HardwareIndexBuffer::IT_16BIT) ? getUsedIndices<uint16>(indexData) : getUsedIndices<uint32>(indexData); VertexData *newVertexData = new VertexData(); newVertexData->vertexCount = indicesMap.size(); newVertexData->vertexDeclaration = sharedVertexData->vertexDeclaration->clone(); for (size_t bufIdx = 0; bufIdx < sharedVertexData->vertexBufferBinding->getBufferCount(); bufIdx++) { HardwareVertexBufferSharedPtr sharedVertexBuffer = sharedVertexData->vertexBufferBinding->getBuffer(bufIdx); size_t vertexSize = sharedVertexBuffer->getVertexSize(); HardwareVertexBufferSharedPtr newVertexBuffer = HardwareBufferManager::getSingleton().createVertexBuffer (vertexSize, newVertexData->vertexCount, sharedVertexBuffer->getUsage(), sharedVertexBuffer->hasShadowBuffer()); uint8 *oldLock = (uint8*)sharedVertexBuffer->lock(0, sharedVertexData->vertexCount * vertexSize, HardwareBuffer::HBL_READ_ONLY); uint8 *newLock = (uint8*)newVertexBuffer->lock(0, newVertexData->vertexCount * vertexSize, HardwareBuffer::HBL_NORMAL); IndicesMap::iterator indIt = indicesMap.begin(); IndicesMap::iterator endIndIt = indicesMap.end(); for (; indIt != endIndIt; ++indIt) { memcpy(newLock + vertexSize * indIt->second, oldLock + vertexSize * indIt->first, vertexSize); } sharedVertexBuffer->unlock(); newVertexBuffer->unlock(); newVertexData->vertexBufferBinding->setBinding(bufIdx, newVertexBuffer); } if (idxType == HardwareIndexBuffer::IT_16BIT) { copyIndexBuffer<uint16>(indexData, indicesMap); } else { copyIndexBuffer<uint32>(indexData, indicesMap); } // Store new attributes subMesh->useSharedVertices = false; subMesh->vertexData = newVertexData; // Transfer bone assignments to the submesh size_t offset = curVertexOffset + newVertexData->vertexCount; for (; it != end; ++it) { size_t vertexIdx = (*it).first; if (vertexIdx > offset) break; VertexBoneAssignment boneAssignment = (*it).second; boneAssignment.vertexIndex = static_cast<unsigned int>(boneAssignment.vertexIndex - curVertexOffset); subMesh->addBoneAssignment(boneAssignment); } curVertexOffset = newVertexData->vertexCount + 1; } // Release shared vertex data delete mesh->sharedVertexData; mesh->sharedVertexData = NULL; mesh->clearBoneAssignments(); }
//--------------------------------------------------------------------- void OptimiseTool::processMesh(Ogre::MeshPtr mesh) { bool rebuildEdgeList = false; // Shared geometry if (mesh->sharedVertexData) { print("Optimising mesh shared vertex data..."); setTargetVertexData(mesh->sharedVertexData); for (unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i) { SubMesh* sm = mesh->getSubMesh(i); if (sm->useSharedVertices) { addIndexData(sm->indexData); } } if (optimiseGeometry()) { if (mesh->getSkeletonName() != StringUtil::BLANK) { print(" fixing bone assignments..."); Mesh::BoneAssignmentIterator currentIt = mesh->getBoneAssignmentIterator(); Mesh::VertexBoneAssignmentList newList = getAdjustedBoneAssignments(currentIt); mesh->clearBoneAssignments(); for (Mesh::VertexBoneAssignmentList::iterator bi = newList.begin(); bi != newList.end(); ++bi) { mesh->addBoneAssignment(bi->second); } } for (unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i) { SubMesh* sm = mesh->getSubMesh(i); if (mesh->getSkeletonName() != StringUtil::BLANK) { print(" fixing bone assignments..."); Mesh::BoneAssignmentIterator currentIt = sm->getBoneAssignmentIterator(); Mesh::VertexBoneAssignmentList newList = getAdjustedBoneAssignments(currentIt); sm->clearBoneAssignments(); for (Mesh::VertexBoneAssignmentList::iterator bi = newList.begin(); bi != newList.end(); ++bi) { sm->addBoneAssignment(bi->second); } } if (sm->useSharedVertices) { fixLOD(sm->mLodFaceList); } } rebuildEdgeList = true; } } // Dedicated geometry for (unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i) { SubMesh* sm = mesh->getSubMesh(i); if (!sm->useSharedVertices) { print("Optimising submesh " + StringConverter::toString(i) + " dedicated vertex data "); setTargetVertexData(sm->vertexData); addIndexData(sm->indexData); if (optimiseGeometry()) { if (mesh->getSkeletonName() != StringUtil::BLANK) { print(" fixing bone assignments..."); Mesh::BoneAssignmentIterator currentIt = sm->getBoneAssignmentIterator(); Mesh::VertexBoneAssignmentList newList = getAdjustedBoneAssignments(currentIt); sm->clearBoneAssignments(); for (Mesh::VertexBoneAssignmentList::iterator bi = newList.begin(); bi != newList.end(); ++bi) { sm->addBoneAssignment(bi->second); } } fixLOD(sm->mLodFaceList); rebuildEdgeList = true; } } } if (rebuildEdgeList && mesh->isEdgeListBuilt()) { // force rebuild of edge list mesh->freeEdgeList(); mesh->buildEdgeList(); } }