Homework due Thursday, February 16, 2012

In this assignment you are going to implement your basic building block routines for doing three dimensional linear transformations, which can be described by 4×4 matrices. You'll want to package your matrices up into a Java class that contains various access routines. Here is an example of what some of your code for this class might look like:

   public class Matrix {
      double data[][] = new double[4][4];

      public void set(int i, int j, double value) { data[i][j] = value; } // SET ONE VALUE
      public double get(int i, int j) { return data[i][j]; }              // GET ONE VALUE

      ...
   }

You can use the set and get routines in various ways. For example, you can copy one matrix into another by implementing a copy method that calls the other matrix's get() method:

   public void copy(Matrix src) {
      for (int row = 0 ; row < 4 ; row++)
      for (int col = 0 ; col < 4 ; col++)
	 data[row][col] = src.get(row,col));
   }

In the notes on the main course page I summarize our class discussion about the forms of the identity, translation, rotation, and scale matrices. Following these notes you can create methods that build the data for primitive matrices:

    createIdentityData(double dst[][]);
    createTranslationData(double x, double y, double z, double dst[][]);
    createXRotationData(double theta, double dst[][]);
    createYRotationData(double theta, double dst[][]);
    createZRotationData(double theta, double dst[][]);
    createScaleData(double x, double y, double z, double dst[][]);

You will be using these primitive matrices to build the methods that translate, rotate and scale a matrix.

Your method within class Matrix to build a translation matrix might be implemented something like this:

public class Matrix {

...

   public void createTranslationData(double a, double b, double c, double dst[][]) {
      createIdentityData(dst);
      dst[0][3] = a;
      dst[1][3] = b;
      dst[2][3] = c;
   }
}
Given that you have implemented methods to create identity, translation, rotation, and scale matrix primitives, you need to be able to transform one matrix by another, so that you can start combining transformations.

To do this, you'll need to implement a method to do matrix multiplication. As we discussed in class, you do this by taking the inner product between the rows of the first matrix and the columns of the second matrix, where the inner product (or dot product) of two vectors is the sum of the products of their elements:

   dotProduct = 0;
   for (int i = 0 ; i < V1.length ; i++)
      dotProduct += V1[i] * V2[i];

For example, you might implement matrix multiplication by:

   public void multiply(Matrix src) {
      multiply(src.getData());
   }

   double temp[][] = new double[4][4];

   void multiply(double src[][]) {

      // FIRST COPY MY ORIGINAL DATA TO A TEMPORARY LOCATION

      for (int row = 0 ; row < 4 ; row++)
      for (int col = 0 ; col < 4 ; col++)
	 temp[row][col] = data[row][col];

      // USE TEMP TO DO THE MATRIX MULTIPLICATION

      for (int row = 0 ; row < 4 ; row++)
      for (int col = 0 ; col < 4 ; col++) {
         double data[row][col] = 0;
         for (int i = 0 ; i < 4 ; i++)
            data[row][col] += temp[row][i] * src[i][col];
      }
   }
      

Once you have methods to create the data for the primitive matrices, together with a method to do matrix multiplication, you can then implement the following methods which allow successive modification to a matrix, as we discussed in class:

   translate(a, b, c);
   rotateX(theta);
   rotateY(theta);
   rotateZ(theta);
   scale(a, b, c);
Each of these methods must first internally create a translation, rotation or scale matrix, respectively, and then it must do a matrix multiply. For example, you might implement your translation method as follows:
   public void translate(double a, double b, double c) {
      createTranslationData(a,b,c,temp); // CREATE TRANSLATION MATRIX DATA
      multiply(temp);                    // MULTIPLY BY THAT MATRIX DATA
   }
This will give you everything you need to combine matrix operations. For example, here is a sequence of steps to first translate, then rotate, and then scale a matrix.
   Matrix m = new Matrix();
   ...
   m.identity();
   m.translate(1,0,0);
   m.rotateY(Math.PI/2);
   m.scale(.5,.5,.5);
Finally, you'll eventually want to use your matrices to transform points. To do this, you need to implement a method that applies your matrix to transform a point src[], placing the result into pixel coordinates dst[]. Here's a way you might implement this within your Matrix class:
   public void transform(double src[], double dst[]) {
      for (int row = 0 ; row < dst.length ; row++) {
         dst[row] = 0;
	 for (int i = 0 ; i < src.length ; i++)
            dst[row] += data[row][i] * src[i];
      }
   }

Your assignment is to:

  • Implement a Matrix class that implements identity, translate, rotateX, rotateY, rotateZ, scale, and transform methods, as well as any support methods these may require.

  • Implement a java applet that models some cool shape as a collection of points, connected by edges (or maybe polygons -- see below). You can draw the edges using the java.awt.Graphics.drawLine(...) method. To do that, your applet will need a viewport method.

As we discussed in class, you need a viewport transform that converts the x and y coordinates of your point to pixels:

   void viewport(double src[], int dst[]) {
      dst[0] = (int)(0.5 * width  + src[0] * width);
      dst[1] = (int)(0.5 * height - src[1] * width);
   }
I've included that viewport method in a very simple applet that I implemented to give you the basic idea of things. Do not use the shape from my applet -- create your own original shape. What you should do is replace the simple house shape that I use in my example with a more interesting, more wonderful, or just plain cooler shape of your own devising. Then use matrices to transform that shape over time. Make a fun animation. :-)

Feel free to use multiple colors, or the fillPolygon method rather than the drawLine method if that will make your applet cooler looking. Also, if you are feeling ambitious, see whether you can create more than a single shape in your animation.

I look forward to seeing the result that you will post to your class web page.