BackgroundTweening (short for in-betweening) is an animation term for the process of generating intermediate frames between two keyframes in order to make an animation appear smooth. In traditional animation (think The Simpsons) a production's animators will draw the main frames of a scene, and then send just these keyframes to an off-site production company (somewhere in Asia), where low-paid animators do the grunt work of generating in-between frames so that the animation will be smooth. For vector graphics (such as a 3d model), the grunt work of generating the in-between frames can be done mathematically. The easiest and fastest technique is called linear interpolation. Linear interpolation is represented by one simple equation: X′ = X1 + t × (X2 - X1) Plugging in the starting position vertex for X1, the ending position vertex for X2, and a time factor (the percent to interpolate between the vertices), X′ will give us the location of the intermediate vertex:
Fortunately, DirectX 8-9 implements this for us, and I am going to show you how to use it with DirectX 9 to make your own animations. But first, I'm going to show you another cool feature of DirectX that will help us to implement tweening. By the way, for the purposes of this article I will assume that you have basic knowledge of creating and using vertex buffers- so if you don't know about VB's, read the SDK documentation or check out some of the awesome articles on gamedev. Vertex DeclarationsVertex Declarations were introduced in DirectX 8 as a powerful alternative to the Flexible Vertex Format (FVF). Vertex declarations are the epitome of vertex-defining flexibility, and make it dead-simple to add features such as multi-texturing and (surprise, surprise) vertex tweening. If you've ever worked with vertex shaders, you probably already know about vertex declarations.
In case you don't know or understand how a vertex declaration works, I will briefly explain it here. When you render primitives in DirectX, you input a buffer of vertex data, which is simply a long list of 1's and 0's. DirectX does not, by default, know how this buffer should be interpreted to form the vertices that make up your space marine or "hello, world" multi-colored cube. The vertex declaration is a map that you provide to DirectX so that it can interpret the data from a byte stream into usable vertex data. In DirectX 9, vertex declarations are "declared" as an array of D3DVERTEXELEMENT9 structures. The fields of the structure are fairly easy to understand and fill out once you understand what they do. Here is the structure:
typedef struct _D3DVERTEXELEMENT9 {
BYTE Stream;
BYTE Offset;
BYTE Type;
BYTE Method;
BYTE Usage;
BYTE UsageIndex;
} D3DVERTEXELEMENT9;
There are many more possible values- see the DirectX SDK documentation under Vertex Declaration. That said, here is a sample declaration that defines a position and a diffuse color:
D3DVERTEXELEMENT9 simple_decl[] =
{
{0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
{0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
D3DDECL_END() // this macro is needed as the last item!
};
Also new to DirectX 9, vertex declarations are COM objects. Don't fret, however, as creating them is one simple call to the device: IDirect3DVertexDeclaration9* my_vertex_declaration; d3d_device->CreateVertexDeclaration(simple_decl, &my_vertex_declaration); Now, get this - the above declaration is equivalent to the following fvf constant: const DWORD simple_fvf = D3DFVF_XYZ|D3DFVF_DIFFUSE; The FVF constant is obviously less code and complexity, so why use vertex declarations instead? Because they allow us to provide additional sets of vertex coordinates on separate streams for tweening, of course! They also are useful for multi-texturing and using the programmable vertex pipeline, as briefly mentioned earlier. For these reasons and more, it is definitely worth learning how to use them. |
|