SDL 2D Rotation

Well, I had been looking for a couple of days for ways to rotate parts of images etc. with the SDL library, but I only found that people said to use the opengl rotate functions.
I didn’t quite like this alternative :stuck_out_tongue:

So, here is what I came up with.

Code:
void SDL_Rotate(SDL_Surface surface, SDL_Rect rect, float angle, int x, int y) {
SDL_LockSurface(surface);
int bpp = surface->format->BytesPerPixel;
int white = SDL_MapRGB(surface->format,0xff,0xff,0xff);
char
pixels = (char
)malloc(surface->wsurface->hbpp);
for (int i = surface->wsurface->h; i >= 0; --i) {
char
c = pixels+ibpp;
memcpy(c,&white,bpp);
}
for(int sx = surface->w; sx >= 0; --sx) {
for (int sy = surface->h; sy >= 0; --sy) {
if (sx >= rect->x && sx < (rect->x+rect->w) && sy >= rect->y && sy < (rect->y+rect->h)) { //Point in surface is part of rect
float curangle;
if (sx-x == 0) {curangle = 90;}
else {curangle = atan((float)(sy-y)/(float)(sx-x)) * 180/3.14159;}
float l = sqrt(pow(sx-x,2)+pow(sy-y,2));
char
p = (char*)surface->pixels+sxbpp+sysurface->pitch;
char* q = (char*)pixels+((int)(cos((angle+curangle)*3.14159/180)*l)+x)*bpp+((int)(sin((angle+curangle)*3.14159/180)l)+y)surface->pitch;
memcpy(q,p,bpp);
if(memcmp(q+bpp,&white,bpp) == 0) {
memcpy(q+bpp,q,bpp); //To effectively cover without many/any holes
}
}
}
}
memcpy(surface->pixels,pixels,surface->w
surface->h
bpp);
SDL_UnlockSurface(surface);
}

As you can see, it only really needs the normal C math library. Other than that, its pretty straightforward and heeds pretty good results, if you want to rotate without getting to nit-picky in detail. The arguments are pretty obvious, and x and y describes the point of rotation. The surface of course must be updated afterward as well.

With my luck it has probably already been done before, as I expect it has, but I was unable to find it. But just in case others needed some reference…

it didn’t work…

:(------------------------
http://mandarx.xoom.it/index.php?lang=eng

Have you heard of SDL_gfx or Sprig?

Jonny DOn Tue, Mar 23, 2010 at 3:01 PM, mandarx wrote:

it didn’t work…

[image: Sad]


http://mandarx.xoom.it/index.php?lang=eng


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

wolf1oo wrote:

With my luck it has probably already been done before, as I expect it
has, but I was unable to find it. But just in case others needed some
reference…

SDL_rotozoom.

CE

aha, so I have finally found the elusive function. Annoys me that I couldn’t find it before… Oh well. Yeah the reason the above didnt work was because I wrote it really quick, not taking heed of the return of atan() being within -pi/2 and pi/2. Here is a full program that will rotate a box. Yay. I looked at rotozoom, its much higher quality I should say! Although of course, much more time put in as well :slight_smile: and thank god for that. Still have one bug in this version of my rotating function, which is driving me to my wits end. If you compile this and run it you’ll see what it is

Code:

#include <SDL/SDL.h>
#include <math.h>
#include <unistd.h>
#include
using namespace std;

void SDL_Rotate(SDL_Surface surface, SDL_Rect rect, float angle, int x, int y) {
SDL_LockSurface(surface);
int bpp = surface->format->BytesPerPixel;
int white = SDL_MapRGB(surface->format,0xff,0xff,0xff);
char
pixels = (char
)malloc(surface->wsurface->hbpp);
for (int i = surface->wsurface->h; i >= 0; --i) {
char
c = pixels+ibpp;
memcpy(c,&white,bpp);
}
for(int sx = surface->w; sx >= 0; --sx) {
for (int sy = surface->h; sy >= 0; --sy) {
if (sx >= rect->x && sx < (rect->x+rect->w) && sy >= rect->y && sy < (rect->y+rect->h)) { //Point in surface is part of rect
float curangle;
bool xshift = (abs(sx) > abs(x))?1:0;
bool yshift = (abs(sy) > abs(y))?0:1;
if (sx-x == 0) {curangle = (abs(sy) > abs(y))?270:90;}
else {curangle = atan((float)(sy-y+yshift)/(float)(sx-x+xshift)) * 180/3.14159;}
if (abs(sx-x) != sx-x) { //Correct angle, since atan() only returns [-pi/2,pi/2]
curangle=180.0-curangle;
}
if (fabs(curangle) != curangle) {curangle+=360;}
float l = sqrt(pow(sx-x,2)+pow(sy-y,2));
char
p = (char*)surface->pixels+sxbpp+sysurface->pitch;
char* q = (char*)pixels+(int)((cos((angle+curangle)*3.14159/180)*l)+x)*bpp+(int)((sin((angle+curangle)*3.14159/180)l)+y)surface->pitch;
memcpy(q,p,bpp);
if(memcmp(q+bpp,&white,bpp) == 0) {
memcpy(q+bpp,q,bpp); //To effectively cover without many/any holes
}
}
}
}
memcpy(surface->pixels,pixels,surface->w
surface->h
bpp);
SDL_UnlockSurface(surface);
}

int main() {
SDL_Init(SDL_INIT_VIDEO);
SDL_Surface videoSurface = SDL_SetVideoMode(640,480,16,0);
int white = SDL_MapRGB(videoSurface->format,0xff,0xff,0xff);
int black = SDL_MapRGB(videoSurface->format,0x00,0x00,0x00);
SDL_FillRect(videoSurface,NULL,white);
SDL_Rect
rect = new SDL_Rect();
rect->h = 120;
rect->w = 100;
rect->x = videoSurface->w/2-60;
rect->y = videoSurface->h/2-50;
SDL_FillRect(videoSurface,rect,black);
SDL_LockSurface(videoSurface);
char* original_pixels = (char*)malloc(videoSurface->wvideoSurface->hvideoSurface->format->BytesPerPixel);
memcpy(original_pixels,videoSurface->pixels,videoSurface->wvideoSurface->hvideoSurface->format->BytesPerPixel);
SDL_UnlockSurface(videoSurface);
SDL_UpdateRect(videoSurface,0,0,videoSurface->w,videoSurface->h);
atexit(SDL_Quit);
sleep(1);

for(int t = 15; t < 360; t+=15) {
	SDL_Rotate(videoSurface,rect,t,rect->x+rect->w/2,rect->y+rect->h/2);
	SDL_UpdateRect(videoSurface,0,0,videoSurface->w,videoSurface->h);
	sleep(1);
	SDL_LockSurface(videoSurface);
	memcpy(videoSurface->pixels,original_pixels,videoSurface->h*videoSurface->w*videoSurface->format->BytesPerPixel);
	SDL_UnlockSurface(videoSurface);
}

}