Game Development Reference
In-Depth Information
After one update of the rigid bodies and before collision resolution is performed,
the object drops into the plane slightly. This is shown in the second part of the figure.
Because the plane contact is in a different direction from the movement of the object,
the interpenetration resolution moves the block out to the position as shown in the
third part of the figure. Over time, and despite high friction, the block will slowly drift
down the slope.
This is a similar problem to the one we saw at the end of chapter 15. In that
case the drifting was caused by the interaction between different contacts. In this case
there is no interaction: the same thing occurs for objects with only one contact. It is
therefore much easier to resolve.
The solution lies in the calculation of the relative velocity of the contact. We'd like
to remove any velocity that has built up due to forces in the contact plane. This would
allow the object to move into the slope in the direction of the contact normal, but not
along it.
To accomplish this we add a calculation of the velocity due to acceleration to the
calculateLocalVelocity method:
Excerpt from include/cyclone/precision.h
Vector3 Contact::calculateLocalVelocity(unsigned bodyIndex, real duration)
{
RigidBody *thisBody = body[bodyIndex];
// Work out the velocity of the contact point.
Vector3 velocity =
thisBody->getRotation() % relativeContactPosition[bodyIndex];
velocity += thisBody->getVelocity();
// Turn the velocity into contact coordinates.
Vector3 contactVelocity = contactToWorld.transformTranspose(velocity);
// Calculate the amount of velocity that is due to forces without
// reactions.
Vector3 accVelocity = thisBody->getLastFrameAcceleration() * duration;
// Calculate the velocity in contact coordinates.
accVelocity = contactToWorld.transformTranspose(accVelocity);
// We ignore any component of acceleration in the contact normal
// direction; we are only interested in planar acceleration.
accVelocity.x = 0;
// Add the planar velocities - if there's enough friction they will
// be removed during velocity resolution
contactVelocity += accVelocity;