Previous | Table of Contents | Next

LISTING 52.3 L52-3.C

    /* Routines to perform incremental rotations around the three axes. */

    #include <math.h>
    #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<NUM_CUBE_VERTS; i++) {
          CubeVerts[i].X = INT_TO_FIXED(IntCubeVerts[i].X);
          CubeVerts[i].Y = INT_TO_FIXED(IntCubeVerts[i].Y);
          CubeVerts[i].Z = INT_TO_FIXED(IntCubeVerts[i].Z);
       }
    }

Previous | Table of Contents | Next

Graphics Programming Black Book © 2001 Michael Abrash