btRigidBody contains btCompoundShape
btCompountShape contains btBoxShape and btSphereShape
The problem is that when I print the number of collision shapes deserialized, it differs from the number of collision shapes actually in use y all the collision objects.
It seems that either one or the other, btDefaultSeralizer or btBulletWorldImporter, are saving or restoring twice the number of child shapes.
To reproduce the issue just download bullet v 2.82 and add this code to the App_SerializeDemo application in the SerializeDemo.cpp file:
Before the serialisation take place
Code: Select all
// create a simple tree like object
{
btCompoundShape *comp = new btCompoundShape;
btBoxShape *box = new btBoxShape(btVector3(2,2,2));
btSphereShape *sphere = new btSphereShape(2);
btTransform tbox, tsphere;
tbox.setIdentity();
tsphere.setIdentity();
tbox.setOrigin(btVector3(-2,0,0));
tsphere.setOrigin(btVector3(2,0,0));
comp->addChildShape(tbox, box);
comp->addChildShape(tsphere, sphere);
btTransform tbody;
tbody.setIdentity();
tbody.setOrigin(btVector3(0,10,-10));
btScalar mass(1);
bool isDynamic = (mass != 0.f);
btVector3 localInertia(0,0,0);
if (isDynamic)
groundShape->calculateLocalInertia(mass,localInertia);
btRigidBody *body = new btRigidBody(
mass,
new btDefaultMotionState(tbody),
comp,
localInertia);
m_dynamicsWorld->addRigidBody(body);
}
// count the number of collision shapes actually in use
int count = 0;
btHashMap<btHashPtr, btCollisionShape*> shapes;
for (int i=0; i<m_dynamicsWorld->getNumCollisionObjects(); i++) {
btCollisionShape *shape = m_dynamicsWorld->getCollisionObjectArray()[i]->getCollisionShape();
if (!shapes.find(shape)) {
count++;
shapes.insert(shape, shape);
}
if (shape->isCompound()) {
btCompoundShape *comp = (btCompoundShape*) shape;
for (int j=0; j<comp->getNumChildShapes(); j++) {
btCollisionShape *child = comp->getChildShape(j);
if (!shapes.find(child)) {
count++;
shapes.insert(child, child);
}
}
}
}
// logging information: print the the number of objects that should be serialised
printf("serialization\n");
printf("# constraints: %d\n", m_dynamicsWorld->getNumConstraints());
printf("# collision objects: %d\n", m_dynamicsWorld->getNumCollisionObjects());
printf("# collision shapes: %d\n", count);
Code: Select all
if (!m_fileLoader->loadFile("testFile.bullet"))
{
//....
}
else
{
// count the collision shapes that are actually in use
int count = 0;
btHashMap<btHashPtr, btCollisionShape*> shapes;
for (int i=0; i<m_fileLoader->getNumRigidBodies(); i++) {
btCollisionShape *shape = m_fileLoader->getRigidBodyByIndex(i)->getCollisionShape();
if (!shapes.find(shape)) {
count++;
shapes.insert(shape, shape);
}
if (shape->isCompound()) {
btCompoundShape *comp = (btCompoundShape*) shape;
for (int j=0; j<comp->getNumChildShapes(); j++) {
btCollisionShape *child = comp->getChildShape(j);
if (!shapes.find(child)) {
count++;
shapes.insert(child, child);
}
}
}
}
// logging information: print the the number of objects that where deserialised
printf("deserialization\n");
printf("# constraints: %d\n", m_fileLoader->getNumConstraints());
printf("# collision objects: %d\n", m_fileLoader->getNumRigidBodies());
printf("# collision shapes: %d actually in use, %d loaded\n", count, m_fileLoader->getNumCollisionShapes()); //<------discrepancy here!!!!!!
}