Assignment 3: Displaying Motion Capture Data

This project required us to display motion capture data using a variety of methods. The assignment was given in five parts. There was also an obligatory bonus part, of which there were several to choose from (although I didn't do one).
Below is a description of my solution to the assignment.

Part 1: Reading the data

My program can read both .BVA and .BVH file formats, designed by BioVision. The .BVA format is an older one that lacks a hierarchy. The .BVH format includes support for a general hierarchy, describing the skeleton as a collection of joints, each placed by a translation (offset) and a 3D rotation. Rotations are assumed to be rotations within a local coordinate frame.

I make no assumptions about the structure of the hierarchy, however, I do assume that the rotation order (even if specified) is Z-X-Y. Although it would be easily to handle the general case, I saw no examples where the rotation order was different.

Part 2: Displaying the skeleton

I displayed the motion data using an OpenGL window embedded in a Microsoft Foundation Class (MFC) window frame. The MFC frame provides an expandable/collapsable tree depicting the skeleton hierarchy. It also provides a nice interface with controls for manipulating the motion sequence. In particular, the user can advance/retreat frame-by-frame or continuously play the motion sequence forward or backward. The user can also switch between internal rotation representations (EAs/quaternions). A split screen option will simultaneously display two skeletons: one using EAs and the other using quaternions for its internal rotations. Finally, the user can choose start and end frames for interpolation and lock the motion sequence between the two frames.

The skeleton is displayed as a collection of ellipses (scaled spheres). A floor is provided, onto which a drop shadow is projected for effect. A simple light model is employed to enhance the results.

Part 3: Computing end effectors

My method for computing the end effector positions was to perform all transformations in global coordinates. That is, I first translated an end effector to the global origin, translated it according to its offset, rotated it according to the rotation specified for its local coordinate frame, and then translated it to its new position relative to its parent. This simple method works because the rotations given in the file format are local rotations. (See the code below for a more detailed explanation.)

All of this work was done in advance for all frames in the motion sequence. This caching of the end effectors allowed the playback to retain its speed. The end effectors are displayed using cubes. The effector trail is displayed only over the last fifteen frames so as not to clutter the display. This has the pleasing effect of looking like a (blocky) smoke trail.

Part 4: Internal rotation representation

The internal representations are typically indistinguishable. The differences are usually only seen when interpolation is involved. However, some differences appear when the joints are displayed as 3D axes. Occasionally the axes will twist around unnaturally when Euler angles are the current representation.

Part 5: Interpolating motion

Using the MFC interface, the user can choose two frames between which the skeleton's movements will be interpolated. When chosen far enough apart, the movement will look very different than that given by the original frame data. Even more interesting, the user can simulataneously view interpolations given by Euler Angles (linear interpolation) and quaternions (spherical linear interpolation). The differences are often striking.

Implementation notes

I used as the base of my solution source code for the "Dagger" application written by Jeff Lander. This code can be found at http://www.darwin3d.com/gamedev.htm. Jeff's code handled the .BVA format and (or so it claimed) the Acclaim format, which I did not attempt to implement. I integrated quaternions and slerp from "Slash," another of Jeff's applications found at the same location.

The Dagger code provided the MFC base and some of the OpenGL routines. The code that I added can be found by searching for "KEITH:" in the source files. Here's a quick of the functions I added:

Links

Executable instructions

Choose the "Load Anim" option from the Animation menu (shown below) to load any .BVH file. All other instructions are shown below.