CSC 240: Computer Graphics

Homework 4: Transformations II

Due: Friday, Oct. 14, 11:59pm on Moodle

The goal of this homework is to practice working with transformation matrices in a different setting than the previous homework. This time we'll implement each transformation matrix in JavaScript, then use them to create an animation. In some ways we are implementing Lab 3 from scratch, which should hopefully make the order of transformations clearer. We'll also be working with a global transformation matrix, which is exactly how HTML Canvas and WebGL work.

1) Identity matrix

First, download the starter code hw4.html. There is one function implemented called pushMatrix. This function is going to take in a new transformation matrix, multiply the current matrix by this new transformation, and then replace the current matrix with the result. Finally, it will set the current matrix internally (erasing any previous transformations), using the Canvas setTransform method. This uses the Canvas transform method as a subroutine.

For this part, implement a function to create the identity matrix:

function identityMatrix() {
...
}
This should return a 3x3 (2D) array. Then, inside the init method (right before draw), call the identityMatrix method to set the currMatrix to the identity. Our currMatrix variable is global, meaning that we don't have different matrices for each object, they all share the same one.

2) Matrix multiplication

Next implement a matrix multiplication function:

function matrixMultiply(M1, M2) {
...
}
that takes in two matrices, M1, and M2, and returns the result of M1*M2. Your function should be general, in the sense that it should be able to take in any two matrices with matching inner dimensions. When building up the result, it might be helpful to use the push function. For example:

var row = [];
row.push(5); // row is 
var l = row.length; // l is 1
This is a great opportunity to practice for loops in JavaScript and continue learning about JavaScript syntax.

When implementing this function, you should not be looking at any other code that implements matrix multiplication, even in a different language!

3) Transformation matrices

Similar to the identity matrix, create functions for each transformation: scale, rotate, translate, reflection (either across the x or y axis), and shear (choose either x or y direction). Use the arguments below:

function scaleMatrix(ax, ay)     // usually called A
function rotateMatrix(theta)     // usually called R
function translateMatrix(tx, ty) // usually called T
function reflectionMatrix()      // usually called F
function shearMatrix(lambda)     // usually called S
Each of these functions should return a 3x3 matrix.

4) Testing

Inside draw, test each of your methods, and their compositions. After creating each transformation matrix, call the pushMatrix function to multiply it by the current matrix. If you want to undo transformations, we must multiply by the inverse transformations.

Note 1: in this homework, outside of creating shapes and using graphics.setTransform(...) inside pushMatrix, we will not be using ANY built-in transformations. This part should all be from scratch.

Note 2: if you would prefer to put the call to pushMatrix inside each transformation matrix function, you can do that instead. In this case, rename your functions to be translate instead of translateMatrix, etc, since these functions don't need to return a matrix.

5) Figure 8

Using your transformation matrices and the setInteval method for a timer, create an animation that moves a shape (square, circle, etc) in a figure 8 motion (like an ice-skater or drawing an infinity symbol). Save this version as hw4_figure8.html.

Edit: if you would like to clear the canvas before each step of your animation, use this procedure:

graphics.save(); // save the current set of transformations
graphics.setTransform(1, 0, 0, 1, 0, 0); // reset matrix to the identity
graphics.clearRect(0, 0, canvas.width, canvas.height); // clear canvas
graphics.restore(); // restore the transformations you had before
This makes sure the canvas is cleared properly without any transformations, but it still saves whatever transformations you were working with. Other than this, you may not use setTransform except in pushMatrix!