RotationThe rotation matrix is the most complex of all the transformations because it's full of trig functions. Basically, you want to rotate the input point by using the rotation equations. To achieve this, you must look at the rotation equations, pick the operators, and then push them into a matrix. In addition, you don't want any translation, so the bottom row in positions 0 and 1 will be 0. Here's the matrix that does the job: | cos q sin q 0| Mr = |-sin q cos q 0| | 0 0 1 | Eg . p = [x y 1] | cos q sin q 0 | p' = p*Mr = [x y 1] * |-sin q cos q 0 | = | 0 0 1 | p' = [(x*cos q – y*sin q) (x*sin q + y*cos q) 1] Which is correct! Before moving on to polygons, let's discuss the question that was posed before in reference to using a 3x2 post-multiplication matrix rather than a 3x3. It looks as if the last term in all the matrix multiplications is completely discarded, in addition to always being 1.0. Both of these statements are true. Therefore, for the transformations that you've performed thus far, you can use a 3x2. However, I wanted to use a 3x3 to make a point about homogenous matrices and coordinates. The significance of the last 1.0 is this (in reality, let's refer to it as q): To convert the coordinates to their final correct form after the transformation is complete, you would divide by the factor q, or in other words: p' =[x y q] x' = x/q y' = y/q However, because q = 1 in this case, the divisions are unnecessary, as is the computation of q. Nonetheless, this factor will have importance later in the discussion of 3D graphics, so keep it in mind. In any case, with this new information, you can change a couple of data structures and store all points in a 1x2 and all transformation matrices in a 3x2, using the following data structures and transform function: // the transformation matrix typedef struct MATRIX3X2_TYP { float M[3][2]; // data storage } MATRIX3X2, *MATRIX3X2_PTR; // our 2D point typedef struct MATRIX1X2_TYP { float M[2]; // data storage } MATRIX1X2, *MATRIX1X2_PTR; int Mat_Mul_1X2_3X2(MATRIX1X2_PTR ma, MATRIX3X2_PTR mb, MATRIX1X2_PTR mprod) { // this function multiplies a 1x2 matrix against a // 3x2 matrix – ma*mb and stores the result // using a dummy element for the 3rd element of the 1x2 // to make the matrix multiply valid i.e. 1x3 X 3x2 for (int col=0; col<2; col++) { // compute dot product from row of ma // and column of mb float sum = 0; // used to hold result for (int index=0; index<2; index++) { // add in next product pair sum+=(ma->M[index]*mb->M[index][col]); } // end for index // add in last element * 1 sum+= mb[index][col]; // insert resulting col element mprod->M[col] = sum; } // end for col return(1); } // end Mat_Mul_1X2_3X2 For a demo of using matrices in a program, check out DEMO8_6.CPP|EXE. I've created a polygon that resembles a little spaceship in wire frame, and you can scale, rotate, and translate it. Take a look at Figure 8.26 for a screen shot. Figure 8.26. DEMO8_6.EXE in action.NOTE You must always multiply a m x r matrix by an r x n matrix. In other words, the inner dimension must be equal. Obviously, 1x2 and 3x2 don't work because 2 is not equal to 3. However, in the code, you can add a dummy element 1.0 to each of the 1x2's, making them into 1x3's, just for the math to work out. Here are the control keys for this demo:
|