Game Development Reference

In-Depth Information

Excerpt from src/contacts.cpp

// We need to work out the inertia of each object in the direction

// of the contact normal, due to angular inertia only.

for (unsigned i = 0;i<2;i++) {

if (body[i]) {

Matrix3 inverseInertiaTensor;

body[i]->getInverseInertiaTensorWorld(&inverseInertiaTensor);

// Use the same procedure as for calculating frictionless

// velocity change to work out the angular inertia.

Vector3 angularInertiaWorld =

relativeContactPosition[i] % contactNormal;

angularInertiaWorld =

inverseInertiaTensor.transform(angularInertiaWorld);

angularInertiaWorld =

angularInertiaWorld % relativeContactPosition[i];

angularInertia[i] = angularInertiaWorld * contactNormal;

// The linear component is simply the inverse mass.

linearInertia[i] = body[i]->getInverseMass();

// Keep track of the total inertia from all components.

totalInertia += linearInertia[i] + angularInertia[i];

}

}

At the end of this loop we have the four values (two for single-body collisions)

that tell us the proportion of the penetration to be resolved by each component of

eachrigidbody.Theactualamounteachobjectneedstomoveisfoundby

real inverseInertia = 1 / totalInertia;

linearMove[0] = penetration * linearInertia[0] * inverseInertia;

linearMove[1] = -penetration * linearInertia[1] * inverseInertia;

angularMove[0] = penetration * angularInertia[0] * inverseInertia;

angularMove[1] = -penetration * angularInertia[1] * inverseInertia;

The penetration value is negative for the second object in the collision for the same

reason we changed the sign of the impulse for velocity resolution: the movement is

given from the first object's point of view.

Applying the Movement

Applying the linear motion is simple. The linear move value gives the amount of

motion required, and the contact normal tells us the direction in which the movement

should take place: