serializing / deserializing btBvhTriangleShape
Posted: Tue Nov 02, 2010 1:58 pm
I'm writing a tool to convert an Ogre mesh file to a bullet file for use in our game. Problem is, I can't for the life of me get serializing / deserializing to work as expected; the triangle data produced is just plain wrong. I've been stepping through bullet all day long trying to find the cause, and came to the conclusion that the triangle data was getting deleted as the btWorldImporter went out of scope (it deletes data it did not allocate!) so I instead allocated the world importer on the heap and (for testing purposes) never delete it - yet when I view the deserialized mesh by enabling debug draw, I get a series of lines going from the origin to infinity in all directions. I read elsewhere on the forum that Bullet never makes a copy of the data it reads from the .bullet file, so I instead filled a buffer from the file myself, and ensured that the data was not deleted prematurely, but this didn't help either.
Well, I think it's about time for some code - beware of the leaks; this is purely for testing purposes.
Serialize
Deserialize
I can verify that the mesh strider is producing valid data (it's this one from the Ogre wiki), as the BVH triangle mesh appears just fine prior to serialization. Is there anything obvious I'm missing? This is driving me nuts.
Note: I have tried this with the simplest mesh I could come up with - a tetrahedron, but that was no help. I've attached the bullet file from the screenshot if anyone wants to take a look at it (it's meant to be a tank trap)
Well, I think it's about time for some code - beware of the leaks; this is purely for testing purposes.
Serialize
Code: Select all
void OgreMeshCollisionHull::serialize(std::string const &path)
{
std::string directory, fileName, extension;
size_t slashPos = path.find_last_of("\\/");
if(slashPos != std::string::npos)
{
++slashPos;
size_t dotPos = path.find_last_of('.');
directory = path.substr(0, slashPos);
fileName = path.substr(slashPos, dotPos - slashPos);
extension = path.substr(dotPos, std::string::npos);
}
//Create a large enough buffer. There is no method to pre-calculate the buffer size yet.
const size_t byteCount = 1024 * 1024 * 5;
btDefaultSerializer *pSerializer = new btDefaultSerializer(byteCount);
pSerializer->registerNameForPointer(m_pCollisionShape, fileName.c_str());
pSerializer->startSerialization();
m_pCollisionShape->serializeSingleShape(pSerializer);
pSerializer->finishSerialization();
std::fstream file;
file.open(path.c_str(), std::ios_base::out | std::ios_base::binary);
file.write((const char *)pSerializer->getBufferPointer(), pSerializer->getCurrentBufferSize());
file.close();
delete pSerializer;
pSerializer = 0;
}
Code: Select all
void OgreMeshCollisionHull::deserialize(BulletPhysicsWorld &physics, std::string const &path)
{
std::fstream file;
file.open(path.c_str(), std::ios_base::in | std::ios_base::binary | std::ios_base::ate);
if(file)
{
m_byteCount = file.tellg();
file.seekg(0, std::ios::beg);
m_pData = new char[m_byteCount];
file.read(m_pData, m_byteCount);
file.close();
}
//Leaks ahoy!
btBulletWorldImporter *pImporter = new btBulletWorldImporter;
if(pImporter->loadFileFromMemory(m_pData, m_byteCount))
{
int numShapes = pImporter->getNumCollisionShapes();
if(numShapes >= 1)
{
m_pCollisionShape = (btBvhTriangleMeshShape*)new char[sizeof(btBvhTriangleMeshShape)];
memcpy((void*)m_pCollisionShape, (void*)pImporter->getCollisionShapeByIndex(0), sizeof(btBvhTriangleMeshShape));
btRigidBody::btRigidBodyConstructionInfo constructionInfo(0.0f, NULL, m_pCollisionShape);
physics.addRigidBody(constructionInfo);
}
}
}
Note: I have tried this with the simplest mesh I could come up with - a tetrahedron, but that was no help. I've attached the bullet file from the screenshot if anyone wants to take a look at it (it's meant to be a tank trap)