COMP 559 - Winter 2011 - Assignment 4
Physically Based Character Simulation

Due noon Friday March 18

Getting Started

In this assignment, you will create an animation of a human figure using motion capture and physically based simulation.

Download the provided code from WebCT and dump it into a new java project. The code depends on the mintools jar you used in the previous assignments, but it also now depends on ode4j, which is a java implementation of the Open Dynamics Engine. A jared version of the ode4j is included with the provided code for this assignment. Two motion capture files are included in the provided code zip file, but you may want to try out others from here. The CMU motion capture database also has a large database of motion capture motions, for which bvh conversions of this data are available at cgspeed. Here follows a short description of the provided files.

  • OdeMocapApp contains the main method, creates the 3D viewer, and defines the keyboard controls attached to the 3D canvas. It loads a motion capture file and sets up the ODE simulation.
  • BVHData loads the skeleton and joint angle data from a bvh file. The simple parser also creates a hierarchy of SkeletonNode objects. The setSkeletonPose method sets the joint angles and root translation for the loaded skeleton. The motionData is private, but you should not need to do this for the objectives below.
  • SkeletonNode defines a joint which can rotate about a set of axes. The object has a parent SkeletonNode (null if it is the root), and a list of children). The rotation axes of the skeleton node are located at a fixed offset from the parent frame, and the order of rotation is specified in a channel list (as loaded by the BVHData). While all skeleton nodes joints can also have a translation component, this is only used for the root of the character (usually named the hips). The init method of this class estimates the size of different segments of the body to display simple 3D geometry between the joint and its parent. Finally, note the computeTransforms method which will compute for each node (i.e., for each joint) the transformation from the joint frame to the parent frame, and the transformation from the joint frame to the world frame. You will want to look closely at this method to see how the hierarchy of transforms is computed and stored.
  • ODESkeleton is the code that adapts a SkeletonNode hierarchy to the Open Dynamics Engine. This is separate from the SkeletonNode class probably more for historical reasons as this assignment was adapted from one that focused on motion capture alone. An ODESkeleton must be created with a unique SkeletonNode hierarchy (this is done for you). You need to complete methods in this class so that the ODE rigid bodies can have their position and velocity set, and so that joint torques can be applied between adjacent bodies in the hierarchy (see TODO comments, and objectives below).
  • BoxBodyODE is a small helper class that holds information about the ODE representation of link corresponding to a SkeletonNode.
  • ODESimulation manages the various elements of a simulated scene. It deals with stepping the simulation, the walls and floor, collision detection, and contact.

It is suggested that you read through all the provided code, and note in particular the areas that are marked TODO.

Steps and Objectives

  1. Set ODESkeleton poses (3 marks)

    Write code to set the pose of the ODE skeleton simulation from the motion capture skeleton. You will need to call setPosition on the odeBody stored with each SkeletonNode. When "follow mocap" is selected in the control panel, the OdeMocapApp will call setCurrentPose on each display call, so you can verify that your solution is correct by verifying that the ODE skeleton (drawn with ellipsoids) tracks the wire frame boxes of the SkeletonNodes as they display different frames from the motion capture.
  2. Set ODESkeleton velocities (3 marks)

    Write code to set the velocity of the ODE skeleton bodies to match the velocity of the motion capture. You should verify that you are setting the velocity correctly by turning off "follow mocap" and stepping the system to check that the bodies roughly follow the trajectory of the motion capture. You will want to disable collision detection to do this test, and you may likewise want to disable gravity.
  3. Rag-doll simulation (1 mark)

    Given that you can set the initial position and velocity of all the bodies in the skeleton, you can now create a rag doll simulation. Uncomment the createSkeletonJoints call in OdeMocapApp to create joint constraints in the simulation, and test that your simulation still works. Note that this is not much of an objective, but you could note that it might be useful to create hinge joint constraints for some joints, and likewise set joint limits (see optional objectives below).
  4. Joint springs (1 mark)

    To improve the rag doll simulation, we can have our simulated character continue to try to produce the movement recorded in the motion capture. Write code in ODESkeleton.applyJointTorques to compare the rotation of a node with respect to its parent in the motion capture, to the rotation of an odeBody with respect to its parent in your simulation. Apply a torque proportional to the difference between these two bends.

    Note that you might find it easier to test just an individual joint spring. You can do this by modifying the joint constraint creation code to only create the one joint you want to test, and likewise only apply torques for that one joint. Use a comparison with the node.name to select the joint in question.

    The default spring stiffness is probably reasonable, but you should test with lower and higher stiffness to see what is possible. Note, likewise, that it would be very reasonable to set each joint's stiffness differently and likewise to modulate that stiffness over time based on the task (this is not an objective).

  5. Velocity damping at joints (1 mark)

    You should also compute and apply a damping force based on the relative velocity of the bodies in the simulation (note that this could instead be a damping force that compares the simulated relative velocity to the desired relative velocity, but this is not necessary for this assignment).

    The default damping coefficient for the joints should be suitable, but you may also find it to be a bit high. Consider experimenting with different values, and again, note that it would be reasonable to set a different coefficient for each joint and to vary it over time (this is not an objective).

  6. Make a movie (1 mark)

    Record a movie that shows that you've successfully met the objectives of this assignment. You are encouraged to make your video informative, amusing, and aesthetically pleasing.

    Optionally, you can make a movie using a high quality rendering. Save a sequence of poses (i.e., mocap frames) to a file, and then use Blender to create an animation high quality lighting (e.g., ambient occlusion). You will need to write some code to set the joint angles in the SkeletonNodes to match your simulation in order to use the existing bvh export code (some code will be posted to the WebCT forum should anyone ask). Using blender, you can follow these instructions to create your movie.

  7. OPTIONAL Extensions

    You might optionally like to think about the following issues.

    • Dynamically create obstacles

      Currently, the ODESimulation rather naively sets up two obstacles with initial conditions so that they will collide with the character. Consider replacing this code with a mechanism for letting the user throw boxes and balls at the character (for instance, when they press a key on the keyboard). Consider using a reasonable set of random values for the initial positions and velocities, or let the user specify parameters in some way (size, mass, velocity, position, colour, etc.).
    • Joint limits

      ODE supports limits for some joint types. Can you add reasonable limits to the virtual simulated characters?
    • Mixing with motion capture

      Can you blend the kinematic motion and simulation to get the best of both worlds?
    • Multiple responsive characters

      Can you simulate a football tackle? Characters would need some additional control to be realistic, for instance, closing arms to try to catch another character, or reaching out to brace for a fall.
    • Jumping between simulation and motion capture

      Motion graphs are a powerful technique of reusing motion capture. The idea is to allow temporally distant pieces of captured motion to be played one after another provided the pose and velocity matches at the cut. Using a physics based simulation is great for producing a reaction to some external force, but it is still useful to jump back into motion capture. Consider trying to find a way to control your character so that it can seamlessly return to the motion capture, perhaps through a combination of control, and searching for a motion capture clip appropriate for the given disturbance.
    • Maintaining balance

      Your simulated character will tend to fall down when it is using joint torques to try to produce the captured motion. What could you do to make the character stay balanced? Note that this has been an active area of research!
    • Interesting static obstacles

      Stunts such as falling down stairs can be dangerous for real people to perform. Consider using your simulation as a virtual stuntman. Can you get your character to land on its feet?
    • Other capabilities

      There are a vast number of other capabilities it would be nice to give a simulated character. What do you think is important or interesting?

References

Additional Reading and Links

Finished?

Great! Submit your source code and xvid encoded videos as a zip file via webCT. Include a readme.txt file with any specific comments. Your readme should provide a list of people with which you discussed the assignment, or state that you did discuss the assignment with anyone.