Here is a sample rendering of how test.skel should look:

This is from a more or less straight view with the x-axis pointing to the right, y-axis pointing up, and z-axis coming out of the screen towards the viewer. Also notice that by default, the character is aligned with the viewer, therefore looking ahead, and facing away from us.

Note that the right knee is bent. This is because the right knee has values specified in the 'pose' field within the .skel file. Also note that these values are being clamped to within the DOF limits for the knee. The knee is able to rotate about the x-axis from –2 radians to 0 radians, but y and z are constrained to be locked at 0, effectively deactivating those DOFs, and making the knee a 1-DOF hinge joint. This is all controlled in the .skel file by specifying the DOF limits.

Here is a sample rendering of how wasp.skel should look:

Note that this example renders solid boxes with shading, this is not required.

Programming Project One: Skeleton

Due Wednesday, Jan 23rd, 6pm

Getting Started

You will probably find it helpful to begin with the Project 0 basecode that we have provided. In order to use the basecode, you must first set up an OpenGL project in an IDE such as Visual Studio. The following links are quite helpful in doing this:

Although Visual Studio is by far the most popular choice for an IDE (and that most widely supported by our lab) you are free to use any IDE you wish. A guide for Apple Xcode will be posted here shortly.


Write a program that loads a character skeleton from a .skel file (described below) and display it in 3D. All joints in the skeleton will be 3-DOF rotational joints (ball-and-socket joints) that rotate in x first, then y, then z. The program should perform the forward kinematics computations to generate world space matrices for the joints.

The program should be able to load any skel file given to it, and should accept a .skel file name as a command line argument. If no file name is given, it should default to 'test.skel'.

You can use the sample code in project0 to start with if you want. Either way, you must do the matrix computations in C++ code rather than through OpenGL. The only OpenGL matrix routine you should need to draw the skeleton is glLoadMatrixf(). In other words, do not use glPushMatrix(), glPopMatrix(), glRotatef(), glTranslatef(), or similar commands for rendering the skeleton. You can use the Matrix34 class provided in the sample code.

To render the actual 'bones' of the skeleton, you can use the drawWireBox() command provided in core.cpp or you can use another method of your choice.

To make loading the data file easier, a class called Tokenizer is provided in the sample code which opens a file and reads individual strings, ints or floats. Also, please see the lecture notes from Lecture 2: Skeletons for more info.

If you want to add extra features, feel free. Some possible ideas include:

.skel File Format Description

The .skel file is a simple indented hierarchy of joints. Each joint also lists some relevant data about its configuration. For a sample .skel file, see test.skel. For a more complex skeleton, see dragon.skel, or wasp.skel. The .skel data file has 8 keyword tokens which are then followed by data (usually floats). These specify properties of a particular joint. Not all joints will specify all properties, so reasonable default values should be used. Here is a list of the keywords and their associated data:

offset      x y z      (joint offset vector)
boxmin      x y z      (min corner of box to draw)
boxmax      x y z      (max corner of box to draw)
rotxlimit      min max      (x rotation DOF limits)
rotylimit      min max      (y rotation DOF limits)
rotzlimit      min max      (z rotation DOF limits)
pose      x y z      (values to pose DOFs)
balljoint      name { }      (child joint)

The 'offset' is the constant positional offset to add to the local joint transformation. It represents the location of a joint's pivot point described relative to the parent joint's space. This will almost always be specified for a joint, but if not, it should default to (0,0,0).

The 'boxmin' and 'boxmax' parameters describe the min and max corners of a box representing the bone to render for the particular joint. If these are not specified for a joint, they should still have a reasonable default, say (-0.1,-0.1,-0.1) and (0.1,0.1,0.1).

The 'rotlimit' tokens describe the rotational joint DOF limits. Note that all angles are in radians. These should default to an essentially unlimited state if they are not specified in the file (i.e., -100000 to 100000 would be fine).

The 'pose' token specifies values to pose the DOFs at. Normally, data like this would not be needed in a skeleton file, as the skeleton is usually posed by a higher level animation system. For the purposes of this project, however, we will include optional pose data in the .skel file. By default, these should be 0. If the pose specifies values outside of the range of the DOF limits, then it should get properly clamped before displaying. Again, remember that these values are in radians.

The 'balljoint' token specifies a child balljoint which will have its own data and possibly its own children. There should not be any limit to the number of children allowed. Every balljoint has a name in the file, but you don't have to do anything with this string if you don't want to. Optionally, you could draw bone names as labels in the 3D view though...

In theory, one could extend this file format to include other joint types (hingejoint, prismaticjoint, freejoint, etc.). Each one of these joint types could have additional data tokens if needed.


This project is worth 15 points.

Extra Credit

  1. Design your own .skel file with at least 10 joints that uses joint limits, different sized boxes, and a non-trivial tree (i.e., no snakes!), then pose it.
  2. Add a simple GUI to the program (try glui, tcl...?) that lists all of the DOFs by name (i.e. "knee_r X") and allows the user to adjust the value within the DOF limits. Display the active DOF name and value on the screen.