#include "OgreGTGeometry.h" #include OgreGTGeometry *Ogre::Singleton::ms_Singleton = 0; Geometry::Mesh *OgreGTGeometry::transform( const Ogre::Mesh *ogreMesh ) { bool copiedShared = false; size_t numSubMeshes = 0; size_t subMeshIndex = 0; Geometry::Mesh *mesh = new Geometry::Mesh(); mesh->mSubMeshCount = ogreMesh->getNumSubMeshes(); //--- Calc num of triangle-list subMeshes for(unsigned short i = 0; i < ogreMesh->getNumSubMeshes(); ++i) { Ogre::SubMesh *subMeshSrc = ogreMesh->getSubMesh(i); if (subMeshSrc->operationType == Ogre::RenderOperation::OT_TRIANGLE_LIST) { ++numSubMeshes; } else { Ogre::LogManager::getSingleton().logMessage( Ogre::String("SubMesh number ")+ Ogre::StringConverter::toString((unsigned int)i)+ Ogre::String(" ")+ogreMesh->getName()+ Ogre::String(" hasn't a valid Render Operation")); } } //--- allocate memory mesh->mSubMesh = new Geometry::SubMesh[numSubMeshes]; //--- foreach Ogre-SubMesh create our Geometry-SubMesh for(unsigned short smi = 0; smi < ogreMesh->getNumSubMeshes(); ++smi) { Ogre::SubMesh *subMeshSrc = ogreMesh->getSubMesh(smi); // Only Triangle list subMeshes if (subMeshSrc->operationType != Ogre::RenderOperation::OT_TRIANGLE_LIST) { continue; } Ogre::VertexData *vertexSrc = (subMeshSrc->useSharedVertices)? ogreMesh->sharedVertexData : subMeshSrc->vertexData; Ogre::IndexData *indexSrc = subMeshSrc->indexData; Geometry::SubMesh *subMeshDst = &(mesh->mSubMesh[subMeshIndex]); Geometry::VertexBuffer *vertexDst = 0; Geometry::Index *indexDst = 0; //--- Vertex info --- if (subMeshSrc->useSharedVertices) { if (!copiedShared) { mesh->mVertexBuffer = new Geometry::VertexBuffer; vertexDst = mesh->mVertexBuffer; vertexDst->mVertexCount = vertexSrc->vertexCount; copiedShared = true; } else { vertexDst = 0; } subMeshDst->mSharedVertexBuffer = true; subMeshDst->mVertexBuffer = mesh->mVertexBuffer; } else { subMeshDst->mSharedVertexBuffer = false; subMeshDst->mVertexBuffer = new Geometry::VertexBuffer; vertexDst = subMeshDst->mVertexBuffer; vertexDst->mVertexCount = vertexSrc->vertexCount; } if (vertexDst) { unsigned int vertexInfo = Geometry::VERTEX_EMPTY; if (loadVertexInfo(vertexSrc, vertexDst, Ogre::VES_POSITION, Geometry::VERTEX_POSITION)) { vertexInfo |= Geometry::VERTEX_POSITION; } if (loadVertexInfo(vertexSrc, vertexDst, Ogre::VES_NORMAL, Geometry::VERTEX_NORMAL)) { vertexInfo |= Geometry::VERTEX_NORMAL; } if(loadVertexInfo(vertexSrc, vertexDst, Ogre::VES_TEXTURE_COORDINATES, Geometry::VERTEX_TEXCOORDS)) { vertexInfo |= Geometry::VERTEX_TEXCOORDS; } vertexDst->mVertexInfo = vertexInfo; } if (subMeshDst->mSharedVertexBuffer) { subMeshDst->mVertexBuffer = mesh->mVertexBuffer; } //--- Index info --- indexDst = new Geometry::Index[indexSrc->indexCount]; subMeshDst->mIndex = indexDst; subMeshDst->mIndexCount = indexSrc->indexCount; Ogre::HardwareIndexBufferSharedPtr ibuf = indexSrc->indexBuffer; unsigned short *index16 = static_cast(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); if (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT) { unsigned int *index32 = (unsigned int*) index16; memcpy(indexDst, index32 + indexSrc->indexStart, indexSrc->indexCount*sizeof(unsigned int)); } else { for(size_t i = 0; i < indexSrc->indexCount; ++i, ++index16) { indexDst[i] = (unsigned int) *index16; } } ibuf->unlock(); subMeshIndex++; } return mesh; } bool OgreGTGeometry::loadVertexInfo(const Ogre::VertexData* ogreV, Geometry::VertexBuffer *geoV, Ogre::VertexElementSemantic ogreType,unsigned int geoType) { const Ogre::VertexElement* posElem = ogreV->vertexDeclaration-> findElementBySemantic(ogreType); if (posElem) { Ogre::HardwareVertexBufferSharedPtr vbuf = ogreV->vertexBufferBinding-> getBuffer(posElem->getSource()); unsigned char* vertex = static_cast(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); void* pSrc = 0; void* pDst = 0; size_t elementSize = 0; switch(geoType) { case (Geometry::VERTEX_POSITION): geoV->mPosition = new Geometry::Vector3[geoV->mVertexCount]; pDst = geoV->mPosition; elementSize = sizeof(Geometry::Vector3); break; case (Geometry::VERTEX_NORMAL): geoV->mNormal = new Geometry::Vector3[geoV->mVertexCount]; pDst = geoV->mNormal; elementSize = sizeof(Geometry::Vector3); break; case (Geometry::VERTEX_TEXCOORDS): geoV->mTexCoords = new Geometry::Vector2[geoV->mVertexCount]; pDst = geoV->mTexCoords; elementSize = sizeof(Geometry::Vector2); break; } for(size_t i = 0; i < ogreV->vertexCount; ++i, vertex += vbuf->getVertexSize(), pDst = (char*)pDst + elementSize ) { posElem->baseVertexPointerToElement(vertex, &pSrc); memcpy(pDst,pSrc,elementSize); } vbuf->unlock(); return true; } else { return false; } } Ogre::MeshPtr OgreGTGeometry::transform( const Geometry::Mesh *geoMesh, const Ogre::String name, const Ogre::String groupName) { Geometry::Real max_squaredLength = 0; Ogre::AxisAlignedBox aab; bool sharedVertexCopied = false; Ogre::MeshPtr mesh = Ogre::MeshManager::getSingleton().createManual(name, groupName, 0); for(size_t i = 0; i < geoMesh->mSubMeshCount; ++i) { Geometry::SubMesh *subMeshSrc = &(geoMesh->mSubMesh[i]); Ogre::SubMesh *subMeshDst = mesh->createSubMesh(); //--- Vertex Info ---- if ((subMeshSrc->mSharedVertexBuffer && !sharedVertexCopied) || !subMeshSrc->mSharedVertexBuffer) { Geometry::VertexBuffer *vertexDataSrc = (subMeshSrc->mSharedVertexBuffer)? geoMesh->mVertexBuffer : subMeshSrc->mVertexBuffer; unsigned int vertexInfo = vertexDataSrc->mVertexInfo; size_t numVerts = vertexDataSrc->mVertexCount; Ogre::VertexData *vertexData = new Ogre::VertexData(); Ogre::VertexDeclaration *vertexDec = new Ogre::VertexDeclaration(); size_t offset = 0; vertexData->vertexCount = numVerts; vertexData->vertexDeclaration = vertexDec; if (vertexInfo & Geometry::VERTEX_POSITION) { offset += vertexDec->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION).getSize(); } if (vertexInfo & Geometry::VERTEX_NORMAL) { offset += vertexDec->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL).getSize(); } if (vertexInfo & Geometry::VERTEX_TEXCOORDS) { offset += vertexDec->addElement(0, offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES).getSize(); } Ogre::HardwareVertexBufferSharedPtr vbuf = Ogre::HardwareBufferManager::getSingleton(). createVertexBuffer(vertexDec->getVertexSize(0), numVerts, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, true); unsigned char* data = static_cast(vbuf->lock(Ogre::HardwareBuffer::HBL_DISCARD)); // Fill data for(size_t j = 0; j < numVerts; ++j) { if (vertexInfo & Geometry::VERTEX_POSITION) { Geometry::Vector3 &v = vertexDataSrc->mPosition[j]; Ogre::Vector3 ogre_v(v.val); *((Geometry::Vector3*)data) = v; data+=sizeof(Geometry::Vector3); if (v.squaredLength() > max_squaredLength) max_squaredLength = v.squaredLength(); aab.merge(ogre_v); } if (vertexInfo & Geometry::VERTEX_NORMAL) { *((Geometry::Vector3*)data) = vertexDataSrc->mNormal[j]; data+=sizeof(Geometry::Vector3); } if (vertexInfo & Geometry::VERTEX_TEXCOORDS) { *((Geometry::Vector2*)data) = vertexDataSrc->mTexCoords[j]; data+=sizeof(Geometry::Vector2); } } vbuf->unlock(); vertexData->vertexBufferBinding->setBinding(0, vbuf); if (subMeshSrc->mSharedVertexBuffer) { mesh->sharedVertexData = vertexData; sharedVertexCopied = true; subMeshDst->useSharedVertices = true; } else { subMeshDst->vertexData = vertexData; subMeshDst->useSharedVertices = false; } } //--- Index info --- Ogre::HardwareIndexBufferSharedPtr ibuf= Ogre::HardwareBufferManager::getSingleton(). createIndexBuffer(Ogre::HardwareIndexBuffer::IT_32BIT, subMeshSrc->mIndexCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, true); ibuf->writeData(0, ibuf->getSizeInBytes(), subMeshSrc->mIndex, true); subMeshDst->indexData->indexBuffer = ibuf; subMeshDst->indexData->indexCount = subMeshSrc->mIndexCount; subMeshDst->indexData->indexStart = 0; //--- Misc ---- subMeshDst->operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST; } mesh->_setBounds(aab); mesh->_setBoundingSphereRadius(sqrt(max_squaredLength)); mesh->load(); return mesh; }