float radians = (2*3.1416*angle)/360;
float cosine = (float)cos(radians);
float sine = (float)sin(radians);
int x1 = (int)(-m_imageheight * sine);
int y1 = (int)(m_imageheight * cosine);
int x2 = (int)(m_imagewidth * cosine - m_imageheight * sine);
int y2 = (int)(m_imageheight * cosine + m_imagewidth * sine);
int x3 = (int)(m_imagewidth * cosine);
int y3 = (int)(m_imagewidth * sine);
int minx = min(0,min(x1, min(x2,x3)));
int miny = min(0,min(y1, min(y2,y3)));
int maxx = max(x1, max(x2,x3));
int maxy = max(y1, max(y2,y3));
int w = maxx - minx;
int h = maxy - miny;
int xyoffet = (x + y * windowWidth);
int x10 = m_imagewidth/2;
int y10 = m_imageheight/2;
for( int y_ = (miny-y10); y_ <= (maxy-y10); y_++ )
{
for( int x_ = (minx-x10); x_ <= (maxx-x10); x_++ )
{
int sourcex = x_*cosine + y_*sine;
int sourcey = y_*cosine - x_*sine;
if( (sourcex + x10) >= 0 && (sourcex + x10) < m_imagewidth && (sourcey + y10) >= 0 && (sourcey + y10) < m_imageheight )
topleftimage[ (x_ + x10) + ((y_ + y10) * windowWidth) +xyoffet ] = imagepointer[ (sourcex+x10) + m_imagewidth * (sourcey+y10) ];
}
}
2D Image Rotation around origin
Hi, Sorry if this is in the wrong forum, it seemed the most appropriate.
I have a problem with my rotation which im stumped with. Im trying to rotate the image around its centre. The image rotates but the drawing area when rotated by so much cuts off the image :(. This can be seen in the image at the below link, when progressing to 90degree rotation the image is now not drawn :/.
Any help would be greatly appreciated.
The image is probably rotating fine, but it looks like you're not expanding or rotating the actual drawing surface for the image. Are you doing this in DirectX?
Its straight from source image data to screen data, not directx. I have seen a few methods similar and when trying them I also get the same problem.
If I'm right then your routine iterates the drawing area on a per pixel basis, computes where the pixel originates in the source image, and transfers that pixel. This is, in fact, the correct way of doing such things.
However, the extent of the drawing area is definitely given by the ranges of the both loops y_ and x_. Presumbly you want to iterate over the _whole_ drawing area.
EDIT: You're doing much "mysterious" calculations that look like optimizations to me. Perhaps you should go back to the roots by calculating the original pixel address in 1 step inside the loops e.g. by a combined affine transformation and look what happens if changing things. This would give you the flexibility of scaling and translation and non-center rotations all at once. Later then, with that understanding, start to optimize if necessary.
However, the extent of the drawing area is definitely given by the ranges of the both loops y_ and x_. Presumbly you want to iterate over the _whole_ drawing area.
EDIT: You're doing much "mysterious" calculations that look like optimizations to me. Perhaps you should go back to the roots by calculating the original pixel address in 1 step inside the loops e.g. by a combined affine transformation and look what happens if changing things. This would give you the flexibility of scaling and translation and non-center rotations all at once. Later then, with that understanding, start to optimize if necessary.
The drawing area within the loops appears to be correct on debuggin though which is whats annoying me.
EDIT: The method is described here
EDIT: The method is described here
I went back to basics and tried rotating around the top left 0,0 and the problem similar is in here also.
It is fine until 90 degrees in which the edges start to move in similar to the previous problem.
float radians = (2*3.1416*angle)/360; float cosine = (float)cos(radians); float sine = (float)sin(radians); int x1 = (-m_imageheight * sine); int y1 = (m_imageheight * cosine); int x2 = ((m_imagewidth * cosine) - (m_imageheight * sine)); int y2 = ((m_imageheight * cosine) + (m_imagewidth * sine)); int x3 = (m_imagewidth * cosine); int y3 = (m_imagewidth * sine); int minx = min(0,min(x1, min(x2,x3))); int miny = min(0,min(y1, min(y2,y3))); int maxx = max(x1, max(x2,x3)); int maxy = max(y1, max(y2,y3)); int w = maxx - minx; int h = maxy - miny; int xyoffet = (x + y * windowWidth); for( int y_ = miny; y_ < maxy; y_++ ) { for( int x_ = minx; x_ < maxx; x_++ ) { int sourcex = x_*cosine + y_*sine; int sourcey = y_*cosine - x_*sine; if( sourcex >= 0 && sourcex < m_imagewidth && sourcey >= 0 && sourcey < m_imageheight ) topleftimage[x_+(y_*windowWidth)+xyoffet] = imagepointer[sourcex+(m_imagewidth*sourcey)]; } }
Here's some SDL code I came up with a while back for an Asteroids clone I am/was working on:
I'm pretty sure I simply glued together two rotation algorithms I found, but I can't remember which ones.
Off-topic, but does anyone know why my code is double-spaced? It looks fine on my system, but gdnet seems to mangle it somehow.
Oops, forgot usage. Make sure dstrect is large enough to contain your rotated sprite, otherwise it will clip to dstrect as in your screenshots.
EDIT: Fixed code spacing.
[Edited by - GenPFault on August 19, 2007 10:17:23 AM]
void RotBlitSurface(SDL_Surface* src, SDL_Rect* srcrect, SDL_Surface* dst, SDL_Rect* dstrect, int angle){ double cosT, sinT; double radangle = angle * (3.141592654 / 180.0); cosT = cos(radangle); sinT = sin(radangle); // fix alignment on cardinal directions if(angle == 0) { cosT = 1; sinT = 0; } if(angle == 90) { cosT = 0; sinT = 1; } if(angle == 180) { cosT = -1; sinT = 0; } if(angle == 270) { cosT = 0; sinT = -1; } // center of rotation int x1p = srcrect->w/2 + srcrect->x; int y1p = srcrect->h/2 + srcrect->y; // blit position int x1 = dstrect->x + dstrect->w/2; int y1 = dstrect->y + dstrect->h/2; // destination area (clipped to dst surface) int min_x = max(dstrect->x, (Sint16)0); // cast to shut up gcc/STL int max_x = min(min_x+dstrect->w, dst->w); int min_y = max(dstrect->y, (Sint16)0); int max_y = min(min_y+dstrect->h, dst->h); Uint32* s = (Uint32*)src->pixels; Uint32* d = (Uint32*)dst->pixels; Uint32 color; double xp, yp; for(int y = min_y; y < max_y; y++) { xp = (min_x-x1)*cosT + (y-y1)*sinT + x1p; yp = (y-y1)*cosT - (min_x-x1)*sinT + y1p; for(int x = min_x; x < max_x; x++) { if(xp >= srcrect->x && yp >= srcrect->y && xp < srcrect->x+srcrect->w && yp < srcrect->y+srcrect->h) { color = s[(int)xp+(int)yp*src->w]; if(color != src->format->colorkey) d[x+y*dst->w] = color; } xp += cosT; yp -= sinT; } }}
I'm pretty sure I simply glued together two rotation algorithms I found, but I can't remember which ones.
Off-topic, but does anyone know why my code is double-spaced? It looks fine on my system, but gdnet seems to mangle it somehow.
Oops, forgot usage. Make sure dstrect is large enough to contain your rotated sprite, otherwise it will clip to dstrect as in your screenshots.
EDIT: Fixed code spacing.
[Edited by - GenPFault on August 19, 2007 10:17:23 AM]
Quote:Original post by GenPFaultIt's probably related to line endings. I'd guess you are on a mac, which has line endings in the opposite order as windows (one is CR LF the other LF CR) and the way GDNet copes with "broken"(since it's made for windows probably) line endings ends up expanding mac line endings to two HTML line endings.
[...]Off-topic, but does anyone know why my code is double-spaced? It looks fine on my system, but gdnet seems to mangle it somehow.[...]
Quote:Original post by ExtrariusQuote:Original post by GenPFaultIt's probably related to line endings. I'd guess you are on a mac, which has line endings in the opposite order as windows (one is CR LF the other LF CR) and the way GDNet copes with "broken"(since it's made for windows probably) line endings ends up expanding mac line endings to two HTML line endings.
[...]Off-topic, but does anyone know why my code is double-spaced? It looks fine on my system, but gdnet seems to mangle it somehow.[...]
Linux, actually. Copy-pasted out of gedit, so it's probably just LF's. Weird. Thanks for the heads-up though.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement