|
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
-
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.
-
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.
-
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).
-
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).
-
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).
-
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.
-
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.
|