**LISTING 52.3 L52-3.C** /* Routines to perform incremental rotations around the three axes. */ #include #include "polygon.h" /* Concatenate a rotation by Angle around the X axis to transformation in XformToChange, placing the result back into XformToChange. */ void AppendRotationX(Xform XformToChange, double Angle) { Fixedpoint Temp10, Temp11, Temp12, Temp20, Temp21, Temp22; Fixedpoint CosTemp = DOUBLE_TO_FIXED(cos(Angle)); Fixedpoint SinTemp = DOUBLE_TO_FIXED(sin(Angle)); /* Calculate the new values of the six affected matrix entries */ Temp10 = FixedMul(CosTemp, XformToChange[1][0]) + FixedMul(-SinTemp, XformToChange[2][0]); Temp11 = FixedMul(CosTemp, XformToChange[1][1]) + FixedMul(-SinTemp, XformToChange[2][1]); Temp12 = FixedMul(CosTemp, XformToChange[1][2]) + FixedMul(-SinTemp, XformToChange[2][2]); Temp20 = FixedMul(SinTemp, XformToChange[1][0]) + FixedMul(CosTemp, XformToChange[2][0]); Temp21 = FixedMul(SinTemp, XformToChange[1][1]) + FixedMul(CosTemp, XformToChange[2][1]); Temp22 = FixedMul(SinTemp, XformToChange[1][2]) + FixedMul(CosTemp, XformToChange[2][2]); /* Put the results back into XformToChange */ XformToChange[1][0] = Temp10; XformToChange[1][1] = Temp11; XformToChange[1][2] = Temp12; XformToChange[2][0] = Temp20; XformToChange[2][1] = Temp21; XformToChange[2][2] = Temp22; } /* Concatenate a rotation by Angle around the Y axis to transformation in XformToChange, placing the result back into XformToChange. */ void AppendRotationY(Xform XformToChange, double Angle) { Fixedpoint Temp00, Temp01, Temp02, Temp20, Temp21, Temp22; Fixedpoint CosTemp = DOUBLE_TO_FIXED(cos(Angle)); Fixedpoint SinTemp = DOUBLE_TO_FIXED(sin(Angle)); /* Calculate the new values of the six affected matrix entries */ Temp00 = FixedMul(CosTemp, XformToChange[0][0]) + FixedMul(SinTemp, XformToChange[2][0]); Temp01 = FixedMul(CosTemp, XformToChange[0][1]) + FixedMul(SinTemp, XformToChange[2][1]); Temp02 = FixedMul(CosTemp, XformToChange[0][2]) + FixedMul(SinTemp, XformToChange[2][2]); Temp20 = FixedMul(-SinTemp, XformToChange[0][0]) + FixedMul( CosTemp, XformToChange[2][0]); Temp21 = FixedMul(-SinTemp, XformToChange[0][1]) + FixedMul(CosTemp, XformToChange[2][1]); Temp22 = FixedMul(-SinTemp, XformToChange[0][2]) + FixedMul(CosTemp, XformToChange[2][2]); /* Put the results back into XformToChange */ XformToChange[0][0] = Temp00; XformToChange[0][1] = Temp01; XformToChange[0][2] = Temp02; XformToChange[2][0] = Temp20; XformToChange[2][1] = Temp21; XformToChange[2][2] = Temp22; } /* Concatenate a rotation by Angle around the Z axis to transformation in XformToChange, placing the result back into XformToChange. */ void AppendRotationZ(Xform XformToChange, double Angle) { Fixedpoint Temp00, Temp01, Temp02, Temp10, Temp11, Temp12; Fixedpoint CosTemp = DOUBLE_TO_FIXED(cos(Angle)); Fixedpoint SinTemp = DOUBLE_TO_FIXED(sin(Angle)); /* Calculate the new values of the six affected matrix entries */ Temp00 = FixedMul(CosTemp, XformToChange[0][0]) + FixedMul(-SinTemp, XformToChange[1][0]); Temp01 = FixedMul(CosTemp, XformToChange[0][1]) + FixedMul(-SinTemp, XformToChange[1][1]); Temp02 = FixedMul(CosTemp, XformToChange[0][2]) + FixedMul(-SinTemp, XformToChange[1][2]); Temp10 = FixedMul(SinTemp, XformToChange[0][0]) + FixedMul(CosTemp, XformToChange[1][0]); Temp11 = FixedMul(SinTemp, XformToChange[0][1]) + FixedMul(CosTemp, XformToChange[1][1]); Temp12 = FixedMul(SinTemp, XformToChange[0][2]) + FixedMul(CosTemp, XformToChange[1][2]); /* Put the results back into XformToChange */ XformToChange[0][0] = Temp00; XformToChange[0][1] = Temp01; XformToChange[0][2] = Temp02; XformToChange[1][0] = Temp10; XformToChange[1][1] = Temp11; XformToChange[1][2] = Temp12; } **LISTING 52.4 L52-4.C** /* Fixed point matrix arithmetic functions. */ #include "polygon.h" /* Matrix multiplies Xform by SourceVec, and stores the result in DestVec. Multiplies a 4x4 matrix times a 4x1 matrix; the result is a 4x1 matrix. Cheats by assuming the W coord is 1 and bottom row of matrix is 0 0 0 1, and doesn't bother to set the W coordinate of the destination. */ void XformVec(Xform WorkingXform, Fixedpoint *SourceVec, Fixedpoint *DestVec) { int i; for (i=0; i<3; i++) DestVec[i] = FixedMul(WorkingXform[i][0], SourceVec[0]) + FixedMul(WorkingXform[i][1], SourceVec[1]) + FixedMul(WorkingXform[i][2], SourceVec[2]) + WorkingXform[i][3]; /* no need to multiply by W = 1 */ } /* Matrix multiplies SourceXform1 by SourceXform2 and stores result in DestXform. Multiplies a 4x4 matrix times a 4x4 matrix; result is a 4x4 matrix. Cheats by assuming bottom row of each matrix is 0 0 0 1, and doesn't bother to set the bottom row of the destination. */ void ConcatXforms(Xform SourceXform1, Xform SourceXform2, Xform DestXform) { int i, j; for (i=0; i<3; i++) { for (j=0; j<4; j++) DestXform[i][j] = FixedMul(SourceXform1[i][0], SourceXform2[0][j]) + FixedMul(SourceXform1[i][1], SourceXform2[1][j]) + FixedMul(SourceXform1[i][2], SourceXform2[2][j]) + SourceXform1[i][3]; } } **LISTING 52.5 L52-5.C** /* Set up basic data that needs to be in fixed point, to avoid data definition hassles. */ #include "polygon.h" /* All vertices in the basic cube */ static IntPoint3 IntCubeVerts[NUM_CUBE_VERTS] = { {15,15,15},{15,15,-15},{15,-15,15},{15,-15,-15}, {-15,15,15},{-15,15,-15},{-15,-15,15},{-15,-15,-15} }; /* Transformation from world space into view space (no transformation, currently) */ static int IntWorldViewXform[3][4] = { {1,0,0,0}, {0,1,0,0}, {0,0,1,0}}; void InitializeFixedPoint() { int i, j; for (i=0; i<3; i++) for (j=0; j<4; j++) WorldViewXform[i][j] = INT_TO_FIXED(IntWorldViewXform[i][j]); for (i=0; i