Jump to content
  • Advertisement
Sign in to follow this  
PunaProgrammer chris

SDL_gfx rototzoomer

This topic is 4512 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Let's say I am using SDL_gfx's rotozoomer to rotate a surface 90 degrees every second:
[source lang = "cpp]
SDL_Surface* newSurface = oldSurface;
for(;;)
{
SDL_Delay(1000);
newSurface = rotozoomSurface(newSurface, 90, 1, 0);
Draw(newSurface);
FlipScreen();

Every time I call rotozoom, it moves the image down & right by a pixel or two (or three, maybe). I've tried rotating it by 360 degrees, and it does the same thing. Am I doing something wrong, or is it just because rotatations are supposed to all be based of of 1 source image, so the moving is normally not noticable?

Share this post


Link to post
Share on other sites
Advertisement
No, you're not doing anything wrong. The rotozoomer seems optimized for speed not quality so this is what you get. Try turning off smoothing if you have it enabled, I believe this should fix the skew.

Or you could write your own routine fixed to 90/180/270 degrees. The pseudo code below should rotate by 90 degrees (very innefficient of course)


for(y=0; y<src->h; y++)
for(x=0; x<src->w; x++)
if(0 == SDL_GetPixel(src, x, y, &pixel))
SDL_PutPixel(dest, src->h-1-y, x, pixel);


Share this post


Link to post
Share on other sites
You should find the center of the created surface and then match it with the center of the old surface. SOmething like this:

temp = rotozoomSurface(unit, unit_s->angle, 1, 1);

dest.x = (unit_s->x - (temp->w/2)); //get center of rotozoomed surface.
dest.y = (unit_s->y - (temp->h/2));
dest.w = temp->w;
dest.h = temp->h;

SDL_BlitSurface(temp, NULL, screen, &dest);


Check out the full source code http://gamescreators.sourceforge.net/downloads/demos.htm
(Rotozoom & all directions moving)

Share this post


Link to post
Share on other sites
A better solution would be to hold onto the original SDL_Surface, and then manipulate it when needed. This way you wouldn't get any distortion from odd rotations.

Share this post


Link to post
Share on other sites
First, you have a giant memory leak there. rotozoomSurface returns a pointer to a newly allocated surface, and you're throwing the pointer to your old surface away. Eventually, you'll run out of memory.

Second, artifacts introduced by the scaling and rotation will multiply each time you do it. To prevent that, rotate from the original image every time. Things could get pretty messy, I had a similar problem rotating polygons. I would rotate the set of verts every frame, but after a while, the polygons got all out of shape!

Third, to rotate by 90 degrees, you don't really need a rotozoomer. For a surface WxH, allocate a surface HxW, lock them both, read the pixels manually and write them into the new surface. Not that the rotozoomer won't work, but this just much simpler. Less unknowns == less headaches.

Share this post


Link to post
Share on other sites
Quote:
Original post by Rob Loach
A better solution would be to hold onto the original SDL_Surface, and then manipulate it when needed. This way you wouldn't get any distortion from odd rotations.


Yeah, I realized I should try that, and it's much better, but it still looks a little funky, like it keeps rotating on a different point.

Quote:
Original post by jonahrowley
First, you have a giant memory leak there. rotozoomSurface returns a pointer to a newly allocated surface, and you're throwing the pointer to your old surface away. Eventually, you'll run out of memory.


Well I actually have a wrapper Image class around my SDL_Surfaces which auto clears the memory and safe-copys surfaces, so when I quickly typed up this example (rather than put the actual code and the Image class code) I forgot to put the surface memory clearing thing.

Quote:
Original post by jonahrowley
Third, to rotate by 90 degrees, you don't really need a rotozoomer. For a surface WxH, allocate a surface HxW, lock them both, read the pixels manually and write them into the new surface. Not that the rotozoomer won't work, but this just much simpler.


Yeah, I was just putting an example.

Quote:
Original post by freenity
You should find the center of the created surface and then match it with the center of the old surface. SOmething like this:

temp = rotozoomSurface(unit, unit_s->angle, 1, 1);

dest.x = (unit_s->x - (temp->w/2)); //get center of rotozoomed surface.
dest.y = (unit_s->y - (temp->h/2));
dest.w = temp->w;
dest.h = temp->h;

SDL_BlitSurface(temp, NULL, screen, &dest);


Check out the full source code http://gamescreators.sourceforge.net/downloads/demos.htm
(Rotozoom & all directions moving)


So rotozoomSurface doesn't rotate by the center of the surface? Or am I not understnading?

Share this post


Link to post
Share on other sites
What do you mean by center? One in between pixels or one in the center of a pixel? A 3x3 surface would have a pixel center and a 4x4 surface would have a center in-between pixels. What are the dimensions of the surface your are rotating? Is the image drawn on the surface perfectly centered on that surface? For non-square surfaces are you applying the correct offset to blit with?

Good Luck.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!