Sdl_rotozoom Problems


PokeParadox

Founder of Pirate Games - Penjin Coder
Staff member
Joined
Dec 8, 2005
Messages
6,603
Age
41
Location
UK
Website
pokeparadox.itch.io
WEBSITE
https://github.com/pokeparadox
YOUTUBE
pokeparadox
Ok... anyone know anything about rotozoom and SDL, because I'm hitting my head against the keyboard trying to fix rotations...
Either I can get full sprite rotated and displayed but it's not centred... or I can get it centred but it's cropped :/

here is the truncated code from my image class:
CODE

else if(useRotation)
{
SDL_Surface* tempImage = NULL;
src.w *=scaleX;
src.h *=scaleY;

if(angle || scaleX != 1 || scaleY != 1)
{
if(!angle)
tempImage = zoomSurface(images,scaleX, scaleY, SMOOTHING_OFF);
else
tempImage = rotozoomSurfaceXY(images, angle, scaleX, scaleY, SMOOTHING_ON);
src.x -= (src.w - tempImage->w)/2;
src.y -= (src.h - tempImage->h)/2;
}
SDL_BlitSurface(tempImage,&src, dstimg, &dst);
if(tempImage)
SDL_FreeSurface(tempImage);
}


And this is what it currently does...
 
How about this:

CODE

SDL_Surface* tempImage = NULL;

if(angle || scaleX != 1 || scaleY != 1)
{
if(!angle)
tempImage = zoomSurface(images,scaleX, scaleY, SMOOTHING_OFF);
else
tempImage = rotozoomSurfaceXY(images, angle, scaleX, scaleY, SMOOTHING_ON);
}

dst.x = (dstimg->w - tempImage->w) / 2;
dst.y = (dstimg->h - tempImage->h) / 2;

SDL_BlitSurface(tempImage, NULL, dstimg, &dst);

if(tempImage)
SDL_FreeSurface(tempImage);



Of course dstimg needs to be at least as large as tempImage, otherwise tempImage will be cropped. Is dstimg the screen?
 
Rotating is always a huge PITA to me.

ie: Given a square, if you rotate it 45deg, it will be much 'larger' in the original squares dimensions of width/height (ie: the poiints stick out.) So you have to enlarge the buffers to handle the new image size, or else get cropped. centering can be a pain depending on the origin of the rotation (roitate in the middle or based oin some arbitrary point?)

I've not messed iwth SDL rotations in years and years, but I just know in my own rotation code its an ugly kludge :)

jeff
 
Alex. said:
How about this:

CODE

SDL_Surface* tempImage = NULL;

if(angle || scaleX != 1 || scaleY != 1)
{
if(!angle)
tempImage = zoomSurface(images,scaleX, scaleY, SMOOTHING_OFF);
else
tempImage = rotozoomSurfaceXY(images, angle, scaleX, scaleY, SMOOTHING_ON);
}

dst.x = (dstimg->w - tempImage->w) / 2;
dst.y = (dstimg->h - tempImage->h) / 2;

SDL_BlitSurface(tempImage, NULL, dstimg, &dst);

if(tempImage)
SDL_FreeSurface(tempImage);

Of course dstimg needs to be at least as large as tempImage, otherwise tempImage will be cropped. Is dstimg the screen?

dstimg is the screen yes.
I've tried that(I'm sure I tried that before too) and
now the logo is not centred... and not cropped and kind of bouncing around... hmmm
 
Last edited by a moderator:
Hmm, could it be that the surface returned by the rotozoom is larger than the minimum rectangle that can hold the rotated image? That would explain it bouncing around.
 
I tested the code below and it works:

CODE
SDL_Surface* screen = SDL_SetVideoMode (320, 240, 32, SDL_SWSURFACE);
SDL_Surface* img = IMG_Load("bar.png");
int angle = 0;

...

if(++angle >= 360) angle = 0;
SDL_FillRect(screen, NULL, 0);

SDL_Surface* rot = rotozoomSurfaceXY(img, angle, 1, 1, SMOOTHING_ON);

SDL_Rect dst = {(320 - rot->w) / 2, (240 - rot->h) / 2};
SDL_BlitSurface(rot, NULL, screen, &dst);

SDL_FreeSurface(rot);
SDL_Flip(screen);


rotoworksau6.gif
 
Is rotation is hardware-accelerated in SDL? (mean hw version on GP2X)
 
Alex. said:
I tested the code below and it works:
Ooh, thanks! Looking at it I think I know what I've been doing wrong!
You're a star! (hopefully :lol:)

quasist said:
Is rotation is hardware-accelerated in SDL? (mean hw version on GP2X)
I don't think so, but I don't know how optimised it is. In all honesty I'll be using this in PandoraPanic! which is for Pandora, but the Pandora section of the board doesn't have the "I need Dev help", and also my engine supports GP2X too so it should benefit.

Best thing to do is to store prerotated surfaces where speed is critical. I intend of adding that later, but needed to get it working in the first place. Thanks again Alex. :)

UPDATE: Thankyouuuuu! It was those bloody "-=" I changed those to just an "-" sign and voilá! :)

UPDATE2: Just to share the wealth, here is my final rotate function:
dst is the position of the sprite, images is the original surface, tempImage is the rotated surface.
Now I just need to fix AnimatedSprites (which I can do now)
CODE

else if(useRotation)
{
SDL_Surface* tempImage = NULL;

if(angle || scaleX != 1 || scaleY != 1)
{
tempImage = rotozoomSurfaceXY(images, angle, scaleX, scaleY, SMOOTHING_OFF);
dst.x += (images->w - tempImage->w)/2;
dst.y += (images->h - tempImage->h)/2;
}
SDL_BlitSurface(tempImage,NULL/*&src*/, dstimg, &dst);
if(tempImage)
SDL_FreeSurface(tempImage);
}
 
Last edited by a moderator:
Bah... seems cropping an SDL_surface isn't working how I thought it would:
CODE

SDL_Surface* Image::cropSurface(SDL_Surface* in, SDL_Rect* c)
{
SDL_Surface *cropped = NULL;
// Cropped surface
cropped = SDL_CreateRGBSurface(in->flags,c->w, c->h,in->format->BitsPerPixel,
in->format->Rmask,in->format->Gmask,in->format->Bmask, in->format->Amask);

SDL_BlitSurface(in,c,cropped,NULL);
return cropped;
}


I pass in the clip rect from my spritesheet animation and nothing is display. My intention is to isolate one frame of the animation sheet, rotozoom that... This is what I'm doing, but the AnimatedSprite doesn't show :blink:
CODE

else if(useRotation)
{
SDL_Surface* tempImage = NULL;
SDL_Surface* subSprite = NULL; // Need to use this for animated sprites to get the subsprite isolated.

if(angle || scaleX != 1 || scaleY != 1)
{
if(sheetMode)
{
subSprite = cropSurface(images,&src);
tempImage = rotozoomSurfaceXY(subSprite, angle, scaleX, scaleY, SMOOTHING_OFF);
dst.x += (subSprite->w - tempImage->w)/2;
dst.y += (subSprite->h - tempImage->h)/2;
SDL_FreeSurface(subSprite);
}
else
{
tempImage = rotozoomSurfaceXY(images, angle, scaleX, scaleY, SMOOTHING_OFF);
dst.x += (images->w - tempImage->w)/2;
dst.y += (images->h - tempImage->h)/2;
}
SDL_BlitSurface(tempImage,NULL, dstimg, &dst);
SDL_FreeSurface(tempImage);
}
}
 
Maybe you're passing scale 1 and angle 0 in your tests? I think you shouldn't filter against those cases, after all 'useRotation' wouldn't be true unless in the majority of cases it would be expected to do something.

The cropping method looks fine, try blitting a sprite from it without passing it through rotozoom, just to see if it works.
 
The problem must be in SDL_CreateRGBSurface then, try this, it works for me.

CODE
// Cropped surface
cropped = SDL_CreateRGBSurface(in->flags,c->w, c->h,in->format->BitsPerPixel, 0, 0, 0, 0);


All masks are 0, that sets them to auto values.
 
Thanks again Alex, your response has helped me find out what was going wrong (I had to reset the transparent colour after creating the cropped surface!)

Animated Sprites are rotating fine now! :)
 
Back
Top