Homework due Wednesday, Feb 13, 2008

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:

   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 these set and get routines in various ways. For example, you can copy one matrix into another by:

   public void copy(Matrix src) {
      for (int i = 0 ; i < 4 ; i++)
      for (int j = 0 ; j < 4 ; j++)
	 set(i,j, src.get(i,j));
   }

You will be implementing an API for matrices that consists of the following methods: translate(a, b, c), rotateX(theta), rotateY(theta), rotateZ(theta), scale(a, b, c) and transform(src[], dst[]).

In order to implement this API, you will need to build matrix primitives as well as a method to do matrix multiply. The first thing you need to do is implement internal methods for your Matrix class the build the matrix primitives:

    identityMatrix();
    translationMatrix(double x, double y, double z);
    xRotationMatrix(double theta);
    yRotationMatrix(double theta);
    zRotationMatrix(double theta);
    scaleMatrix(double x, double y, double z);

In the on-line notes I go over the math for implementing these primitives.

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

public class Matrix {

...

   public void translationMatrix(double a, double b, double c) {
      identity();
      data[0][3] = a;
      data[1][3] = b;
      data[2][3] = c;
   }
}
Given that you have implemented primitive matrix routines to create an identity, translation, rotation, and scale, you need to build software that transforms 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 most of you already know, you do this by taking the inner product between the rows of the first matrix and the columns of the second matrix. As you recall from your linear algebra classes: 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];

So you can implement matrix multiplication by:

   Matrix temp = new Matrix();

   ...

   void multiply(Matrix M) {
      temp.copy(this);      // FIRST COPY MY ORIGINAL DATA TO A TEMPORARY MATRIX
      for (int i = 0 ; i < 4 ; i++)
      for (int j = 0 ; j < 4 ; j++) {
         double sum = 0;
         for (int k = 0 ; k < 4 ; k++)
            sum += temp.get(i,k) * M.get(k,j);
         data[i][j] = sum;  // THEN COMPUTE NEW DATA VALUES FOR ME
      }
   }
      

Note that I use a method copy(Matrix src) in the code above. To implement matrix multiplication, you will find it convenient to implement a matrix copy method.

Now you are ready to implement the following methods in the API:

   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:
   public void translate(double a, double b, double c) {
      temp.translationMatrix(a,b,c); // CREATE A TRANSLATION MATRIX
      multiply(temp);                // MULTIPLY ME BY THAT MATRIX
   }
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 vertices of your geometry. To do this, you need to implement a method that applies your matrix to transform a point src[], placing the result into dst[]. Here's how you might implement that:
   public void transform(double src[], double dst[]) {
      for (int i = 0 ; i < 3 ; i++)
         dst[i] = data[i][0] * src[0] + data[i][1] * src[1] + data[i][2] * src[2] + data[i][3];
   }

Your assignment is to:

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

  2. I've created a really simple applet to help you test your Matrix class. 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. :-)

    Post your result to your class web page.