Is my code not cleaning-up properly all the btBoxShape alloc

Post Reply
rraallvv
Posts: 30
Joined: Thu Feb 09, 2012 2:39 am

Is my code not cleaning-up properly all the btBoxShape alloc

Post by rraallvv »

I've changed the BasicDemo project in bullet physics to create one collision shape per rigid body instead of sharing the same collision shape. This is because the need to apply a per shape collision filter that tells apart which collision shape is colliding by looking at it's user pointer.

This is the original initialisation:

Code: Select all

void    BasicDemo::initPhysics()
{
        //...

        {
                //create a few dynamic rigidbodies
                // Re-using the same collision is better for memory usage and performance

                btBoxShape* colShape = new btBoxShape(btVector3(SCALING*1,SCALING*1,SCALING*1));
                //btCollisionShape* colShape = new btSphereShape(btScalar(1.));
                m_collisionShapes.push_back(colShape);

                /// Create Dynamic Objects
                btTransform startTransform;
                startTransform.setIdentity();

                btScalar        mass(1.f);

                //rigidbody is dynamic if and only if mass is non zero, otherwise static
                bool isDynamic = (mass != 0.f);

                btVector3 localInertia(0,0,0);
                if (isDynamic)
                        colShape->calculateLocalInertia(mass,localInertia);

                float start_x = START_POS_X - ARRAY_SIZE_X/2;
                float start_y = START_POS_Y;
                float start_z = START_POS_Z - ARRAY_SIZE_Z/2;

                for (int k=0;k<ARRAY_SIZE_Y;k++)
                {
                        for (int i=0;i<ARRAY_SIZE_X;i++)
                        {
                                for(int j = 0;j<ARRAY_SIZE_Z;j++)
                                {
                                        startTransform.setOrigin(SCALING*btVector3(
                                                                                btScalar(2.0*i + start_x),
                                                                                btScalar(20+2.0*k + start_y),
                                                                                btScalar(2.0*j + start_z)));


                                        //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
                                        btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
                                        btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,colShape,localInertia);
                                        btRigidBody* body = new btRigidBody(rbInfo);


                                        m_dynamicsWorld->addRigidBody(body);
                                }
                        }
                }
        }
}
I've changed it like this:

Code: Select all

void    BasicDemo::initPhysics()
{
        //...

    {
        /// Create Dynamic Objects
        btTransform startTransform;
        startTransform.setIdentity();

        btScalar    mass(1.f);

        //rigidbody is dynamic if and only if mass is non zero, otherwise static
        bool isDynamic = (mass != 0.f);

        float start_x = START_POS_X - ARRAY_SIZE_X/2;
        float start_y = START_POS_Y;
        float start_z = START_POS_Z - ARRAY_SIZE_Z/2;

        for (int k=0;k<ARRAY_SIZE_Y;k++)
        {
            for (int i=0;i<ARRAY_SIZE_X;i++)
            {
                for(int j = 0;j<ARRAY_SIZE_Z;j++)
                {
                    //create one collision shape per body to be able to assign different user points
                    btBoxShape* colShape = new btBoxShape(btVector3(SCALING*1,SCALING*1,SCALING*1));

                    m_collisionShapes.push_back(colShape);

                    btVector3 localInertia(0,0,0);
                    if (isDynamic)
                        colShape->calculateLocalInertia(mass,localInertia);


                    startTransform.setOrigin(SCALING*btVector3(btScalar(2.0*i + start_x),
                                                               btScalar(20+2.0*k + start_y),
                                                               btScalar(2.0*j + start_z)));


                    //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
                    btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
                    btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,colShape,localInertia);
                    btRigidBody* body = new btRigidBody(rbInfo);


                    m_dynamicsWorld->addRigidBody(body);
                }
            }
        }
    }
}
This is the clean-up code:

Code: Select all

void    BasicDemo::exitPhysics()
{

    //cleanup in the reverse order of creation/initialization

    //remove the rigidbodies from the dynamics world and delete them
    int i;
    for (i=m_dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--)
    {
        btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i];
        btRigidBody* body = btRigidBody::upcast(obj);
        if (body && body->getMotionState())
        {
            delete body->getMotionState();
        }
        m_dynamicsWorld->removeCollisionObject( obj );
        delete obj;
    }

    //delete collision shapes
    for (int j=0;j<m_collisionShapes.size();j++)
    {
        btCollisionShape* shape = m_collisionShapes[j];
        delete shape;
    }
    m_collisionShapes.clear();

    delete m_dynamicsWorld;

    delete m_solver;

    delete m_broadphase;

    delete m_dispatcher;

    delete m_collisionConfiguration;


}
To my knowledge, the clean-up code doesn't need to be modified to take care of the different approach since my new code inserts each collision shape into the m_collisionShapes that holds track of all the shapes allocated in the initialization.

Is there something I'm missing? because Xcode Instruments shows a fixed increment in memory each time I restart the simulation, even when there seems to be no memory leaks.

Image
xexuxjy
Posts: 225
Joined: Wed Jan 07, 2009 11:43 am
Location: London

Re: Is my code not cleaning-up properly all the btBoxShape a

Post by xexuxjy »

couldn't see anything obvious, but I'm a bit puzzled why you're doing it the way you're doing it . You can add a different user pointer to each rigid body (CollisionObject) while they all share the same collision shape, so you could keep the existing demo implementation of a single shape. just set the userpointer on the RB rather than the collision shape
rraallvv
Posts: 30
Joined: Thu Feb 09, 2012 2:39 am

Re: Is my code not cleaning-up properly all the btBoxShape a

Post by rraallvv »

xexuxjy wrote:couldn't see anything obvious, but I'm a bit puzzled why you're doing it the way you're doing it . You can add a different user pointer to each rigid body (CollisionObject) while they all share the same collision shape, so you could keep the existing demo implementation of a single shape. just set the userpointer on the RB rather than the collision shape
Yes, your are right, but I want to create compound bodies each child shape with its own user pointer, in order to use the gCompoundChildShapePairCallback.

I've just added one shape per collision object to make a quick test, but since it is leaking, I didn't add more shapes.

Anyway, I've found that the leak is somewhere in the renderme() function, I commented out that line of code, and that was it, the app ran without any leaks, although showing a black window ofcourse.
Post Reply