Game Development Reference
// If the velocity is very slow, limit the restitution.
real thisRestitution = restitution;
if (real_abs(contactVelocity.x) < velocityLimit)
thisRestitution = (real)0.0f;
// Combine the bounce velocity with the removed
// acceleration velocity.
-thisRestitution * (contactVelocity.x - velocityFromAcc);
Once again, both cases must be able to take their adjustment from either the first
or second object of the contact that has been adjusted.
The complete code listing is very similar to that shown for penetration, so I won't
include it here. You can find it in the src/contacts.cpp file on the CD.
A LTERNATIVE U PDATE A LGORITHMS
I must confess I have a natural distaste for algorithms that repeatedly loop over arrays
finding maxima, or that search through an array finding matching objects to adjust.
Over years of programming I've learned to suspect that there is probably a much
better way. Both these red flags crop up in the penetration and velocity resolution
I spent a good deal of time preparing this topic, implementing alternatives and
variations that would improve the theoretical speed of the algorithm. One such alter-
native that provides good performance is to keep a sorted list of the contacts. By way
of illustration I'll describe it here.
The list of contacts is built as a doubly linked list, by adding two pointers in the
contact data structure: pointing to the next and previous contacts in the list.
Taking the penetration resolution algorithm as an example (although exactly the
same thing happens for velocity resolution), we initially sort all the contacts into the
doubly linked list in order of decreasing penetration.
At each iteration of the algorithm, the first contact in the list is chosen and re-
solved (it will have the greatest penetration). Now we need to update the penetrations
of contacts that might have been affected. To do this I use another pair of linked lists
in the contact data structure. These linked lists contain all the contacts that involve
one particular object. There must be two such lists because each contact has up to two
objects involved. To hold the start of these lists, I add a pointer in the RigidBody class.
This means that, if we know which rigid bodies were adjusted, we can simply walk
through their list of contacts to perform the update. In (highly abbreviated) code it
looks something like this: