Hello,
I'm in the midst of developing a simple 3d physics engine, but have been stuck on a problem for quite a while now. I would really appreciate it if someone could have a look at it, because I'm at a loss.
The issue I'm having concerns the collision response code, which seems to fail spectacularly in some cases, generating wrong impulse magnitudes. Specifically, something with the angular part of it is wrong, since it works as expected when only dealing with the linear part.
I'm still not sure if I calculate the inertia tensor in world coordinates the right way, so that could be one possible culprit (though I've tried a few different ways). Impulses seem to be applied correctly to the bodies, so I think the error lies in the calculation of the impulse magnitude denominator.
I've checked it many times with the way the Bullet physics engine does it, with the formulas available at Wikipedia, and some other sources, to no avail.
The bodies simply keep bouncing off eachother (even though there is supposed to be no restitution) or spinning wildly on collisions.
Here is the code that deals with the collision response:
Vector3 originA = contactOrigin - bodyA.Position;
Vector3 originB = contactOrigin - bodyB.Position;
Vector3 velocityA = bodyA.Velocity + Vector3::Cross(bodyA.AngularVelocity, originA);
Vector3 velocityB = bodyB.Velocity + Vector3::Cross(bodyB.AngularVelocity, originB);
Vector3 velocity = velocityA - velocityB;
Matrix3x3 inverseWorldInertiaTensorA = Matrix3x3::Scale(bodyA.InverseInertia) * Matrix3x3::Rotate(bodyA.Orientation);
Matrix3x3 inverseWorldInertiaTensorB = Matrix3x3::Scale(bodyB.InverseInertia) * Matrix3x3::Rotate(bodyB.Orientation);
float normalVelocity = Vector3::Dot(velocity, contactNormal);
if (normalVelocity > 0.f)
{
float impulseDenominator =
bodyA.InverseMass +
bodyB.InverseMass +
Vector3::Dot(Vector3::Cross(inverseWorldInertiaTensorA * Vector3::Cross(originA, contactNormal), originA), contactNormal) +
Vector3::Dot(Vector3::Cross(inverseWorldInertiaTensorB * Vector3::Cross(originB, contactNormal), originB), contactNormal);
float j = -normalVelocity / impulseDenominator;
bodyA.Velocity += j * bodyA.InverseMass * contactNormal;
bodyB.Velocity -= j * bodyB.InverseMass * contactNormal;
bodyA.AngularVelocity += j * (inverseWorldInertiaTensorA * Vector3::Cross(originA, contactNormal));
bodyB.AngularVelocity -= j * (inverseWorldInertiaTensorB * Vector3::Cross(originB, contactNormal));
}
Thanks in advance!