Deleting compound shapes

cobolt_dink
Posts: 72
Joined: Fri Apr 04, 2008 6:07 pm

Deleting compound shapes

Post by cobolt_dink »

During the course of the game when a entity is killed I remove the rigid body when destroying the rest of the entity. This code works fine for regular shapes but crashes when trying to delete a compound shape. What is the proper way of deleting compound shapes?

Code: Select all

void CEntity::DeleteBody()
{	
	if (GetBody() != NULL)
	{
		// still may be rendering the object so set the entity position to the current rigid
		// body position before deleting the rigid body
		D3DXMATRIX mat;
		btTransform trans;

		GetBody()->getMotionState()->getWorldTransform(trans);

		mat = ConvertBulletTransform(&trans);

		btCollisionObject *obj = static_cast<btCollisionObject *>(GetBody());
		
		m_world->removeCollisionObject(obj);
	
		m_world->removeRigidBody(GetBody());

		delete GetBody()->getMotionState();
		delete GetBody();

		D3DXQuaternionRotationMatrix(&m_rotation, &mat);
		
		SetBody(NULL);
		
		SetPosition(D3DXVECTOR3(mat._41, mat._42, mat._43));
	}
}
GetBody() returns the btRigidBody pointer. The crash is an access viloation when calling the removeCollisionObject() function.
cobolt_dink
Posts: 72
Joined: Fri Apr 04, 2008 6:07 pm

Re: Deleting compound shapes

Post by cobolt_dink »

It was crashing on a null pointer.

But I was reading that compound shapes don't remove their own children. So is the following code is what is needed to make sure a compound cleans up after itself?

Code: Select all

void CEntity::DeleteBody()
{	
	if (GetBody() != NULL)
	{
		// still may be rendering the object so set the entity position to the current rigid
		// body position before deleting the rigid body
		D3DXMATRIX mat;
		btTransform trans;

		GetBody()->getMotionState()->getWorldTransform(trans);

		mat = ConvertBulletTransform(&trans);

		btCollisionObject *obj = static_cast<btCollisionObject *>(GetBody());
		
		btCollisionShape *shape = obj->getCollisionShape();
				
		if (shape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE)
		{
			btCompoundShape *compound = static_cast<btCompoundShape *>(shape);

			for (int i=0; i<compound->getNumChildShapes(); ++i)
			{
				btCollisionShape *s = compound->getChildShape(i);
				compound->removeChildShape(s);
			}
		}

		m_world->removeCollisionObject(obj);
	
		m_world->removeRigidBody(GetBody());

		delete GetBody()->getMotionState();
		delete GetBody();

		D3DXQuaternionRotationMatrix(&m_rotation, &mat);
		
		SetBody(NULL);
		
		SetPosition(D3DXVECTOR3(mat._41, mat._42, mat._43));
	}
}
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: Deleting compound shapes

Post by Erwin Coumans »

Two obvious issues:
  • It is better to store all collision shape in a separate array, including child shapes of compound shapes, and delete them separately. Use 'delete' and not 'removeChildShape'.
  • addRigidBody should be used with removeRigidBody, and addCollisionObject should be used with removeCollisionObject. Don't call them both for a single object.
Hope this helps,
Erwin