Banner
Design of Skin and Bone Animation
Posted Saturday, June 23, 2001
The following are some design notes on our skin and bones animation system. If you are a developer and this information is of use to you then feel free to use and abuse it in any way. The Magicosm project is all about community and we share this information freely.

  1. The system completely separates the animation data from the things being animated. An Animation is a collection of JointAnimations. Animations have a bunch of info including the time in milliseconds that it should take to run its course, whether they cycle, etc.
  2. Each JointAnimation has a name which corresponds to the bone it is allowed to influence. Its stores position and rotation animation tracks which are keyframes for animation.
  3. A Skeleton is what is being animated. It has a set of bones which form the hierarchy of bones which make up the skeleton. We will be using the standard character studio Biped, but any arbitrary bone hierarchy is allowed.
  4. Skeletons also store the set of active animations, queued animations and dorment animations.
  5. When an Animation is attached to a skeleton, a LivingAnimation is constructed and put in the active list. A LivingAnimation has a reference to an Animation plus data related to this particular instance like start time, elapsed time and the current fractional keyframe. It also establishes a list of LivingJointAnimations.
  6. LivingJointAnimations have a reference one to one with a JointAnimation, plus they keep some speed up points into the frames for faster lookup.
  7. When the LivingAnimation is attached to the skeleton it is mapped to the bones. It create LivingJointAnimations only for this JointAnimations which have a matching name in the bone hierarchy. This allows for partial body animations to be applied.
  8. As each LivingJointAnimation is constructed it registers itself with the bone it is modifying. Each bone can have as many animations effecting it as we want, with an alpha controlling the weight of one JointAnimation to another. Mostly this will be for animation transitions.
  9. When a skeleton is asked to animate for a frame, it takes the time and looks through its active LivingAnimations and tells them to update themselves for this frame. This in turn updates the rotation and position of all the LivingJointAnimations.
  10. The bones are then processed and each bone looks at its registered LivingJointAnimations and adjusts its internal matrices for the bone.
  11. Skins are collections of Sinews, Vertex and Triangles. Each Sinew forms a bond between a vertex and a bone with a weight.
  12. After the skeleton has been updated, all the Vertex objects are updated. This causes all the Sinews to calcuate the position of the vertex as if they were the only bone influencing the vertex. These positions are then weighted and combined to produce a new vertex position.
  13. Then all the triangles are processed and their normals are adjusted using the same technique used for calculating vertex.
  14. Skins will be implemented as SingleSkin and MultiSkin. They inherit all the capabilities of skins, but they take the triangles and manage the display. SingleSkin will be the first and simpler method and used for a lot of animals and early avatars. MultiSkins will be used by our advanced texturing.

We are coming in at 530 nanoseconds to compute a full skin and bones frame on a 700 MHz PC. My C++/OpenGL friend was staggered to hear that. Seems that Java still maintains a reputation for being slow, and much slower than C++. I wonder how long until the world wakes up and realizes how much Java has evolved. I was able to animate one character every frame at 180 frames per second with a medium filled scene. Throttling the char animation down to an artificial 20 fps (which looks great btw) the frame rate on the card went up to 310 fps. This is in the test viewer, not in our full app. Our full app runs about 60 fps on a GeforceII right now, mostly due to a bug in java3d that causes it not to use display lists for multi-textured geometry.

We plan all sorts of things to handle the load of multiple characters/animals/monsters in the scene at one time. Some of these techniques include having several layers of animating queues, with different promotion policies depending on number of characters in view and thier relative distance from the view. So in a crowded scene, the characters nearest to you might be animated more frequently than ones further away. But if there are only a few then we will speed them up, even though they might be a bit further away.

The other thing we can do and should do is that as we design our skins we have lower polygon version. This would be true of the whole naked figure as well as the item meshes. Basically just two versions.

Dilvish