The SDL forums have moved to discourse.libsdl.org.
This is just a read-only archive of the previous forums, to keep old links working.


SDL Forum Index
SDL
Simple Directmedia Layer Forums
SDL 2D Rotation
wolf1oo


Joined: 22 Mar 2010
Posts: 2
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 Razz

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->w*surface->h*bpp);
   for (int i = surface->w*surface->h; i >= 0; --i) {
      char* c = pixels+i*bpp;
      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+sx*bpp+sy*surface->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 too 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.....
Re: SDL 2D Rotation
mandarx


Joined: 19 Dec 2009
Posts: 61
Location: Inside Volcano Etna
it didn't work...

:(

can you post a complete program ??
SDL 2D Rotation
Jonny D


Joined: 12 Sep 2009
Posts: 932
Have you heard of SDL_gfx or Sprig?

Jonny D


On Tue, Mar 23, 2010 at 3:01 PM, mandarx wrote:
Quote:
it didn't work...







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


_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

SDL 2D Rotation
Chris Eineke
Guest

wolf1oo wrote:
Quote:
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
_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
wolf1oo


Joined: 22 Mar 2010
Posts: 2
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 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 <iostream>
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->w*surface->h*bpp);
   for (int i = surface->w*surface->h; i >= 0; --i) {
      char* c = pixels+i*bpp;
      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+sx*bpp+sy*surface->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->w*videoSurface->h*videoSurface->format->BytesPerPixel);
   memcpy(original_pixels,videoSurface->pixels,videoSurface->w*videoSurface->h*videoSurface->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);
   }
}