Game Development Reference
In-Depth Information
As with Jakobsen, we solve the constraints directly by projecting the vertices
to positions that satisfy the constraints. To satisfy the constraint, the distance
between the vertices must be the same as it was initially ( currentLength =
restLength ).
So we compare the current length to the initial length. We find the delta and
divide it by two. Each vertex then receives a portion of this delta in the direction
that would bring the vertices closer together or further apart depending on if the
constraint is stretched or compressed. Because the results of the last iteration are
fed into the current iteration, the mesh evolves into a smooth shape. Listing 13.4
shows this is in pseudocode.
float pushStrength = 0.1;
float pullStrength = 0.5;
int iterations = 10;
for (eachIteration)
{ for (eachConstraint)
{
//Calculate vector from vertex A to vertex B
vector3d AB;
AB = constraint.vertexA.pos
constraint.vertexB.pos;
//Calculate delta and divide in half
delta = ( constraint.restLength
AB.length() )
0.5;
//Factor in push/pull strength parameters
if (delta > 0)
delta = pushStrength;
else
delta = pullStrength;
//Add the deltas for point A and point B
AB.normalize();
constraint.vertexA.pos += AB delta;
constraint.vertexB.pos
=AB
delta;
}
}
Listing 13.4. This is the Deform() function of a relaxation deformer. We are solving
position constraints by projecting positions for each constraint individually. Doing several
iterations smooths out the errors and approaches a stable solution.
You will notice two additional parameters, pushStrength and
pullStrength , which describe how much of the delta to correct with each
iteration. As can be seen, the pushStrength parameter describes how much to
correct deformations that involve compression and pullStrength is applied