2D rotation

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

Recommended Posts

Alright, I know this must have been asked a million times before ( in fact, I even found quite some threads ), but I can't find anything that clarifies things for my particular problem. Visualisation of the problem: As I'm making a small 2D game with SDL I aim to make a rotation function for surfaces in SDL. To do this I use a temporary SDL_Surface to which the rotated surface should be written. From another thread and some googling I found out that to calculate the temporary surface's height and width all I had to do was:
tempwidth = orig_height * sin(angle) + orig_width * cos(angle)
tempheight = orig_height * cos(angle) + orig_width * sin(angle)
So I used this to create the new surface, and the next thing I need to do is to rotate all pixels from the original surface to their rotated positions on the temporary surface. Then, I found that to rotate a single pixel I needed to use the following formula:
x' = cos(theta)*x - sin(theta)*y
y' = sin(theta)*x + cos(theta)*y
It seems, however, that this rotation rotates around the origin (0,0) whereas my surface's 0,0 position is the top left. In short, I'm a bit lost as to how I should actually implement the rotation in my code and I hope someone can help me out. This is my function so far:
void Surface::Rotate ( int _angle )
{
// Add the rotation angle to the current rotation angle
rotationAngle += _angle;
if ( rotationAngle > 360 ) rotationAngle %= 360;

// Before we can 'create' the surface we must calculate its width and height.
int newWidth = ceil (  surface->h * sin ( (float)_angle ) + surface->w * cos ( (float) _angle ) );
int newHeight = ceil ( surface->h * cos ( (float)_angle ) + surface->w * sin ( (float) _angle ) );

// Since the masks in the createsurface function depend on the byte order, we
// have to check for it.
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
Uint32 rmask = 0x00000000;
Uint32 gmask = 0x00000000;
Uint32 bmask = 0x00000000;
Uint32 amask = 0x00000000;
#else
Uint32 rmask = 0x00000000;
Uint32 gmask = 0x00000000;
Uint32 bmask = 0x00000000;
Uint32 amask = 0x00000000;
#endif

// Create a black surface

// Lock the temporary surface so we can write on it
SDL_LockSurface ( temp );

// Get pixels and set them in the temporary surface at their newly calculated position
for ( int i = 0; i < surface->h; i++ )
{
for ( int j = 0; j < surface->w; j++ )
{
// This is where the implementation should come
// Help! :P
}
}

// Writing done, unlock the temporary surface
SDL_UnlockSurface ( temp );
}



Share on other sites
You can use SDL_gx library to rotate surfaces.

Share on other sites
Thanks for that suggestion. I'll be sure to check that library out - however, it still wouldn't hurt if I understood the underlying principles ;)

Share on other sites
To rotate about an arbitrary point, you need to use a conjugate-translation, to temporarily change the origin:

First of all, determine the coordinates of the point you wish to rotate around. Then transform your coordinates so that this point becomes the origin (simple translation), perform the rotation as before, then untransform the coordinates back. This is the common T' = Pˉ¹TP construct. The whole operation would look something like:
// Calulate dimensions of new canvasint tempwidth = (orig_height * sin(angle) + orig_width * cos(angle));int tempheight = (orig_height * cos(angle) + orig_width * sin(angle));// Caculate new originint i0 = tempwidth / 2;int j0 = tempheight / 2;for (int i = 0; i < tempwidth; ++i) {    for(int j = 0; j < tempheight; ++j) {        float x = (float) (i - i0); // Translate        float y = (float) (j - j0);        float rx = x*cos(-angle) - y*sin(-angle); // Rotate        float ry = x*sin(-angle) + y*cos(-angle);        rx += i0; // Untranslate        ry += j0;        if (rx < 0 || rx >= orig_width || ry < 0 || ry > orig_height) {            reult[i][j] = BACKGROUND_COLOUR;        } else {            result[i][j] = BilinearSample(rx, ry);        }    }}
I haven't tested this code, so proceed with due scrutiny.

Regards

Share on other sites
i know that:

x' = xcos(theta) - ysin(theta)
y' = xsin(theta) + ycos(theta)

but i'm not sure why it is:

x' = xcos(-theta) - ysin(-theta)
y' = xsin(-theta) + ycos(-theta)

in your code? could you explain please

thanks

Share on other sites
There is also the SDL_rotozoom, which enables you to rotate a sdl surface with ease.

http://www.ferzkopp.net/Software/SDL_rotozoom/

Share on other sites
Quote:
 Original post by JasonL220i know that:x' = xcos(theta) - ysin(theta)y' = xsin(theta) + ycos(theta)but i'm not sure why it is:x' = xcos(-theta) - ysin(-theta)y' = xsin(-theta) + ycos(-theta)in your code? could you explain please

Of course. I should have explained this in the first place.
The only difference between our formulas is that the sign of theta has been swapped. This corresponds to the inverse rotation. This is done because the code works in 'destination space' and calculates the coordinates in 'source space'. Intuitively, if we want to rotate the source by theta to get to the destination, then we'd equivalently need to rotate the destination by -theta to get to the source.
If the code was written the other way - mapping each pixel in the source to the appropriate position in the destination - (which, I'll add, is a bloody mess and should be avoided) then the rotation would go the other way and there's be no need to negate theta.

Regards

Share on other sites

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

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

• Forum Statistics

• Total Topics
628725
• Total Posts
2984407

• 25
• 11
• 10
• 16
• 14