Jump to content


Photo

Sdl_rotozoom Problems


  • Please log in to reply
13 replies to this topic

#1 PokeParadox

PokeParadox

    Founder of Pirate Games - Penjin Coder

  • GP32 Hardcore
  • PipPipPipPipPipPip
  • 3908 posts
  • Gender:Male
  • Location:UK
  • Interests:Homebrew and Emulation!

Posted 26 November 2008 - 04:22 PM

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[i],scaleX, scaleY, SMOOTHING_OFF);
                else
                    tempImage = rotozoomSurfaceXY(images[i], 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...
IPB Image

#2 Alex.

Alex.

    Retired

  • GP Guru
  • 4582 posts
  • Gender:Male

Posted 26 November 2008 - 07:18 PM

How about this:

CODE

SDL_Surface* tempImage = NULL;

if(angle || scaleX != 1 || scaleY != 1)
{
    if(!angle)
        tempImage = zoomSurface(images[i],scaleX, scaleY, SMOOTHING_OFF);
    else
        tempImage = rotozoomSurfaceXY(images[i], 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?

Edited by Alex., 26 November 2008 - 07:20 PM.


#3 skeezix

skeezix

    Mega GP Mania

  • GP Guru
  • 5088 posts
  • Gender:Male
  • Interests:Blog: http://www.rjmitchell.ca/~jeff/blog2009/

Posted 26 November 2008 - 07:53 PM

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 smile.gif

jeff

#4 PokeParadox

PokeParadox

    Founder of Pirate Games - Penjin Coder

  • GP32 Hardcore
  • PipPipPipPipPipPip
  • 3908 posts
  • Gender:Male
  • Location:UK
  • Interests:Homebrew and Emulation!

Posted 26 November 2008 - 09:05 PM

QUOTE(Alex. @ Nov 26 2008, 07:18 PM) View Post

How about this:

CODE

SDL_Surface* tempImage = NULL;

if(angle || scaleX != 1 || scaleY != 1)
{
    if(!angle)
        tempImage = zoomSurface(images[i],scaleX, scaleY, SMOOTHING_OFF);
    else
        tempImage = rotozoomSurfaceXY(images[i], 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

#5 Alex.

Alex.

    Retired

  • GP Guru
  • 4582 posts
  • Gender:Male

Posted 26 November 2008 - 09:44 PM

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.

#6 PokeParadox

PokeParadox

    Founder of Pirate Games - Penjin Coder

  • GP32 Hardcore
  • PipPipPipPipPipPip
  • 3908 posts
  • Gender:Male
  • Location:UK
  • Interests:Homebrew and Emulation!

Posted 26 November 2008 - 10:07 PM

if it helps any... it's offset away from the topleft corner of the screen (approximately in the area the sprite is supposed to be)
But it's bouncing around there...

IPB Image

#7 Alex.

Alex.

    Retired

  • GP Guru
  • 4582 posts
  • Gender:Male

Posted 26 November 2008 - 11:05 PM

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);


IPB Image

#8 quasist

quasist

    !DIZ IZ WIZ!

  • GP32 Hardcore
  • PipPipPipPipPipPip
  • 1230 posts
  • Location:Gorod Khotkovo
  • Interests:A B C ... C++

Posted 26 November 2008 - 11:08 PM

Is rotation is hardware-accelerated in SDL? (mean hw version on GP2X)

Edited by quasist, 26 November 2008 - 11:08 PM.


#9 PokeParadox

PokeParadox

    Founder of Pirate Games - Penjin Coder

  • GP32 Hardcore
  • PipPipPipPipPipPip
  • 3908 posts
  • Gender:Male
  • Location:UK
  • Interests:Homebrew and Emulation!

Posted 26 November 2008 - 11:30 PM

QUOTE(Alex. @ Nov 26 2008, 11:05 PM) View Post

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 laugh.gif)

QUOTE(quasist @ Nov 26 2008, 11:08 PM) View Post

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. smile.gif

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

UPDATE2: Just to share the wealth, here is my final rotate function:
dst is the position of the sprite, images[i] 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[i], angle, scaleX, scaleY, SMOOTHING_OFF);
                dst.x += (images[i]->w - tempImage->w)/2;
                dst.y += (images[i]->h - tempImage->h)/2;
            }
            SDL_BlitSurface(tempImage,NULL/*&src*/, dstimg, &dst);
            if(tempImage)
                SDL_FreeSurface(tempImage);
        }

Edited by PokeParadox, 26 November 2008 - 11:53 PM.


#10 PokeParadox

PokeParadox

    Founder of Pirate Games - Penjin Coder

  • GP32 Hardcore
  • PipPipPipPipPipPip
  • 3908 posts
  • Gender:Male
  • Location:UK
  • Interests:Homebrew and Emulation!

Posted 27 November 2008 - 12:39 PM

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.gif
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[i],&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[i], angle, scaleX, scaleY, SMOOTHING_OFF);
                    dst.x += (images[i]->w - tempImage->w)/2;
                    dst.y += (images[i]->h - tempImage->h)/2;
                }
                SDL_BlitSurface(tempImage,NULL, dstimg, &dst);
                SDL_FreeSurface(tempImage);
            }
        }


#11 Alex.

Alex.

    Retired

  • GP Guru
  • 4582 posts
  • Gender:Male

Posted 27 November 2008 - 03:16 PM

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.



#12 PokeParadox

PokeParadox

    Founder of Pirate Games - Penjin Coder

  • GP32 Hardcore
  • PipPipPipPipPipPip
  • 3908 posts
  • Gender:Male
  • Location:UK
  • Interests:Homebrew and Emulation!

Posted 27 November 2008 - 03:56 PM

OK, I sorted out the filtering problem, thanks for pointing that out.
And I'm getting a square of the correct dimensions, but it's all black...

#13 Alex.

Alex.

    Retired

  • GP Guru
  • 4582 posts
  • Gender:Male

Posted 28 November 2008 - 03:05 PM

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.

#14 PokeParadox

PokeParadox

    Founder of Pirate Games - Penjin Coder

  • GP32 Hardcore
  • PipPipPipPipPipPip
  • 3908 posts
  • Gender:Male
  • Location:UK
  • Interests:Homebrew and Emulation!

Posted 28 November 2008 - 08:55 PM

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! smile.gif