Page 131 - Computer Graphics Handout
P. 131
3.11.4 Order of Transformations
You might be bothered by what appears to be a reversal of the required function calls. The rule in OpenGL is this: The transformation
specified last is the one applied first. A little examination shows that this order is a consequence of multiplying the CTM on the right
by the specified affine transformation and thus is both correct and reasonable. The sequence of operations that we specified was
C←I,
C←CT(4.0, 5.0, 6.0),
C←CR(45.0, 1.0, 2.0, 3.0),
C←CT(−4.0, −5.0, −6.0).
In each step, we postmultiply at the end of the existing CTM, forming the matrix
C = T(4.0, 5.0, 6.0)R(45.0, 1.0, 2.0, 3.0)T(−4.0, −5.0, −6.0),
which is the matrix that we expect from Section 3.11. Each vertex p that is specified after the model-view matrix has been set will
be multiplied by C, thus forming the new vertex
q = Cp.
There are other ways to think about the order of operations. One way is in terms of a stack. Altering the CTM is similar to pushing
matrices onto a stack; when we apply the final transformation, the matrices are popped off the stack in the reverse order in which
they were placed there. The analogy is conceptual rather than exact because when we use a transformation function, the matrix is
altered immediately.
3.12 SPINNING OF THE CUBE
We will now examine how we can manipulate the color cube interactively. We will take the cube that we defined in Section 3.6 and
we rotate it using the three buttons of the mouse. Our program will be based on the following three callback functions:
glutDisplayFunc(display);
glutIdleFunc(spincube);
glutMouseFunc(mouse)
We will examine two fundamentally different ways of doing the updates to the display. In the first, we will form a new model-view
matrix in the display callback and apply it to the vertex data to get new vertex positions. We must then send the new data to the
GPU. In the second, we will send the model-view matrix to the vertex shader and apply it there. The mouse and idle callbacks will
be the same in both cases, so let’s examine them first. The mouse callback selects the axis for rotation, using 0, 1, and 2 to denote
rotation about the x, y, and z axes, respectively:
int axis = 0;
void mouse(int button, int state, int x, int y)
{
if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) axis = 0;
if(button == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN) axis = 1;
if(button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) axis = 2;
}
The idle callback increments the angle associated with the chosen axis by 0.1 degrees
each time:
void spinCube()
{
theta[axis] += 0.1;
if( theta[axis] > 360.0 ) theta[axis] -= 360.0;
glutPostRedisplay();
}
3.12.1 Updating in the Display Callback
The function display starts by clearing the frame and depth buffers and then forms a model-view matrix using the values of three
angles determined by the mouse callback
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
mat4 ctm = RotateX(theta[0])*RotateY(theta[1])*RotateZ(theta[2]);
131

