Bitmap Rotation and Scaling
DirectDraw supports both bitmap rotation and scaling, as shown in Figure 7.31. However, only the HAL supports rotation. This means that if there isn't hardware support for rotation, you're out of luck. You might ask, "Why does the HEL support scaling and not rotation?" The answer is that bitmap rotation is about 10–100 times slower than a scaling operation, and Microsoft found that no matter how well they wrote software rotation code, it was just too slow! So the long and the short of it is that you can always count on scaling, but not rotation. You can always write your own bitmap rotation function, but this is rather complex and not really necessary for 3D polygon games. I'm not going to cover it in this book. However, this is one of the reasons Microsoft merged DirectDraw with Direct3D. If you just use 3D polygons for everything, and texture map onto them your 2D bitmap and place the camera in an aerial view then you end up being able to rotate, shear, do transparency, lighting effects, everything. However, this comes at the cost of having to use 3D hardware to do 2D graphics which is fine, but if you don't want to then it's not!
Performing bitmap scaling is easy. All you need to do is change the size of the destination RECT to make it different from the source RECT image, and the image will be scaled. For example, let's say that you have an image that's 64x64, and you want to scale it to a size mxn and position it at (x,y). Here's the code:
// fill in the destination rect dest_rect.left = x; dest_rect.top = x; dest_rect.right = x+m-1; dest_rect.bottom = y+n-1; // fill in the source rect source_rect.left = 0; source_rect.top = 0; source_rect.right = 64-1; source_rect.bottom = 64-1; // blt to destination surface if (FAILED(lpddsback->Blt(&dest_rect, lpdds_image, &source_rect, (DDBLT_WAIT | DDBLT_KEYSRC), NULL))) return(0);
That's easy enough! Rotation is a little harder, though, because you have to set up a DDBLTFX structure. To perform a rotation operation on a bitmap. you must have hardware acceleration that supports it (very rare) and then set up a DDBLTFX structure, as follows:
DDBLTFX ddbltfx; // this holds our data // initialize the structure DDRAW_INIT_STRUCT(ddbltfx); // set rotation angle, note that each unit is in 1/100 // of a degree rotation ddbltfx.dwRotationAngle = angle; // each unit is
Then you make the call to Blt() as you normally would, but you add the flag DDBLT_ROTATIONANGLE to the flags parameter and add the ddbltfx parameter like this:
// blt to destination surface if (FAILED(lpddsback->Blt(&dest_rect, lpdds_image, &source_rect, (DDBLT_WAIT | DDBLT_KEYSRC | DDBLT_ROTATIONANGLE), &ddbltfx))) return(0);
You can determine if your hardware has rotation support by querying the surface capabilities of the DDSCAPS structure of a surface and looking at the DDFXCAPS_BLTROTATION* caps flags in the dwFxCaps member of DDSCAPS. You can query the capabilities of a surface with the IDIRECTDRAWSURFACE7::GetCaps() function, which I'll cover at the end of the chapter.
And if you have hardware-accelerated rotation, the bitmap will rotate!