btTriangleMesh* GameLibrary::ogreToBulletMesh(Ogre::MeshPtr mesh) { btTriangleMesh* btMesh = new btTriangleMesh(); Ogre::Mesh::SubMeshIterator j = mesh->getSubMeshIterator(); while (j.hasMoreElements()) { Ogre::SubMesh* submesh = j.getNext(); int idxStart = submesh->indexData->indexStart; int nIdx = submesh->indexData->indexCount; Ogre::HardwareIndexBuffer* idxBuffer = submesh->indexData->indexBuffer.get(); Ogre::HardwareVertexBufferSharedPtr virtBuffer; Ogre::VertexDeclaration* virtDecl; if (submesh->useSharedVertices) { virtDecl = mesh->sharedVertexData->vertexDeclaration; assert(mesh->sharedVertexData->vertexBufferBinding->getBufferCount() > 0); virtBuffer = mesh->sharedVertexData->vertexBufferBinding->getBuffer(0); } else { virtDecl = submesh->vertexData->vertexDeclaration; assert(submesh->vertexData->vertexBufferBinding->getBufferCount() > 0); virtBuffer = submesh->vertexData->vertexBufferBinding->getBuffer(0); } unsigned char* pVert = static_cast<unsigned char*>(virtBuffer->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); // need to lock the buffer since vertex data resides on GPU // and we need synchronization unsigned short* sindices = NULL; unsigned long* lindices = NULL; if (idxBuffer->getType() == Ogre::HardwareIndexBuffer::IT_16BIT) { sindices = static_cast<unsigned short*>(idxBuffer->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); } else if (idxBuffer->getType() == Ogre::HardwareIndexBuffer::IT_32BIT) { lindices = static_cast<unsigned long*>(idxBuffer->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); } else { assert(true == false); } const Ogre::VertexElement* elm = virtDecl->findElementBySemantic(Ogre::VES_POSITION, 0); int offset = elm->getOffset(); // assert(elm->getType() == VET_FLOAT3); for (int k = idxStart; k < idxStart + nIdx; k += 3) { unsigned int indices[3]; btVector3 vertices[3]; if (idxBuffer->getType() == Ogre::HardwareIndexBuffer::IT_16BIT) { for (int l = 0; l < 3; ++l) { indices[l] = sindices[k + l]; } } else { for (int l = 0; l < 3; ++l) { indices[l] = lindices[k + l]; } } for (int l = 0; l < 3; ++l) { // for each vertex Ogre::Real* posVert = (Ogre::Real*)(pVert + indices[l] * virtBuffer->getVertexSize() + offset); for (int m = 0; m < 3; ++m) { // for each vertex component vertices[l][m] = posVert[m]; } } btMesh->addTriangle(vertices[0], vertices[1], vertices[2]); } idxBuffer->unlock(); virtBuffer->unlock(); } return btMesh; }
void BtOgreSoftBody::updateOgreMesh() { Ogre::Node *ogreNode = mEntity->getParentNode(); //printf("updateOgreMesh %d %s %s\n", internalId, mEntity->getName().c_str(), ogreNode->getName().c_str()); Ogre::MeshPtr mesh = mEntity->getMesh(); Ogre::Mesh::SubMeshIterator subMeshI = mesh->getSubMeshIterator(); Ogre::SubMesh* subMesh = NULL; Ogre::VertexData* vData = NULL; Ogre::VertexDeclaration* vDeclaration = NULL; const Ogre::VertexElement* vPosElement = NULL; bool isSharedVerticesAdded = false; unsigned short bufferIndex = 0; Ogre::HardwareVertexBufferSharedPtr vBuffer; // Can not do arithmetic operations on void* unsigned char* lockedMem = NULL; float* vPosition; btSoftBody::tNodeArray& btNodes = mSoftBody->m_nodes; //printf("Bullet nodes size %d\n", btNodes.size()); int ogreVertexIdx = 0; while (subMeshI.hasMoreElements()) { subMesh = subMeshI.getNext(); if (subMesh->useSharedVertices) { if (isSharedVerticesAdded) { continue; } vData = mesh->sharedVertexData; // We need to add shared vertices only once isSharedVerticesAdded = true; } else { vData = subMesh->vertexData; } vDeclaration = vData->vertexDeclaration; vPosElement = vDeclaration->findElementBySemantic(Ogre::VES_POSITION); bufferIndex = vPosElement->getSource(); vBuffer = vData->vertexBufferBinding->getBuffer(bufferIndex); // Lock the buffer before reading from it lockedMem = static_cast<unsigned char*>(vBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD)); // Read each vertex for (unsigned int i = 0; i < vData->vertexCount; ++i) { vPosElement->baseVertexPointerToElement(lockedMem, &vPosition); int idx = getBulletIndex(ogreVertexIdx); *vPosition++ = btNodes[idx].m_x.x(); *vPosition++ = btNodes[idx].m_x.y(); *vPosition = btNodes[idx++].m_x.z(); // Point to the next vertex lockedMem += vBuffer->getVertexSize(); ogreVertexIdx++; } vBuffer->unlock(); } btTransform transform = mSoftBody->getWorldTransform(); btQuaternion rot = transform.getRotation(); ogreNode->setOrientation(rot.w(), rot.x(), rot.y(), rot.z()); btVector3 pos = transform.getOrigin(); ogreNode->setPosition(pos.x(), pos.y(), pos.z()); }
mesh::mesh(const std::string &mn, const mat4 &tf, const world &_world): /** Don't know if world() is the best thing to pass but it works for now **/ _mesh(NewtonMeshCreate(_world)) { Ogre::MeshPtr meshPtr; try { meshPtr = Ogre::MeshPtr(Ogre::MeshManager::getSingleton().load(mn, Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME)); } catch(...) { return; } const Ogre::Mesh &mesh = *meshPtr; NewtonMeshBeginFace(_mesh); for (unsigned smi = 0; smi < mesh.getNumSubMeshes(); smi++) { Ogre::SubMesh *subMesh = mesh.getSubMesh(smi); Ogre::VertexData *vertexData = (subMesh->useSharedVertices) ? vertexData = mesh.sharedVertexData : vertexData = subMesh->vertexData; Ogre::VertexDeclaration *vertexDecl = vertexData->vertexDeclaration; const Ogre::VertexElement *element = vertexDecl->findElementBySemantic(Ogre::VES_POSITION); Ogre::HardwareVertexBufferSharedPtr vertexHVBSP = vertexData->vertexBufferBinding->getBuffer(element->getSource()); unsigned char *vPtr = (unsigned char*)(vertexHVBSP->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); Ogre::IndexData *indexData = subMesh->indexData; size_t numIndices = indexData->indexCount; size_t numTris = numIndices / 3; // get pointer! Ogre::HardwareIndexBufferSharedPtr indexHIBSP = indexData->indexBuffer; // 16 or 32 bit indices? bool indicesAre32Bit = (indexHIBSP->getType() == Ogre::HardwareIndexBuffer::IT_32BIT); unsigned long *longPtr = NULL; unsigned short *shortPtr = NULL; if (indicesAre32Bit) longPtr = static_cast<unsigned long*>( indexHIBSP->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); else shortPtr = static_cast<unsigned short*>( indexHIBSP->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); //now loop through the indices, getting polygon info! int iOffset = 0; for (size_t i = 0; i < numTris; i++) { vec3 triVertices[3]; unsigned char *vOffset = NULL; float *vertexPosPtr = NULL; int idx = 0; for (int j = 0; j < 3; j++) { if (indicesAre32Bit) idx = longPtr[iOffset + j]; else idx = shortPtr[iOffset + j]; vOffset = vPtr + (idx * vertexHVBSP->getVertexSize()); element->baseVertexPointerToElement(vOffset, &vertexPosPtr); triVertices[j].x = *vertexPosPtr; vertexPosPtr++; triVertices[j].y = *vertexPosPtr; vertexPosPtr++; triVertices[j].z = *vertexPosPtr; vertexPosPtr++; triVertices[j] = tf * triVertices[j]; } // _mesh, 3 vertices (triangle), (float = 4 bytes) * 3 // index = index of sub mesh (easy to recognize) NewtonMeshAddFace(_mesh, 3, &triVertices[0].x, sizeof(float) * 3, smi); iOffset += 3; } //unlock the buffers! vertexHVBSP->unlock(); indexHIBSP->unlock(); } NewtonMeshEndFace(_mesh); }