Transformation Hierarchy:

In order to create nested transformations, (eg: the limbs of a person, or the steering wheel of a moving automobile), we need a way to create tree structures of transformations. As we discussed in class, you will traverse this tree of nested transformations by using a stack.

NOTE: For this week's assigment I am going to provide you with a very easy way to implement this matrix stack, so that you can practice making hierarchical objects and movements. For this assignment, feel free to use the support code that I provide in these on-line notes. But do not just duplicate the simple one-armed person that I use as an example. You need to come up with your own original example of a model and animation. Creating a full human figure (with all the arms and legs) is ok.

One way to implement the stack is as an array of matrices, together with an integer stack pointer:

```   final static int MATRIX_STACK_SIZE = 100;
int matrixStackTop = 0;
Matrix matrixStack[] = new Matrix[MATRIX_STACK_SIZE];
{
for (int n = 0 ; n < MATRIX_STACK_SIZE ; n++)
matrixStack[n] = new Matrix();
}
```
As we discussed in class, we need a way to reset this stack at the beginning of each animation frame, a way to push/copy a value on the stack, a way to pop off the top value, and a way to get the value of the matrix currently at the top of the stack. This functionality can be implemented by the following four methods:
```   // CLEAR THE STACK BEFORE PROCESSING THIS ANIMATION FRAME

public void mclear() {
matrixStackTop = 0;
matrixStack[0].identity();
}

// PUSH/COPY THE MATRIX ON TOP OF THE STACK -- RETURN false IF OVERFLOW

public boolean mpush() {
if (matrixStackTop + 1 >= MATRIX_STACK_SIZE)
return false;

matrixStack[matrixStackTop + 1].copy(matrixStack[matrixStackTop]);
matrixStackTop++;
return true;
}

// POP OFF THE MATRIX ON TOP OF THE STACK -- RETURN false IF UNDERFLOW

public boolean mpop() {
if (matrixStackTop <= 0)
return false;

--matrixStackTop;
return true;
}

// RETURN THE MATRIX CURRENTLY ON TOP OF THE STACK

public Matrix m() {
return matrixStack[matrixStackTop];
}
```
As we discussed in class, you can use these methods both for doing modeling operations on your Geometry primitives, and also for doing animation operations.

Generally speaking, you use just the `m()` method to modify the matrix on top of the stack. You use the `mpush()` and `mpop()` methods to traverse the hierarchy that relates the different parts of the model to each other.

For example, here is some simple example code that makes the arm wave on a simple model of a person who has a left arm but no right arm:

```   Geometry torso        = addNewGeometry().cylinder(16);

public void update(double time) {

// CLEAR THE MATRIX STACK FOR THIS ANIMATION FRAME

mclear();

// UPDATE THE TORSO SHAPE

mpush();
m().rotateX(-Math.PI / 2); // ORIENT THE TORSO CYLINDER UPRIGHT
m().scale(0.9, 0.7, 1);
m().translate(0, 0, 1);
transformAndRender(torso, m());
mpop();

mpush();

// TRANSLATE CURRENT POSITION TO THE NECK JOINT

m().translate(0, 2, 0);

// ANY CODE TO NOD OR SHAKE THE HEAD WOULD GO JUST AFTER THIS COMMENT

mpush();
m().translate(0, 1, 0);        // TRANSLATE THE HEAD UP, OFF OF THE TORSO
m().scale(0.5, 0.7, 0.5);      // SCALE THE HEAD INTO AN ELLIPSOID SHAPE
transformAndRender(body, m());
mpop();

mpop();

mpush();

// TRANSLATE CURRENT POSITION TO THE LEFT SHOULDER JOINT

m().translate(1, 2, 0);

// ROTATE ABOUT THE LEFT SHOULDER JOINT

m().rotateZ(Math.PI / 4 * Math.sin(3 * time));

// UPDATE THE LEFT UPPER ARM SHAPE

mpush();
m().rotateY(Math.PI / 2); // UPPER ARM STICKS OUT TO THE RIGHT
m().scale(0.2, 0.2, 2);
m().translate(0, 0, 1);
transformAndRender(leftUpperArm, m());
mpop();

// TRANSLATE CURRENT POSITION TO THE LEFT ELBOW JOINT

m().translate(2, 0, 0);

// ROTATE ABOUT THE LEFT ELBOW JOINT

m().rotateZ(Math.PI / 4 * (1 + Math.sin(3 * time)));

// UPDATE THE LEFT LOWER ARM SHAPE

mpush();
m().rotateY(Math.PI / 2); // LOWER ARM STICKS OUT TO THE RIGHT
m().scale(0.2, 0.2, 2);
m().translate(0, 0, 1);
transformAndRender(leftLowerArm, m());
mpop();
mpop();
}
```
I leave it up to you to implement the `addNewGeometry()` and `transformAndRender()` methods in a way that is consistent with what you've done so far.

YOUR HOMEWORK, DUE BEFORE CLASS STARTS ON THURSDAY MARCH 1:

Create your own animated hierarchical model. It can be anything that's fun and interesting, and that can be built from the shape primitives that you have implemented. Possibilities include a person running, two people dancing. a cat walking, a spider walking, a butterfly in flight, a twisting worm, a pool table with pool balls, an automobile with rolling wheels and a steering wheel, an electric motor, the solar system As you can see, the possibilities are endless.

For this assignment, please incorporate perspective, as described in class and in the on-line notes.