I know this topic was discussed here a few times, and I red all of them, I get the idea, but for some reason I cannot implement it correctly. I'm currently working on a physical simulation which is currently aimed on spheres and their collisions with static object, for example a plane. The collision handling is impulse based and everything works ok without the friction involved. I even have the resting forces correctly implemented using Baraffs papers.
Here is how I do it:
/*
... normal impulse calculations ...
The * operator between vectors is cross product.
*/
Vector3D r1 = collision_point - rigid_body->getCenterOfMassLocation();
Vector3D col_point_vel_rel_new = rigid_body->getLinearVelocity() + (rigid_body->getAngularVelocity() * r1);
Vector3D tangent_vel = col_point_vel_rel_new - (collision_normal * col_point_vel_rel_new.dot(collision_normal));
double tangent_speed = tangent_vel.mag();
Vector3D T = -tangent_vel * (1 / tangent_speed);
Vector3D r1_cross_col_tangent = r1 * T;
matrix_tools::transform(rigid_body->getInertiaTensorInverse(), r1_cross_col_tangent, r1_cross_col_tangent);
double denominator = (1.0 / rigid_body->getMass()) + T.dot(r1_cross_col_tangent * r1);
if (denominator > EPSILON)
{
double impulse_to_reverse = tangent_speed / denominator;
double impulse_from_normal_impulse = normal_impulse_size * rigid_body->getCoefficientOfStaticFrictionWith(entity->getType());
double friction_impulse = (impulse_to_reverse < impulse_from_normal_impulse) ? impulse_to_reverse : (normal_impulse_size * rigid_body->getCoefficientOfDynamicFrictionWith(entity->getType()));
T *= friction_impulse;
rigid_body->setLinearVelocity(rigid_body->getLinearVelocity() + T * (1.0 / rigid_body->getMass()));
rigid_body->setAngularMomentum(rigid_body->getAngularMomentum() + r1 * T);
}
The idea behind this is that, if I the tangential impulse is smaller than the normal_impulse*static_friction_coeff, it means that the static friction was not overcamed, hences it equals the tangential impulse which would result in zero tangential velocity. Otherwise the dynamic friction is involved. The inspiration comes from the jiglib project and its creator to which I'm very thankfull.
But with this code, the dynamic friction does not work at all, for example if I drop a ball with no angular momentum to a horizontal plane with some horizontal velocity (after that only gravitation is working), than the impulse_to_reverse is applied to the rigid_body at the first collision, which I think is wrong. And when the second collision occurs the relative tangential velocity is zero hence, no friction is applied anymore.
I use the inertia tensor and its inverse like this:
I do not transform the inertia tensor to world coors because it's just simple scaling so in my opinion it is not necessary.
Can anyone tell me please what may be the problem? I think I'm missing something basic, and I'm not applying or calculating the impulse correctly, but I'm struggling with this a few day and I'm have no idea what to do.
Thanks.