Bitmap rotation1

(for the not leaking version see Bitmap rotation2)

When working with tiles and sprites  you can rotate the sprite easily, because rotation is a property of the sprite. But we are working in the bitmapmode.

We can copy images to a background without a problem, but rotating the image is somewhat complicated.

The first solution is to do a simnple rotation of points:

within the loop of the pixels of the image:

//minus point of rotation
float x = (float)j – height/2.0;
float y = (float)i – width/2.0;
//rotating matrix
float newX = x*cosine-y*sine;
float newY = x*sine+y*cosine;
//plus point of rotation
int newIntX = (int)newX + height/2.0;
int newIntY = (int)newY + width/2.0;

but the you notice that some pixels due to approximations are not drawn. Some pixel locations are not reached:


The trick is to work from the destination bitmap and ask for the pixel color of the source…

see this link:

http://www.codeguru.com/cpp/g-m/bitmap/specialeffects/article.php/c1743/

but here the rotation is done from the corner point (0,0) and the use of the double buffer has to be considered for nds programming.

we solve these problems in this way:

float cosine = cos(angle);
float sine = sin(angle);

// Compute dimensions of the resulting bitmap, but now using four points and transforming these

int cx = width/2; //point of rotation
int cy = height/2;

int x0 = (int)(0 – cx); //four points minus point of rotation
int y0 = (int)(0 – cy);
int x1 = (int)(width – cx);
int y1 = (int)(0 – cy);
int x2 = (int)(width – cx);
int y2 = (int)(height – cy);
int x3 = (int)(0 – cx);
int y3 = (int)(height – cy);
int x0N = (int)(x0 * cosine – y0 * sine) + cx; //transform the points of rotation
int y0N = (int)(y0 * cosine + x0 * sine) + cy;
int x1N = (int)(x1 * cosine – y1 * sine) + cx;
int y1N = (int)(y1 * cosine + x1 * sine) + cy;
int x2N = (int)(x2 * cosine – y2 * sine) + cx;
int y2N = (int)(y2 * cosine + x2 * sine) + cy;
int x3N = (int)(x3 * cosine – y3 * sine) + cx;
int y3N = (int)(y3 * cosine + x3 * sine) + cy;

int minx = min(x0N,min(x1N, min(x2N,x3N))) ; //find the limiting bounding box
int miny = min(y0N,min(y1N, min(y2N,y3N))) ;
int maxx = max(x0N,max(x1N, max(x2N,x3N))) ;
int maxy = max(y0N,max(y1N, max(y2N,y3N))) ;

//then we do the trick:

int x,y;
for(  y = miny; y < maxy; y++ )
{
for(  x = minx; x < maxx; x++ )
{ //same as in the link
int sourcex = (int)(( x – cx )*cosine + ( y – cy )*sine) + cx; //only consider the point of rotation
int sourcey = (int)(( y – cy )*cosine – ( x – cx )*sine) + cy;


//now find out if point is in the original rectangle using a method finding out if a point is in a triangle

//we use this 2 times to get the point in the rectangle

int intBool1 = pointInTriangle ( x0N,x1N,x2N,y0N,y1N,y2N,x, y) ;
int intBool2 = pointInTriangle ( x2N,x3N,x0N,y2N,y3N,y0N,x, y) ;

//now if point is in triangle1 or triangle 2:

if ( intBool1 == 1 || intBool2 == 1 )
{
if ( bufferX + x>0 && bufferX + x < 256  && bufferY + y>0 && bufferY + y < 192) //if in field
{
index = ((bitmapY + sourcey) * width) + bitmapX + sourcex;
drawPixel(video_buffer_Dest, bufferX + x, bufferY + y, PIXEL(bitmap[index]));
}
}
else //if not in the rectangle restore the old pixel coming from the hidden double buffer
{
u16 backColor = getPixel(video_buffer_Source, bufferX + x, bufferY + y);
drawPixel(video_buffer_Dest, bufferX + x, bufferY + y, backColor );
}
}
}

without blanks, but you see the rotation effect on the paperclip

Ok, eating is the proof of the pudding: (a sketch just showing the rotation of a rather big bitmap to get a good view of the effect)

http://cid-58814201e79976dd.skydrive.live.com/self.aspx/iepro/bitmapRotation%5E_DB.zip

You can see the image is somewhat leaking at the corners, which can possible be solved by restoring from a slightly bigger range from the hidden buffer.

Also looking at the method parameters (far too much!), you see this is crying for a struct “around the image”, having members like

  • imagename (start array of pixels
  • imageWidth
  • imageHeight
  • posX
  • posY
  • rotationAngle
  • rotationPosX
  • rotationPosY


Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: