Documentation Archive Developer
Search

ADC Home > Reference Library > Technical Q&As > QuickTime > Graphics & Imaging >

Why does my identity matrix look strange?


Q: I'm trying to understand why my QuckTime identity matrix doesn't seem correct. I thought a QuickTime identity matrix is supposed to be:

1 0 0
0 1 0
0 0 1

But whenever I create one using SetIdentityMaxtix, I get the following:

1 0 0
0 1 0
    0 0 16384

Am I doing something wrong? What does the number 16384 mean?

A: While a MatrixRecord is declared as a 3-by-3 array of Fixed values, the last column of this structure is actually interpreted as Fract. Therefore, the number 16384 is really just 1.0 as a Fract.

Here's a closer look:

A Fixed is a 16-bit signed integer plus a 16-bit fraction.
A Fract is a 2-bit signed integer plus a 30-bit fraction.

typedef long Fixed;
typedef long Fract;
struct MatrixRecord {
     Fixed matrix[3][3];
};
typedef struct MatrixRecord MatrixRecord;

Each cell in Figure 1 represents the data type of the corresponding element of a 3-by-3 matrix. The elements in the first two columns of a matrix are represented by Fixed values. The elements in the third column, although declared as Fixed, are represented internally as Fract values. The Fract data type specifies a 32-bit, fixed-point value that contains 2 integer bits and 30 fractional bits.

[0][0]Fixed       [1][0]Fixed       [2][0]Fract
[0][1]Fixed       [1][1]Fixed       [2][1]Fract
[0][2]Fixed       [1][2]Fixed       [2][2]Fract

Figure 1. MatrixRecord

This is done because the last column defines non-affine (perspective) transformations. These transforms require additional precision in the math, but not as much range for the values.

Because this last column of values have a complex mapping between the element value and behavior, they are quite difficult to set up properly on your own. QuickTime provides the QuadToQuadMatrix API which can be used to set up a perspective matrix, and can also be used to perform any transformation (scale, rotate, skew, and so on) with a minimal amount of brainwork.

OSErr QuadToQuadMatrix(const Fixed *source,
                       const Fixed *dest, MatrixRecord *map);

Figure 2. QuadToQuadMatrix API

This call takes four initial points, four final points, and defines a matrix that will map between them.

The following is an example of using QuadToQuadMatrix to build a matrix that performs a Star Wars type "scroll into the distance" effect. The function simply starts with your source points (x, y) top left, top right, bottom right and bottom left. Then sets up the destination points top left + 20 in x, + 40 in y, top right - 20 in x, + 40 in y, bottom right and bottom left.

void SetPerspectiveMatrix(Rect &inRect, MatrixRecord &outMatrix)
{
    FixedPoint source[4], dest[4];
    source[0].x = Long2Fix(inRect->left);
    source[0].y = Long2Fix(inRect->top);
    source[1].x = Long2Fix(inRect->right);
    source[1].y = Long2Fix(inRect->top);
    source[2].x = Long2Fix(inRect->right);
    source[2].y = Long2Fix(inRect->bottom);
    source[3].x = Long2Fix(inRect->left);
    source[3].y = Long2Fix(inRect->bottom);
    dest[0].x = Long2Fix(inRect->left + 20);
    dest[0].y = Long2Fix(inRect->top + 40);
    dest[1].x = Long2Fix(inRect->right - 20);
    dest[1].y = Long2Fix(inRect->top + 40);
    dest[2].x = Long2Fix(inRect->right);
    dest[2].y = Long2Fix(inRect->bottom);
    dest[3].x = Long2Fix(inRect->left);
    dest[3].y = Long2Fix(inRect->bottom);
    QuadToQuadMatrix((Fixed *)source, (Fixed *)dest, outMatrix);
}

Listing 1. Example use of QuadToQuadMatrix



[Jan 03 2002]