Course notes for November 13


Procedurally animating a mesh over time:

In class we showed an example of the procedurally animated face mesh of my Interactive Fish java applet.

Here is the source code. Note that I define a VertexFilter. Behind the scenes this object loops through a mesh's vertices one by one, handing each one to a method filterVertex(double[] v) that allows me to modify their x,y,z values in place.

If you implement something like this in JavaScript, you will need to keep two copies of your mesh: The original unmodified mesh, and the one that gets copied from the original and then vertex-filtered at every animation frame.

When you modify the mesh, you will end up needing to change the vertex normals. To recompute vertex normals for a mesh, you can use the following algorithm:

  1. Compute the normal to the plane of all the mesh's faces. You can do this for any polygonal face with vertices v0 ... vn-1 by summing the cross products of successive edges: (vi+1mod n - vi) × (vi+2mod n - vi+1mod n)

  2. For every vertex, sum the face normals of all faces adjoining that vertex, then normalize the result. This will give you a good approximation to the normal at that vertex.

If you are feeling ambitious, you can also try implementing this sort of filter in a vertex shader. In that case, you will need to be a bit more clever about modifying vertex normals. For example (since you will have greater compute power to work with), you can do finite differences to compute the new surface normals.


Making footsteps:

In class we showed tricks for placing feet during a procedural character walk.

The trick I showed was to "freeze" time periodically for each foot position. As the character's body moves along a path over time, each foot moves alongside the body as well, but the position of the foot is periodically "frozen" while the foot is pressed against the ground and supporting the weight of the body. This is done by modifying the time argument, by adding a sawtooth function to the time value passed to that foot:

      timeL += saw(time)
      timeR += saw(time+1)
where:
      function saw(t) = { t%=2; return t<1 ? t : 2-t; }

Layered keyframe animation:

I showed a simple example of layered animation in this java applet.

One thing to take away from this example is the way it allows its users to create layered transparency for parts of movement, in a way analogous to how PhotoShop lets you do layered transparency for just some pixels of an image but not others.


Two link inverse kinematics:

I went over, in some detail, a simpler way to implement two-link inverse kinematics, given a two-link chain at the origin, with limb lengths a and b, respectively, reaching toward point C, with elbow aim hint vector D:

   c = C•C
   x = ((a2-b2)/c + 1)/2
   D -= C(C•D)/c
   y = √max(0, a2 - x2c)
   D = xC + yD/|D|
The last line requires a square root, to compute |D|. For efficiency, we can get the algorithm down to a single square root by modifying the last two lines:
   y = √max(0, a2 - x2c)/(D•D)
   D = xC + yD

General n-link inverse kinematics:

Here is a simple way to do N-Link inverse kinematics, given a chain of N+1 points P[0]....P[N], building on our two-link IK algorithm:

For each link in the chain i = 1 through N-1:
  • Move the end effector P[N] fractionally toward the goal.

  • Compute a new position for P[i] by solving for (P[i-1],P[i],P[N]) as a two-link IK chain.

  • Transform all points P[i+1] through P[N-1] to match the translation+rotation defined by the new locations of P[i] and P[N].
We can vary the compliance at each joint by adjusting the fractional amount that we move toward the goal at each step of the loop.

Homework:

For homework due by class on Wednesday November 20, feel free to pick and choose from among the above directions in this week's homework. This is your chance to explore ideas in keyframe animation, character animation, procedural animation, creature animation, and related topics.