Collision detection and leaving the objects in a safe pos.

Adversus
Posts: 19
Joined: Mon Nov 10, 2008 11:24 am

Collision detection and leaving the objects in a safe pos.

Post by Adversus »

I'm iterating over the contact manifolds after the time step like the example CollisionInterfaceDemo shows to detect collision and to respond.

There's just one other thing, I need to place them in a "safe" location where they don't overlap together. This is a complicated problem due to multiple collisions and I was wondering if Bullet provides any functionality for this (I'm assuming it does as the physics would require it).

Thanks.
Adversus
Posts: 19
Joined: Mon Nov 10, 2008 11:24 am

Re: Collision detection and leaving the objects in a safe pos.

Post by Adversus »

Has no-one had to do this?

How do people handle the collisions when a kinematic object collides with a static object so that the kinematic object just doesn't pass straight through it?
sparkprime
Posts: 508
Joined: Fri May 30, 2008 2:51 am
Location: Ossining, New York

Re: Collision detection and leaving the objects in a safe pos.

Post by sparkprime »

I wouldn't use a kinematic object in such a situation (i.e. when i wanted it to respond to collisions from other objects). What you are doing is reimplementing the dynamics engine :) What you should do is use a non-kinematic body, apply forces to effect movement in your body, and use the dynamics provided by bullet to resolve collisions.


In general I'm not sure there's any solution to your problem since in a sphere could get "jammed" in a cranny and the only solution would be to remove it from the cranny entirely. The best option is to prevent it from getting into such a situation in the first place, and that means preventing tunnelling etc. (Assuming I understood your problem.)
Adversus
Posts: 19
Joined: Mon Nov 10, 2008 11:24 am

Re: Collision detection and leaving the objects in a safe pos.

Post by Adversus »

Using forces to move things around isn't suitable for most games.
sparkprime
Posts: 508
Joined: Fri May 30, 2008 2:51 am
Location: Ossining, New York

Re: Collision detection and leaving the objects in a safe pos.

Post by sparkprime »

Why not? Either impulses or forces have been sufficient for all my needs so far.
User avatar
Dragonlord
Posts: 198
Joined: Mon Sep 04, 2006 5:31 pm
Location: Switzerland

Re: Collision detection and leaving the objects in a safe pos.

Post by Dragonlord »

If your game has complex animations/interactions or non-FPS environments you can quickly hit walls with this approach.
sparkprime
Posts: 508
Joined: Fri May 30, 2008 2:51 am
Location: Ossining, New York

Re: Collision detection and leaving the objects in a safe pos.

Post by sparkprime »

Wasn't his problem that he wasn't hitting walls? :)

Seriously, can you give examples of problems forces/impulses cause? This could cause me to have to redesign so I'd rather know about this as early as possible.
Nacho
Posts: 31
Joined: Tue Mar 04, 2008 1:41 pm

Re: Collision detection and leaving the objects in a safe pos.

Post by Nacho »

I do it with this code (I copy&paste it and it can have errors):

Code: Select all

bool GetPenetrationDepth(const btConvexShape* pShapeFromKinematicRigidBody, const btTransform& oShapeFromKinematicRBTrans,
				 btCollisionShape* pShapeFromCollisionRB, const btTransform& oShapeFromCollisionRBTrans, CXCollision& oCollision) const
{
	if( !pShapeFromCollisionRB->isCompound() )
	{
		// Compute penetration depth
		btSimplexSolverInterface simplexSolver;
		btGjkEpaPenetrationDepthSolver Solver;
		btVoronoiSimplexSolver sGjkSimplexSolver;
		btConvexShape* pShapeA=static_cast<btConvexShape*>(pShapeFromCollisionRB);
		btGjkPairDetector GJK(pShapeA, pShapeFromKinematicRigidBody, &sGjkSimplexSolver, &Solver);
		btDiscreteCollisionDetectorInterface::ClosestPointInput input;
		input.m_transformA = oShapeFromCollisionRBTrans;
		input.m_transformB = oShapeFromKinematicRBTrans;
		input.m_stackAlloc = &gStackAlloc;
		CU1CollisionDetector output;
		GJK.getClosestPoints(input, output, 0);
		if( output.m_bHasResult )
		{
			btVector3 vNormal=output.m_vNormalOnBInWorld;
			oCollision.m_fPenetration=-output.m_fDepth;
			oCollision.m_vColNormal.Set(-vNormal.x(), -vNormal.y(), -vNormal.z());
			oCollision.m_vColPosition.Set(output.m_vPointInWorld.x(), output.m_vPointInWorld.y(), output.m_vPointInWorld.z());
			oCollision.m_bIsCollided=true;
			return true;
		}
	}
	else
	{	// Compound shapes
		float fMaxPenetration=-FLT_MAX;
		btCompoundShape* pCompoundShape=static_cast<btCompoundShape*>(pShapeFromCollisionRB);
		uint iNumChild=pCompoundShape->getNumChildShapes();
		bool bRet=false;
		for(uint i=0; i<iNumChild; ++i)
		{
			btCollisionShape* pChildShape=pCompoundShape->getChildShape(i);
			btTransform	btChildTransform=pCompoundShape->getChildTransform(i);
			btChildTransform*=oShapeFromCollisionRBTrans;
			CXCollision oCollisionTmp;
			if( GetPenetrationDepth(pShape, oShapeTrans, pChildShape, oColShapeTrans, oCollisionTmp) &&
				(oCollisionTmp.m_fPenetration>fMaxPenetration) )
			{
				oCollision=oCollisionTmp;
				fMaxPenetration=oCollisionTmp.m_fPenetration;
				bRet=true;
			}
		}
		return bRet;
	}
	return false;
}


// For each object collided:
bool bCollision=GetPenetrationDepth(m_pKinematicRBShape, m_oKinematicRBShapeTrans, pColObjectShape, oColObjectShapeTrans, oCollision);
if( bCollision )
{  // vPosition is the position of the kinematic RB
    vPosition.x+=(oCollision.m_vNormal.x*oCollision.m_fPenetration);
    vPosition.y+=(oCollision.m_vNormal.y*oCollision.m_fPenetration);
    vPosition.z+=(oCollision.m_vNormal.z*oCollision.m_fPenetration);
}
The idea is compute the penetration depth and collision normal between our kinematic rigid body (simulating player) and one collided object (detected in normal bullet step). Then, we move the kinematic rigid body using the vector vCollisionNormal*fPenetrationDepth.

The only way I see to do it was using btGjkPairDetector. Other solutions are welcome.


Nacho