Direct3D's core provides tons of functionality to application developers. But it is an immediate-mode API at heart, so functionality is basically geared toward rendering. Most persistent data structures and complex algorithms are omitted from the API for elegance and simplicity. But that does not imply that we have to code these manually. In the most recent iterations of Microsoft's API, an additional library called the extension library has grown from a simple collection of frequently used routines to a full-blown set of objects and functions, which make programming games much easier. Need progressive meshes? Animation controls? All are included within the Direct3DX extension library. In this section, we will review what's available for developers in version 9.0.
The ID3DXMesh interface provides access to triangle meshes. Many game developers prefer to keep full control over their mesh representation and rendering. However, after taking a look at the features included in this interface, you might want to think twice. Many popular algorithms are included, so you can get working with little or no coding at all. Routines like X file loading, generating indexed meshes, stripping data, and sorting by texture identifier are all supported internally. For example, assuming an ID3DXMesh object, the following code generates triangle strips from it:
D3dxmesh->Optimize(D3DXMESHOPT_STRIPREORDER | D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT, PrevAdj, PostAdj, FaceMap, VertMap, newmesh);
This code returns a second mesh (newmesh) based on the original one, making sure data is converted to strips, unused vertices are deleted, and faces are sorted by attributes to minimize state changes. PrevAdj and PostAdj are the input and resulting adjacency lists, whereas FaceMap and VertMap are indices to faces and vertices.
Progressive meshes (see Chapter 22, "Geometrical Algorithms") are one of the most powerful paradigms to represent level-of-detail (LOD) geometry. They allow us to scale the number of triangles up or down with very little CPU impact, thus making them ideal for video games. But progressive meshes are hard to get right. Luckily, the extension library has an interface to support them internally, so you do not have to worry about the algorithm's specifics. The interface is equivalent to ID3DMesh, but includes specific calls to change the object's level of detail. In this case, the calls are as follows, which set the number of faces to be used by the progressive mesh engine:
Due to the nature of these meshes, we may not get a mesh with the exact triangle count we request, but it will definitely be close.
The ID3DXFont interface provides font rendering capabilities, so we can access TrueType fonts and use them within our application. Fonts are created using the following code:
HRESULT D3DXCreateFont( LPDIRECT3DDEVICE9 pDevice, HFONT hFont, LPD3DXFONT *ppFont );
The first parameter is the Direct3D object, the second is the font object information encapsulated in an HFONT interface, and the third returns the newly created font. Then, all we have to do is render text to the screen by using the following line:
INT DrawText(LPCSTR pString, INT Count, LPRECT pRect, DWORD Format, D3DCOLOR Color);
We pass the string, the number of characters to be rendered, a rectangle defining the position and size of the characters, a format string that can be used for justification and so on, and a color.