This lab is an introduction to Matrix Transformation
After the lab lecture, you have one week to:
Each vertex of polygons will pass through two main stages of transformations:
- Model view transformation (translation, rotation, and scaling of objects, 3D viewing transformation)
- Projection (perspective or orthographic)
There is one global matrix internally for each of the two stage above:
- M_{modelview}
- M_{projection}
Given a 3D vertex of a polygon, P = [x, y, z, 1]^{T}, in homogeneous coordinates, applying the model view transformation matrix to it will yield a new coordinate:
P’ = [x’, y’, z’, 1]^{T} = M_{modelview}*P.
By applying projection to P’, a 2D coordinate in homogeneous form is produced:
P” = [x”, y”, 1]^{T} = M_{projection}*P’.
The final coordinate [x”, y”] will be a point on the screen to be drawn.
Each matrix can be, and should be, initialized to identity at the beginning of an application.
For example, setting the model view matrix to the identity matrix can be done by:
glMatrixMode(GL_MODELVIEW); //selecting the global matrix to be modified glLoadIdentity(); //set the currently selected global matrix to identitySimilarly, we can set the projection matrix to identity as well:
glMatrixMode(GL_PROJECTION); glLoadIdentity();These two global transformation matrices can be modified by the following elementary transformation functions as required by individual applications.
glTranslate*(dx, dy, dz);
Where [dx, dy, dz] is the translation vector.
The effect of calling this function is to concatenate the translation matrix defined by the parameters [dx, dy, dz] to the global model view matrix:
M_{modelview} = M_{modelview} * T(dx, dy, dz);Where T(dx, dy, dz) =
In general, a new transformation matrix is always concatenated to the global matrix from the right. This is often called post-multiplication.
glRotate*(angle, x, y, z)
Where angle is the angle of counterclockwise rotation in degrees, and x, y and z define a vector(originating at the origin) to rotate about.
Typically we rotate about only one of the major axes, which simplifies x, y and z to be a unit vector.
For example, if we want to rotate about the x-axis, then x=1, y=0, and z=0.
The effect of calling a rotation matrix is similar to translation. For example, the function call:
glRotatef(a, 1, 0, 0);will have the following effect:
M_{modelview} = M_{modelview} * R_{x}(a);
Where R_{x}(a) denotes the rotation matrix about the x-axis for degree a: R_{x}(a) =
Rotations about the y-axis or z-axis can be achieved respectively by functions calls:
glRotatef(a, 0, 1, 0); // rotation about the y-axis glRotatef(a, 0, 0, 1); // rotation about the z-axis
glScale*(sx, sy, sz);
where sx, sy and sz are the scaling factors along each axis with respect to the local coordinate system of the model. The scaling transformation allows a transformation matrix to change the dimensions of an object by shrinking or stretching along the major axes centered on the origin.
Example: to make the wire cube three times as high, we can stretch it along the y-axis by a factor of 3 by using the following commands.
// make the y dimension 3 times larger glScalef(1, 3, 1); // draw the cube glutWireCube(1);
Example: Suppose we want to rotate a cube 30 degrees and place it 5 units away from the camera for drawing. You might write the program intuitively as below:
// first rotate about the x axis by 30 degrees glRotatef(30, 1, 0, 0); // then translate back 5 glTranslatef(0, 0, -5); // use the GLUT library's cube routine to draw // a cube centered(by default) at the origin
The following figure shows that:
If you run this program, you might be surprised to find that nothing appears in the picture! Think about WHY.
If we modify the program slightly as below:
// first translate back 5 glTranslatef(0, 0, -5); // then rotate about the x axis by 30 degrees glRotatef(30, 1, 0, 0); // use the GLUT library's cube routine to draw // a cube centered(by default) at the origin
The following figure shows that:
glTranslatef(0, 0, -5); glRotatef(30, 0, 1, 0); DrawTheModel();
Using the local coordinate, we first move the local coordinate's origin down the negative z-axis by 5 units and then rotate that coordinate system about y-axis by 30 degrees.
Using the global coordinate, we first rotate the global coordinate system about its origin by -30 degrees, then move the global coordinate system's origin down the positive z-axis by 5 units. The model is fixed, but the global coordinate system is rotated and translated. The viewpoint locates at the origin of the global coordinate system. Remember that in the global coordinate approach, the order is reversed, and the orientation order is also reversed.
The following is the local approach to a rotation:
The following is the global approach to a rotation:
The gluLookAt() Function: define a viewing transformation
void gluLookAt( GLdouble eyex, GLdouble eyey, GLdouble eyez, GLdouble centerx, GLdouble centery, GLdouble centerz, GLdouble upx, GLdouble upy, GLdouble upz )Parameters
eyex, eyey, eyez: specifies the position of the eye point; centerx, centery, centerz: specifies the position of the reference point; upx, upy, upz: specifies the direction of the up vector.
The gluLookAt() function makes it easy to move both the "from" and the "to" points in a linear manner. For example, if you need to pan along the wall of a building located away from the origin and aligned along no axes in particular, you could simply take the "to" point to be one corner of the building and calculating the "from" as a constant distance from the "to" point. To pan along the building, just vary the "to" point.
M_{modelview} = M_{viewing} * M_{modeling}
What this means is that your viewing transformations must be entered into the Modelview matrix before modeling transformations.
Three OpenGL commands are provided to directly manipulate the current matrix: glLoadIdentity(), glMultMatrix*() and glLoadMatrix*(). The glMultMatrix*() is used to perform matrix multiplication. glMultMatrix*(m) multiplies the current matrix with the one specified in m. That is, if M is the current matrix and T is the matrix passed to glMultMatrix, then M is replaced with MT. glLoadMatrix*(m) replaces the current matrix with the one specified in m. In the array m, the elements are stored in column order, whereas arrays in C or C++ are stored in row order. Do not be confused about these.
For viewport transformations, glViewport() takes four parameters, which are used to specify the lower-left corner coordinates and the width and height of the viewport. It is best to call it only once you know how big the window is. That means it should be in your resize function.
OpenGL provides two methods of converting 3D images into 2D ones.
- The first is orthographic, or parallel projection. You use this style of projection to maintain the scale of objects and their angles without regard to their apparent distance.
- The second is Perspective projection. This is the most popular choice in 3D graphics. OpenGL's perspective projection is created by a couple of commands, glFrustum() and gluPerspective.
Projection is handled by the GL_PROJECTION matrix. Before you modify what projection you are using you must switch to projection matrix mode. When you are done it is advisable to switch back to GL_MODELVIEW:
glMatrixMode(GL_PROJECTION); //Set up projectyion glMatrixMode(GL_MODELVIEW);glFrustum()
void glFrustum( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far ) Parameters: left, right: Specify the coordinates for the left and right vertical clipping planes; bottom, top: Specify the coordinates for the bottom and top horizontal clipping planes; near, far: Specify the distances to the near and far depth clipping planes. Both distances must be positive.glFrustum() describes a perspective matrix that produces a perspective projection. (left, bottom, -near) and (right, top, -near) specify the points on the near clipping plane that are mapped to the lower left and upper right corners of the window, respectively, assuming that the eye is located at (0, 0, 0). -far specifies the location of the far clipping plane. Both near and far must be positive.
The following shows perspective viewing volume and the glFrustum() parameters
gluPerspective()
Although glFrustum() is powerful, it is not very intuitive. GLU provides a much simpler perspective command, called gluPerspective(). Like glFrustum() it generates a perspective viewing volume but in a much simpler way.
void gluPerspective( GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar ) Parameters: Fovy: Specifies the field of view angle, in degrees, in the y direction; Aspect: Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height); ZNear: Specifies the distance from the viewer to the near clipping plane (always positive); ZFar: Specifies the distance from the viewer to the far clipping plane (always positive).gluPerspective() specifies a viewing frustum into the world coordinate system. In general, the aspect ratio in gluPerspective should match the aspect ratio of the associated viewport. For example, aspect=2.0 means the viewer's angle of view is twice as wide in x as it is in y. If the viewport is twice as wide as it is tall, it displays the image without distortion.
The following shows perspective viewing volume and the gluPerspective() parameters
Start with this code: boxes.cpp.
As written, this program draws a basic coordinate system with a green x-axis, a red y-axis, and a blue z-axis.
With the initial camera settings you are looking directly down the z-axis so you will not see it.
Make the following changes. Write your answers to the questions in steps 1, 2, 4 and 11.
/5 marks
Click here for some code that draws a robot arm.
/5 marks