Math 155B - Intro to Computer Graphics II - Winter 2005

Project #5 - Quaternions: Trackball and Orientation Interpolation

Overview:  For this assignment you will implement quaternion routines, create a program that handles "trackball" controls to rotate a teapot, and uses spherical linear interpolation to smoothly interpolation between two orientations.

Due date: Monday, February 28, midnight.  
Grading deadline:
Wednesday, March 9.

Turn in:  Save your functioning source code in a folder Project5 in your ieng9 class folder.

What to do:  You should use quaternions for all parts of the program.  (Even though, the functionality of quaternions is important mainly for the interpolation of orientation.)  Optional: You may use the VectorR4 class from the RayTracing project if you wish. 

  1. Download the program MouseRotate.exe that was demoed in class.  Your assignment is recreate the functionality of this program.

  2. Learn the functionality of the program.  There are three main functionalities: (1) Click and drag with the mouse to rotate a teapot.  (2) Use the SPACE bar to toggle between showing a single teapot and showing two teapots.   (3) Use the "i" command two interpolate the positions and orientations of the two teapots.

  3. To implement the single teapot and the trackball functionality.   Start by drawing a single teapot.  Set up a matrix that gives the orientation of the matrix.  This matrix will change with the mouse controls.   Each time the teapot is displayed, use glTranslatef()  to place the teapot in the desired location.  Then use glMultMatrixf() to multiply the model view matrix by the rotation matrix.  Do NOT use glRotatef()!!  
        Set up a callback function with glutMouseFunc to keep track of whether the left mouse button pressed and released.  When the mouse is dragged with the right button down, keep track of its motion with glutMotionFunc.     When the mouse moves from (x1,y1) to (x2,y2), rotated the object around a vector  v  which lies in the xy plane, with v perpendicular to (x2-x1,y2-y1,0).  The angle of rotation should be proportional to the magnitude of  (x2,y2)-(x1,y1).    Express this change in orientation as a quaternion.   [Pitfall: the pixels are numbered with (0,0) at the upper left corner, not the lower left corner.  Some conversion of coordinates is necessary.]
        Implementation algorithm: Maintain a quaternion for the teapot.   When a rotation occurs, multiply the quaternion from the mouse movement with the old quaternion for the teapot.  This updates the quaternion giving the orientation of the teapot.   Whenever the teapot is drawn, a 3x3 rotation matrix created from the quaternion.

  4. Implement the same functionality for two teapots at once.   When the left mouse button is clicked in the left (resp., right) side of the window, the subsequent mouse motion affects the left (resp., right) teapot.

  5. Implement the interpolation.  Position is interpolated linearly, that is, with Lerp-ing.   The orientation is implemented with spherical linear interpolation, Slerping.  Do not forget the dot product test to possibly negate one of the quaternions.

  6. Keep your code functioning on ieng9 until you are graded.  Deadline for grading, Wednesday, March 9.

There will be discussion in class with more details on the implementation.

Grading:  You will be graded on how well you implement distributed ray tracing, how well your images show the advantages of distributed ray tracing, number and difficulty of the features implemented, and the overall scene design.  Grading is based on the web page you upload, and on your discussions with the TA.

Some sample code:  Here is some sample code for handling mouse clicks and mouse motion.  Refer to the glut documentation for more information (links available on the main course web page).

In main():

// Call backs for mouse buttons and mouse movement
glutMouseFunc( MouseUpDown );
glutMotionFunc( MouseActiveMove );

The callback routines:

// glutMouseFunc was used to set this as the call back function
// for all mouse button presses and releases.

void
MouseUpDown( int button, int state, int x, int y ) {
   
if ( button!=GLUT_LEFT_BUTTON ) {
       
return;
    }
   
if ( state==GLUT_UP ) {
       
// Handle released mouse button here - TO BE WRITTEN
    }
   
else {
       
// Handle pressed mouse button here - TO BE WRITTEN
    }
}

// glutMotionFunc was used to set this as the callback function
// for "active" mouse motion.
// This is called only while the mouse is "active", i.e.,
// only while a button is pressed.
void MouseActiveMove ( int x, int y ) {
    if ( !MouseButtonDown ) {
        return;             // Should happen only if a button other than the left one was pressed.
    }
    // Handle new (x,y) position of mouse here - TO BE WRITTEN
}