1.2 Creating a Transformation Matrix

In a typical graphics process, you render polygons after establishing the position of the model and the camera and setting the view port. The same is true for the N64; before rendering graphics you must prepare the model view transformation matrix and the projection transformation matrix. There are two ways of indicating a matrix in an N64 program: as a 4x4 two-dimensional array, or as an Mtx union. By using the latter method and defining the matrix as a union, the array is concealed from the user. Typical N64 OS matrix manipulation functions come in two versions, one for arrays and one for unions. The functions that take arguments in array format are named with an F as the last letter (e.g., guLookAtF). Please remember this convention. Also note that with the union format, each element in the array is expressed in fixed decimal s15.16 format, so you need to be careful when explicitly setting elements. If you are going to separately set elements inside the program, it is best to use the floating point array format.

Next, we will look at a number of functions that the N64 OS has available for manipulating matrices.

Creating a Projection Transformation Matrix

You can use any of the following functions to create a projection transformation matrix:
guPerspective(F) Use for perspective transformations
guOrtho(F) Use for orthogonal transformations
guFrustum(F) Use when defining a perspective transformation from the viewing volume.

Creating a Model View Transformation Matrix

Use the guLookAt(F) function to create a model view transformation matrix:
guLookAt(F) Defines the model view transformation from the viewpoint, the lookat point and the up vector.

Figure 1-1 shows how you can use the guLookAt(F) function to specify the viewpoint and the point that acts as the center of the screen.



Figure 1-1 Conceptual drawing of the guLookAt(F) function

However, in this tutorial we are going to construct a model view transformation that combines scaling, rotation and translation without making use of the guLookAt(F) function.

There are many different useful functions available for matrix calculations in addition to the ones below. They are all easy to use, so we will leave the details to the Function Reference and settle here for a simple explanation of each.

guMtxIdent(F) Initializes the matrix as the identity matrix
guScale(F) Sets scale matrix in the given matrix
guRotate(F) Sets rotation matrix in the given matrix
guRotateRPY(F) Creates rotation matrix from roll, pitch and yaw
guTranslate(F) Sets translation matrix in the given matrix
guMtxCatF Multiplies floating point matrices
guMtxCatL Multiplies fixed point matrices
guMtxF2L Converts floating point matrix to fixed point
guMtxL2F Converts fixed point matrix to floating point.

You use these functions in the program to create the projection transformation matrix and the model view transformation matrix. To give a concrete example of this process we have displayed part of the gfx1.c sample program in the frame below.

List 1-1

  /* Function creating the projection transformation matrix  */
  guPerspective(&projection,
                &perspNorm,
                45.0,                                 /* Viewing angle  */
                (float)SCREEN_WD / (float)SCREEN_HT,  /* Aspect ratio */
                10.0, 100.0,                          /* Distance to clipping plane */
                1.0);

  /* Create rotation matrix */
  guRotateF(fmat1, theta, 1.0, 1.0, 0.5);
  /* Translation matrix in order to keep the distance from the viewpoint  */
  guTranslateF(fmat2, 0.0, 0.0, -50.0);
  /* Multiply 2 matrices  (Put result in fmat1)*/
  guMtxCatF(fmat1, fmat2, fmat1);
  /* Convert matrix from floating point to fixed point  */
  guMtxF2L(fmat1, &modeling);

Most of the calculations done in this code are common to general graphics processes, but let's give a brief explanation will be given of guPerspective, the function that creates the projection matrix. The first argument in this function is the pointer to the matrix union. guPerspective appropriately sets the elements of the array indicated by this argument. The second argument, perspNorm, helps maintain computational precision by dividing by the w-coordinate value of the calculated screen coordinates. When you call guPerspective the appropriate scaling constant is stored in perspNorm. Specify this with the gSPPerspNormalize command and pass it to the RSP.

See Figure 1-2 about the viewing angle, aspect ratio and distance to the clipping plane.



Figure 1-2 The 3D world settings of gfx1.c

The final argument of guPerspective is the scaling constant for the whole matrix. Every element of the matrix is multiplied by this value within guPerspective. For example, when drawing a small-scale 3D world, you could use the scaling constant to enlarge the overall geometry in order to maintain the computational precision until it is time for rendering.