Bug in logic of btParallelConstraintSolver and Islands

Topher
Posts: 10
Joined: Mon Dec 06, 2010 2:30 pm

Bug in logic of btParallelConstraintSolver and Islands

Post by Topher »

We've come across a case using btParallelConstraintSolver (2.77) where SolveGroup is accessing incorrect memory when dealing with manifolds, which causes corrupt float operations later.

The situation is when there is a manifold in btParallelConstraintSolver.cpp between two bodies, but one of the bodies companionId is still -2 (from btSimulationIslandManager::storeIslandActivationState()).

This results in CustomSetupContactConstraints accessing offsetRigBodies with an index of 0xfffe.

I've narrowed the situation down to a collision between a Dynamic object hitting a Kinematic object, but the Kinematic object is discarded from the island at these two points:

Code: Select all

void   btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld)
{
	// put the islandId ('find' value) into m_tag   
	{
		int index = 0;
		int i;
		for (i=0;i<colWorld->getCollisionObjectArray().size();i++)
		{
			btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i];
			if (!collisionObject->isStaticOrKinematicObject())
			{
				collisionObject->setIslandTag( m_unionFind.find(index) );
				//Set the correct object offset in Collision Object Array
				m_unionFind.getElement(index).m_sz = i;
				collisionObject->setCompanionId(-1);
				index++;
			} else
			{
				collisionObject->setIslandTag(-1);
				collisionObject->setCompanionId(-2);
			}
		}
	}
}

Code: Select all

void   btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher)
{

	// put the index into m_controllers into m_tag   
	int index = 0;
	{

		int i;
		for (i=0;i<colWorld->getCollisionObjectArray().size(); i++)
		{
			btCollisionObject*   collisionObject= colWorld->getCollisionObjectArray()[i];
			//Adding filtering here
			if (!collisionObject->isStaticOrKinematicObject())
			{
				collisionObject->setIslandTag(index++);
			}
			collisionObject->setCompanionId(-1);
			collisionObject->setHitFraction(btScalar(1.));
		}
	}
	// do the union find

	initUnionFind( index );

	findUnions(dispatcher,colWorld);
}
If you notice, the index value only increases when the object is Dynamic. This is not the case for the unoptimized versions (STATIC_SIMULATION_ISLAND_OPTIMIZATION).

These only seem to be used with STATIC_SIMULATION_ISLAND_OPTIMIZATION turned on and as such, turning it off fixes the issue.

Additionally btSequentialImpulseConstraintSolver seems to deal with the situation fine. But from looking through the code, it doesn't appear to rely upon the islands in any way.
Topher
Posts: 10
Joined: Mon Dec 06, 2010 2:30 pm

Re: Bug in logic of btParallelConstraintSolver and Islands

Post by Topher »

Looking closer at the unoptimised function and the optimised function, the issue seems to be with the index being incremented at the wrong point.

Unoptimised

Code: Select all

void	btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld)
{
	// put the islandId ('find' value) into m_tag	
	{


		int index = 0;
		int i;
		for (i=0;i<colWorld->getCollisionObjectArray().size();i++)
		{
			btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i];
			if (!collisionObject->isStaticOrKinematicObject())
			{
				collisionObject->setIslandTag( m_unionFind.find(index) );
				collisionObject->setCompanionId(-1);
			} else
			{
				collisionObject->setIslandTag(-1);
				collisionObject->setCompanionId(-2);
			}
			index++;
		}
	}
}
Optimised

Code: Select all

void   btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld)
{
	// put the islandId ('find' value) into m_tag   
	{
		int index = 0;
		int i;
		for (i=0;i<colWorld->getCollisionObjectArray().size();i++)
		{
			btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i];
			if (!collisionObject->isStaticOrKinematicObject())
			{
				collisionObject->setIslandTag( m_unionFind.find(index) );
				//Set the correct object offset in Collision Object Array
				m_unionFind.getElement(index).m_sz = i;
				collisionObject->setCompanionId(-1);
				index++;
			} else
			{
				collisionObject->setIslandTag(-1);
				collisionObject->setCompanionId(-2);
			}
		}
	}
}
Where in the optimised version it only increments the index if it's dynamic.
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: Bug in logic of btParallelConstraintSolver and Islands

Post by Erwin Coumans »

The btParallelConstraintSolver is not well optimized yet, so you might get better results with the original btSequentialImpulseConstraintSolver.

Just like the MultiThreadedDemo, you need to switch off island generation, are you doing that?

Code: Select all

world->getSimulationIslandManager()->setSplitIslands(false);
Thanks,
Erwin
Topher
Posts: 10
Joined: Mon Dec 06, 2010 2:30 pm

Re: Bug in logic of btParallelConstraintSolver and Islands

Post by Topher »

Erwin Coumans wrote:The btParallelConstraintSolver is not well optimized yet, so you might get better results with the original btSequentialImpulseConstraintSolver.

Just like the MultiThreadedDemo, you need to switch off island generation, are you doing that?

Code: Select all

world->getSimulationIslandManager()->setSplitIslands(false);
Thanks,
Erwin
Aha, didn't spot that last time I looked at the demo :). I'll give it a try, thanks!