CS 251: Lab #3

Lab 3: Interactive 3D Viewing

Project due Monday night Mar 3, 2014

The purpose of this lab is to give you the opportunity to construct the transformation matrices for the 3D viewing pipeline.


Tasks

In lab, you will be developing the View class.

  1. Create a file view.py and begin a class View (you can use any name you like, but I'll provide some short test programs that assume the class is named View).

    Within the __init__ method, create the following fields and give them the specified default values. You may want to have a reset method, called from __init__ that assigns the default values, as you may want to enable the user to reset the view at any time. Note that the view parameters provide a complete view of the data, looking normal to the X-Y plane, assuming the data is all located inside the unit cube with one corner on the origin.

    • vrp: a NumPy matrix with the default value [0.5, 0.5, 1].
    • vpn: a NumPy matrix with the default value [0, 0, -1].
    • vup: a NumPy matrix with the default value [0, 1, 0].
    • u: a NumPy matrix with the default value [-1, 0, 0].
    • extent: a list or NumPy matrix with the default value [1, 1, 1]
    • screen: a list or NumPy matrix with the default value [400, 400]
    • offset: a list or NumPy matrix with the default value [20, 20]

  2. Write a build method that that uses the current viewing parameters to return a view matrix.
    1. Generate a 4x4 identity matrix, which will be the basis for the view matrix. For example:

      vtm = numpy.identity( 4, float )

    2. Generate a translation matrix to move the VRP to the origin and then premultiply m by the translation matrix. For example:
          t1 = numpy.matrix( [[1, 0, 0, -self.vrp[0, 0]],
                              [0, 1, 0, -self.vrp[0, 1]],
                              [0, 0, 1, -self.vrp[0, 2]],
                              [0, 0, 0, 1] ] )
          
          vtm = t1 * vtm
          
    3. Calculate the view reference axes tu, tvup, tvpn.
      1. tu is the cross product (np.cross) of the vup and vpn vectors.
      2. tvup is the cross product of the vpn and tu vectors.
      3. tvpn is a copy of the vpn vector.
    4. Normalize the view axes tu, tvup, and tvpn to unit length. You probably want to write a simple normalize function to handle this. Make sure you do not include the homogeneous coordinate in the normalization process. A normalized vector has unit length, and can be computed as below. (There are more compact ways to do this using numpy.)

      Length = math.sqrt( Vx*Vx + Vy*Vy + Vz*Vz )
      Vnorm[0] = Vx / length
      Vnorm[1] = Vy / length
      Vnorm[2] = Vz / length

    5. Copy the orthonormal axes tu, tvup, and tvpn back to self.u, self.vup and self.vpn.
    6. Use the normalized view reference axes to generate the rotation matrix to align the view reference axes and then premultiply M by the rotation. For example:
          # align the axes
          r1 = numpy.matrix( [[ tu[0, 0], tu[0, 1], tu[0, 2], 0.0 ],
                              [ tvup[0, 0], tvup[0, 1], tvup[0, 2], 0.0 ],
                              [ tvpn[0, 0], tvpn[0, 1], tvpn[0, 2], 0.0 ],
                              [ 0.0, 0.0, 0.0, 1.0 ] ] );
          
          vtm = r1 * vtm
          
    7. Translate the lower left corner of the view space to the origin. Since the axes are aligned, this is just a translation by half the extent of the view volume in the X and Y view axes.

      Note that the rest of the project description will use shorthand, rather than writing out the matrices explicitly. Conceptually, the translation is represented as:

      vtm = T( 0.5*extent[0], 0.5*extent[1], 0 ) * vtm

    8. Use the extent and screen size values to scale to the screen.

      vtm = S( -screen[0] / extent[0], -screen[1] / extent[1], 1.0 / extent[2] ) * vtm

    9. Finally, translate the lower left corner to the origin and add the view offset, which gives a little buffer around the top and left edges of the window.

      vtm = T( screen[0] + offset[0], screen[1] + offset[1], 0 ) * vtm

    10. If your code is working properly, then using the default parameters you should get the matrix below.

          [[ 400.    0.    0.    20.]
           [   0. -400.    0.   420.]
           [   0.    0.   -1.    1]
           [   0.    0.    0.    1.]]
          
  3. Create a clone method for your View object that makes a duplicate View object and returns it.

When you are done with the lab exercises, you may start on the rest of the project.