I'm trying to implement a sequential impulse solver (using bias velocity) along with contact caching in order to get a stack of boxes stable. I'm pretty sure that the warm starting it is being done correctly and I'm getting good results, but I need to know the correct way of dealing with friction impulses.
I've implemented the btPersistentManifold from Bullet™ (along with GJK and EPA but these aren't from Bullet™) and analysing the results it is pretty close to get a stack of boxes stable with all cached contact points, but since the friction looks like it is being applied incorrectly (and very extreme making the rigid bodies fall of the plane depending of the position and rotation of the OBB) I think that that is what adding jittering.
I'm correctly clamping the accumulated friction impulse each iteration.
When a new contact is found (before can be replaced), that's what I do:
cContact.vTangent[0] = vDV - (cContact.vNormalB * vDV.Dot(cContact.vNormalB));
float fTanLen = cContact.vTangent[0].LenSq();
if ( fTanLen > ML_ZERO ) {
cContact.vTangent[0] /= CMathLib::Sqrt(fTanLen);
cContact.vTangent[1] = cContact.vTangent[0].Cross(cContact.vNormalB);
cContact.vTangent[1].Normalize();
}
else {
CContactManifold::ComputeBasis(cContact.vNormalB, cContact.vTangent[0], cContact.vTangent[1]);
}
static void ComputeBasis(const CVector3& _vA, CVector3& _vB, CVector3& _vC) {
if (CMathLib::Abs(_vA.x) >= 0.57735f) {
_vB = CVector3(_vA.y, -_vA.x, ML_ZERO);
}
else {
_vB = CVector3(ML_ZERO, _vA.z, -_vA.y);
}
_vB.Normalize();
_vC = _vA.Cross(_vB);
}
Then if a contact can be replaced, I project the old impulse on the new tangents and use that for warm starting:
inline void ReplaceContact(const CM_CONTACT& _NewContact, unsigned int _ui32Index) {
CM_CONTACT& cContact = m_cContacts[_ui32Index];
unsigned long long ui64Time = cContact.ui64Time;
float fPN = cContact.fPN;
CVector3 vLambdaT = cContact.vTangent[0] * cContact.fPT[0] + cContact.vTangent[1] * cContact.fPT[1]; //Old
cContact = _NewContact;
cContact.ui64Time = ui64Time;
cContact.fPN = fPN;
cContact.fPT[0] = vLambdaT.Dot(_NewContact.vTangent[0]);
cContact.fPT[1] = vLambdaT.Dot(_NewContact.vTangent[1]);
}
When debugging the contact basis, looks like everything is correct:

I'm running at 30HZ with only 5 iterations. When changing to 60HZ and increasing the iterations to ~10, things get more stable but a stack of 10 boxes faces jittering and still infinetely sliding on a plane.
Someone have any idea of what should I take into consideration when solving friction constraints? Have someone faced with this problem?