CS91 Computer Animation: Lab 6

In which, we slerp towards greatness

In this assignment, you will implement transformations and forward kinematics. The features you implement in this assignment will lay the groundwork for working with motion capture and character animation. Specifically, after completing this assignment, you will be able to load a BVH motion capture file and play back the animation on a character.

Step 1: Get the source


The forward kinematics assignment has been added to your team's AnimationFramework reporitoy. To get the source, run
> git pull
It appears that Swarthmore github may be down during our lab today. To work around this problem, I've posted the assignment here. Download it to your AnimationFramework directory. Then,
> gunzip fk-assignment.tar.gz
> tar xvf fk-assignment.tar
The tar file will replace several files in your repository which you can check in later.

Step 2: Compile and run


Same as before, you should compile all source in a build subdirectory. The compiled applications will be in /bin as with the rotation assignment. Additionally, the asisgnment includes 'solution' versions of the assignment libraries which you can use to build a 'solution' version of the demo.
> rm -rf build
> mkdir build
> cd build
> make
> ../bin/FKViewer
> ../bin/FKViewer-Soln

User interface overview


The basecode includes a simple interface and 3D viewer for loading and playing BVH files. See above for a screenshot. By default, we will load a character and several example BVH files.

The camera can be controled with the mouse:

The player control panel on the top left can be used to load and play files. The panel at the bottom left can be used to load different BVH files.

Character animation implementation overview

The basecode includes a framework for organizing transforms into a hierachy and animating them using curves. The core data structure for supporting this functionality is the AnimatableTransform, which maintains pointers to parent and child transforms. The AnimatableTransform primarily contains a Transform which keeps track of its position relative to its parent. It also stores its transform relative to the world coordinate system for convenience.

AnimatableTransforms are arranged into a hierachy with the AnimatableHierarchy class. The root of the AnimatableHierarchy is positioned relative to the world coordinate system whereas all other joints are positioned relative to its parent in the hierachy. Although the AnimatableHierachy could be used to animate any group of transforms, for character animation it is natural to think of the AnimatbleHierachy as an actor and its corresponding AnimatableTransforms as joints.

To support BVH files, we populate an AnimatableHierarchy using the skeleton information from the file. BVH files are located at /AnimationToolkit/motions. A sample file is here.

We then initialize curves based on the BVH file's motion data and store the result in BVHController. In the case of BVH, where joint limbs do not change length, the bvh controller only manages a single translational curve for the root joint. However, the BVHController does manage rotational curves for both the root and every joint. During playback, the BVHController queries the animation curves and then updates the transformations accordingly.

To summarize, the class hiererachy used for this asignment is the following:

BVHController
    AnimatableHierarchy (aka Actor)
    ASplineVec3 for the root joint position
    ASplineQuaternion for each AnimatableTransform (aka Joint).

Assignment Due March 27

Quaternion Slerp

Quaternion splines. The basecode includes a class ASplineQuaternion whose interface mirrors the spline you worked with for vectors in the previous assignment.
  1. (5 points) Implement Quaternion::Slerp() in aRotation.cpp

    Input The startpoint quaternion q0

    Input The endpoint quaternion q1

    Input The normalized time t (range 0,1)

    Output The interpolated quaternion

Forward kinematics

  1. (20 points) Transformations. Complete the implementation of the transformation class. This class stores its rotation \(R_j^i\) and translation \(d_j^i\). You may implement these functions either via homogeneous matrices or direct manipulation of \(R\) and \(d\).
    1. (5 points) Implement Transform::Inverse()

      Output Transform objects representing the inverse of this object. Compute the inverse rotation and inverse displacement and pass the result to a new Transform.

    2. (5 points) Implement Transform::TransformPoint()

      Input 3D position to be transformed by this transform

      Output Transformed position

    3. (5 points) Implement Transform::TransformVector()

      Input 3D vector to be transformed by this transform

      Output Transformed vector

    4. (5 points) Implement operator* () for the Transform class. Computes t1 * t2

      InputThe first transform t1 in the operation

      InputThe second transform t2

      OutputThe resulting transform t1 * t2

  2. (10 points) Forward kinematics is the process of computing each transform's local2global matrix. When joint rotations change (e.g. when \(R_j^i\) changes), we need to update the transformation matrices \(F_j^0\). This is achieved by starting at the root and recursively walking the kinematic chain to each end effector, e.g.
    updateTransforms()
    \(\quad R_j^0 = R_{i}^{0} R_j^i\)
       foreach child in mChildren
          child->updateTransforms()
    
    Note that because we start at the root, we can be sure the parent's transformation matrix \(R_i^0\) has already been computed!
    1. (5 points) Implement AnimatableHierarchy::updateTransforms(). Initiate the walk by calling updateTransformation() on the root joint.
    2. (5 points) Implement AnimatableTransform::updateTransformation(). Compute mLocal2Global and then call updateTransformation() on the joint's children.
  • Updating the character each frame.
    1. The character is updated in BVHController::update(double time). This function iterates through each joint of the skeleton and samples the motion curves in BVHController to se the pose for the given time. Once all the local transforms have been updated, we call perform forward kinematics by calling mSkeleton.updateTransforms(), e.g.
      for each joint in mSkeleton
          if the joint is the root
              pos = mRootMotion.getValue(time)
              set joint's local translation to pos
          quaternion = mMotion[jointID].getValue(time)
          set joint's local rotation to quaternion.GetRotation() // set matrix
      
      update the transforms in the skeleton
      

      In BVHController (aBVHController.h), you will find splines for the root position and for the joint rotations.

      In the basecode, joints are implemented with the class AnimatableTransform and the skeleton is implemented with the class AnimatableHierarchy (in aAnimatables.h).

    Extra challenge

  • Create your own unique character. Edit CharacterDrawer.cpp to create a unique character for your team.
  • Quaternion cubic interpolation using squad. In class, we discussed Shoemaker's approach for smoothly interpolating a sequence of quaternions. An alternative approach popular in games is to use a technique called squad. Try implementing squad in the base code.
    1. Implement Quaternion::Squad()
    2. Implement Quaternion::Intermediate()
    3. Compare the animation of the teapot using linear versus cubic interpolation. What are the differences? (Note: The keys used for the demo are hard-coded in the RotationViewer constructor.)
    You can then test your results using the RotationDemo from your first assignment. Choose the Teapot option from the drop down list.

    "Rotate, teapot, ROTATE!"
  • Submission Guidelines (5 points)

    Submitting your assignment

    Students should submit their code along with a README and videos. The README can be very brief, consisting of Videos should show results, including any extra challenges. Videos will be collected together and shown during class presentations. Please submit a mp4 of length no more than 60 seconds. For example

    About checkins

    You will be asked to briefly checkin (less than 1 minute) about your homework assignment. This is not intended to much work. Please don't prepare slides or a voice over for your video. None of these are necessary! Some ideas of what you might like to talk about: