sliding collision response

Started by
2 comments, last by pokky 13 years, 7 months ago
Hi, I'm having trouble with sliding collision response. I can't find any tutorials. I using a BVH acceleration structure and the plane-Sphere intersection test for collision detection. It works great, the sphere is pushed back with the sliding motion but it also slowly sinks through the mesh (the plane) when the sphere motion is zero.
I can't work out how to fix this problem and I've tried pretty much everything I can think of, adding extra values, scaling the push vector, etc. Can anyone help?

I post the code:

void CPhysicsManager::CollideObjects(CCollisionInfoVector& Collisions)
{
for(unsigned int i = 0; i < Collisions.size(); i++)
{
CCollisionInfo CollisionInfo = Collisions;
CEntityPtr pEntityA = CollisionInfo.pEntity1;
CEntityPtr pEntityB = CollisionInfo.pEntity2;

CVector3 Normal = CollisionInfo.Normal;

CVector3 VectorAP = CollisionInfo.Point - pEntityA->GetPosition()->GetCenter();
CVector3 VectorBP = CollisionInfo.Point - pEntityB->GetPosition()->GetCenter();

CVector3 VelocityA = pEntityA->GetMotion()->GetVelocity() + CVector3::Cross(pEntityA->GetMotion()->GetAngularVelocity(),VectorAP);
CVector3 VelocityB = pEntityB->GetMotion()->GetVelocity() + CVector3::Cross(pEntityB->GetMotion()->GetAngularVelocity(),VectorBP);

CVector3 VelocityAB = VelocityA - VelocityB;

float dirDiff = CVector3::Dot(VelocityAB,Normal);
if(dirDiff < 0)
{
float fRestitution = CollisionInfo.fRestitution;
float fFriction = CollisionInfo.fFriction;

CVector3 Tangent = CVector3::Normalize(CVector3::Cross(CVector3::Cross(Normal,VelocityAB),Normal));

float fNumerator = -(1+ fRestitution ) * dirDiff;

CVector3 APTemp = CVector3::Cross(CMatrix::TransformNormal(CVector3::Cross(VectorAP,Normal),pEntityA->GetCollisionModel()->GetInertiaTensorInverse()),VectorAP);
CVector3 BPTemp = CVector3::Cross(CMatrix::TransformNormal(CVector3::Cross(VectorBP,Normal),pEntityB->GetCollisionModel()->GetInertiaTensorInverse()),VectorBP);

float fMassA = pEntityA->GetCollisionModel()->GetOneOverMass();
float fMassB = pEntityB->GetCollisionModel()->GetOneOverMass();

if(fMassA == CCollisionModel::INFINITE_MASS) APTemp = CVector3(0,0,0);
if(fMassB == CCollisionModel::INFINITE_MASS) BPTemp = CVector3(0,0,0);

float fDenominator = fMassA + fMassB + CVector3::Dot((APTemp + BPTemp), Normal);

float fImpulse = fNumerator / fDenominator;
CVector3 ImpulseV = fImpulse * Normal - ((fFriction * fImpulse) * Tangent);

{
pEntityA->GetMotion()->SetVelocity(pEntityA->GetMotion()->GetVelocity() + ImpulseV * pEntityA->GetCollisionModel()->GetOneOverMass());

CVector3 AngularMomentumChange = CVector3::Cross( VectorAP, ImpulseV);
CVector3 AngularVelocityChange = CMatrix::TransformNormal(AngularMomentumChange,pEntityA->GetCollisionModel()->GetRelativeInertiaTensorInverse());
CVector3 CurrentAngularVelocity = pEntityA->GetMotion()->GetAngularVelocity();

pEntityA->GetMotion()->SetAngularVelocity(CurrentAngularVelocity + AngularVelocityChange);
}

{
pEntityB->GetMotion()->SetVelocity(pEntityB->GetMotion()->GetVelocity() - ImpulseV * pEntityB->GetCollisionModel()->GetOneOverMass());

CVector3 AngularMomentumChange = CVector3::Cross( VectorBP, ImpulseV);
CVector3 AngularVelocityChange = CMatrix::TransformNormal(AngularMomentumChange,pEntityB->GetCollisionModel()->GetRelativeInertiaTensorInverse());
CVector3 CurrentAngularVelocity = pEntityB->GetMotion()->GetAngularVelocity();

pEntityB->GetMotion()->SetAngularVelocity(CurrentAngularVelocity - AngularVelocityChange);
}
}
}
}

Advertisement
Check out Erin Catto's GDC tutorial presentation. It is available in the following link. You're looking for the "Solver" *.ppt presentation.

GDC 2009 Presentation

It has a discussion about inequality constraints, including non penetration constraints for things like sliding.

Home page for Box2D, which has links to Erin's downloads, including the link above

Hope that helps!
Graham Rhodes Moderator, Math & Physics forum @ gamedev.net
hi, thanks, I was directed to jan bender's solution.

http://www.impulse-based.de/

http://i31www.ira.uka.de/projekte/mechanik/publications/details2003.php#description

I implemented the collision response and works very well. I perfectly understand the documentation for the first part, but still have problems with resting contacts (which he calls contacts handling). I follow this paper:

http://i31www.ira.uka.de/docs/PaperFinal.pdf


Trying to better document I met very often the solution that you mentioned (Erin Catto box2d), but I have no idea if is possible use both simultaneously.

I try to understand the technique of Erin Catto, I hope it is easier for an ignorant like me
I have realized that the problem is the order of operations during the simulation step.

I set the simulation in this way (starting with t = 0):

while (sim)
(
CollisionDetection ();
CollisionResponse ();
AdvanceSimulation (); // update Force and user's input at time t
ContactHandler (); // time t = newt;
)

For me it's correct... I hope

This topic is closed to new replies.

Advertisement