Platform SDK: DirectX

Step 2.2: Create and Set the View Matrix

[Visual Basic]

The information in this section pertains only to applications written in C and C++. See Direct3D Immediate Mode Visual Basic Tutorials.

[C++]

Given an eye point, a look-at point, and an up vector, you can manually build a 4x4 view matrix for your application. First, get the z basis vector, which points straight ahead:

HRESULT SetViewMatrix( D3DMATRIX& mat, D3DVECTOR& vFrom, D3DVECTOR& vAt,
                       D3DVECTOR& vWorldUp )
{
    // Get the z basis vector, which points straight ahead. This is the
    // difference from the eyepoint to the lookat point.
    D3DVECTOR vView = vAt - vFrom;

The z basis vector is the difference from the eye point to the look-at point. You should normalize the z basis vector before using it in your calculations:

    FLOAT fLength = Magnitude( vView );
    if( fLength < 1e-6f )
        return E_INVALIDARG;
 
    // Normalize the z basis vector
    vView /= fLength;

The preceding code uses the Magnitude function to return the absolute value of the view vector; the Magnitude function is available to programmers who define D3D_OVERLOADS in their projects. For more information on the helper functions provided by the D3D_OVERLOADS C++ extensions, see D3D_OVERLOADS Helper Functions.

Now, you can retrieve the dot product and calculate the projection of the z basis vector onto the up vector. The resulting projection is the y basis vector:

    FLOAT fDotProduct = DotProduct( vWorldUp, vView );
 
    D3DVECTOR vUp = vWorldUp - fDotProduct * vView;

Note  DotProduct is a function defined in D3D_OVERLOADS.

The following code fragment normalizes the y-basis vector:

    vUp /= fLength;

To find the x basis vector, determine the cross product of the y and z basis vectors:

    D3DVECTOR vRight = CrossProduct( vUp, vView );

Note  CrossProduct is a function defined in D3D_OVERLOADS.

At this point, you have enough information to begin building the new view matrix. In the following code, the first three rows contain the basis vectors used to rotate the view to point at the look-at point:

    mat._11 = vRight.x;  mat._12 = vUp.x;  mat._13 = vView.x;  mat._14 = 0.0f;
    mat._21 = vRight.y;  mat._22 = vUp.y;  mat._23 = vView.y;  mat._24 = 0.0f;
    mat._31 = vRight.z;  mat._32 = vUp.z;  mat._33 = vView.z;  mat._34 = 0.0f;

Now, you set the translation values. Note that rotations are still about the eye point:

    mat._41 = - DotProduct( vFrom, vRight );
    mat._42 = - DotProduct( vFrom, vUp );
    mat._43 = - DotProduct( vFrom, vView );
    mat._44 = 1.0f;

After setting the translation values, control returns to the calling application-defined function, App_FrameMove. You can put the new view matrix into effect by calling the IDirect3DDevice7::SetTransform method:

    pd3dDevice->SetTransform( D3DTRANSFORMSTATE_VIEW, &matView );

The cube's vertices are transformed by the programmer-defined function, TransformVertices, which is explained in Step 2.3: Perform the 3-D Transformation.