Sign in to follow this  
fpsgamer

DIRECTDRAW: Bitmap rotation woes....

Recommended Posts

As it turns out the bitmap rotation feature in DirectDraw isnt supported by all cards. Are there any other API functions that I can use to rotate a bitmap by some arbitrary angle? If there aren't any standard API functions, what algorithm would you reccomend. I've read about a few methods, the simplest being passing each pixel through a rotation matrix and the rest I've read were over myhead or slightly unclear.... So if anyone knows any shortcuts I would appreciate it :)

Share this post


Link to post
Share on other sites
Well there are various methods.. GDI has a function, for example.

Hybridizing with some D3D rasterizing is a good solid choice, although you may decide to just drop the DirectDraw stuff entirely in such a case.

if you decide to "do it yourself" then try to continue to leverage the fast directdraw blitting... scanline by scanline in several passes.. shear.. transpose.. shear.. transpose... http://www.gamedev.net/reference/articles/article811.asp

Share this post


Link to post
Share on other sites
After trying to write the function a few times I was able to google and find a completed version. The function passes each pixel of the source bitmap through a rotation matrix and then plots the resulting point onto another surface. Unfortunately I have yet to see success.

The code uses structures from a particular book that I happen to be using.
A BOB is a struct that describes a sprite. In it is an array called "images" which are direct draw surfaces (LPDIRECTDRAWSURFACE7) that describe each frame of animation.

sin_look[x] and cos_look[x] are trig lookup tables.


#define kBitmapWidth 64
#define kBitmapWidthHalf (kBitmapWidth / 2)
#define kBitmapRotatedWidth (int)(ceil(sqrt(kBitmapWidth*kBitmapWidth +
kBitmapWidth*kBitmapWidth)))
OR #define kBitmapRotatedWidth 64
#define kBitmapRotatedWidthLessOne (kBitmapRotatedWidth - 1)
#define rotationPointX (kBitmapRotatedWidth/2)
#define rotationPointY (kBitmapRotatedWidth/2)


int Rotate_BOB(BOB_PTR sourceBob, BOB_PTR destBob, int angle, int frame)
{
// this function rotates a source BOB by the specified angle
// and stores the new image in the destination bob

UCHAR *dest_buffer = NULL; // used to reference the destination buffer
UCHAR *source_buffer = NULL; // used to reference the image buffer
int dest_lpitch; // the linear pitch of the destination buffer
int source_lpitch; // the linear pitch of the image buffer
long x, y;
int xInt, yInt;
int newX, newY;

// is this a valid bob
if (!sourceBob || !destBob)
return(0);

// is the destination bob big enough
// to hold the rotated image?
if (destBob->width < kBitmapRotatedWidth)
return(0);

// clear the destination surface
DDraw_Fill_Surface(destBob->images[frame], 0);

// lock the destination surface, and the image surface
dest_buffer = DDraw_Lock_Surface(destBob->images[frame], &dest_lpitch);
source_buffer = DDraw_Lock_Surface(sourceBob->images[0], &source_lpitch);

// set the angle as the inverse
angle = 360 - angle;
if (angle >=360)
angle = 0;

Build_Sin_Cos_Tables();

// step through each destination pixel and locate the
// source pixel
for (newY=0; newY<kBitmapRotatedWidth; newY++)
{
for (newX=0; newX<kBitmapRotatedWidth; newX++)

// put the (newX,newY) coordinate through the rotation matrix
// use fixed point maths
x = (long)(((newX-rotationPointX) * cos_look[angle]) + ((newY-rotationPointY) * -sin_look[angle]) + rotationPointX) * 256;
y = (long)(((newX-rotationPointY) * sin_look[angle]) + ((newY-rotationPointY) * cos_look[angle]) + rotationPointY) * 256;

xInt = x >> 8; //im really not sure why this author does this bit shifting
yInt = y >> 8;

// if the source pixels are in the range of the source BOB
// then write them to the destination BOB
if (xInt < 0 || xInt > kBitmapRotatedWidthLessOne || yInt < 0 || yInt > kBitmapRotatedWidthLessOne) {
//do nothing
}else if (source_buffer[xInt + yInt * source_lpitch] != 0)
dest_buffer[newX + newY * dest_lpitch] = source_buffer[xInt + yInt * source_lpitch];
}

// unlock the surfaces, very important!
DDraw_Unlock_Surface(destBob->images[frame]);
DDraw_Unlock_Surface(sourceBob->images[0]);

// return success
return(1);

} // end Rotate_BOB



The function seems to execute but doesnt seem to transfer any pixels between the surfaces at all!

Share this post


Link to post
Share on other sites
You might want to have a look at AGG:
http://antigrain.com/

You can pass in a pointer to the surface and a description of the format and render transformed bitmaps as well as high-quality vector graphics. Haven't used it myself, but it seems a lot faster than GDI+ and certainly has better quality and versatility.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this