[ SDL2 – Part 8 ] Image rotation

Introduction


In the last tutorial we learned how to load and render png files with alpha layers. This time we’re gonna dive into rotating textures.  Or more precisely ; rendering them rotated.

 

Today we’ll be making a simple, but working, analog clock. This will show how to rotate textures in SDL2. We’ll also improve how we represent textures

SDL_RenderCopyEx


Until now, we have been rendering using SDL_RencerCopy. But in order to rotate, we need a different function ;  int SDL_RenderCopyEx it takes a couple more arguments. I’ll try to explain all of them.

Parameters :

  • renderer – the SDL_Renderer we always use for rendering
  • texture  – the SDL_Texture we want to render
  • srcrect  – which part of the SDL_Texture to render. null for everything.
  • dstrect  – where to render it. Used exactly like in SDL_RenderFillRect)
  • angle     – angle of rotation
  • center    – the center of rotation
  • flip      – flipping of texture ( vertical, horizontal, no flip )

Return value

  • 0 on success

As you can see, the first four parameters are identical to SDL_RenderCopy you can read more about them in part 6.

Texture flip


Texture flip is represented as an SDL_TextureFlip

It is simply an enum with the following three values :

  • SDL_FLIP_NONE         – don’t flip at all
  • SDL_FLIP_HORIZONTAL   – flip horizontaly
  • SDL_FLIP_VERTICAL     – flip vertically

For now, we will just be using SDL_FLIP_NONE.

Center of rotation


The center of rotation is given as a position seen from the top-left of the texture ( remember; in SDL 0,0 is the top-left of a texture. ) If the center of rotation is 0,0 you rotate it from the top-left corner.

Finding the center of rotation is usually quite simple, it’ll usually just be the center of the texture you are using. For a circle, like a spinning wheel, the center of rotation will simply be the center of the wheel. Or for a Tetris piece it will be the center of the Tetros piece. The center of a texture is easy to find. Since a center of any rectangle will be halfway along its x axis and halfway along its y axis, the position can be calculate as follows ;

The type of center is one we haven’t used before, SDL_Point. But an SDL_Point is simply just a struct with an x and y value.

In our case we are going to make a working analog wall clock. So we can’t rotate it around the middle ( that would be a weird clock! ) What we need to do, is find the base of the hands ( where they connect to the center of the clock )

Here is a picture of on our clock hands. The white hole in the middle is where we want the center of rotation to be. All three hands look very similar to this, all hands have a hole in the base, and all of them rotate around that point.

If you look closely at the green dots, you’ll see that the distance to the hole from either of the sides and the bottom is all the same ( three green dots. ) The green dots span the entire width of the base. So to find the center x value, we simply take half of the width. Looking at the picture, you’ll see that the distance from the bottom to the hole is the same as the distance from the sides subtract half of the width to find the y position of the hole.

So the code for finding the center of rotation will be as follows:

Putting things together


Previously we have worked with simply storing the SDL_Texture and SDL_Rect as separate objects in our main.cpp. But now we also need to store the center of rotation and the angle. So that’s four variables for each texture. With so many variables, it’s a good idea to split it into a separate struct :

We also need to change main.cpp to make the clock work :

As you can see, there is very little code needed in main since a lot of it is moved into Texture.h

Conclusion


The SDL_RenderCopyEx function can be very useful and is a very simple way of rotating textures. An by wrapping the SDL_Texture in a separate struct we can make the remaining code smaller and simpler while still keeping all the functionality we need.

The full code can be downloaded here.


Feel free to comment if you have anything to say or ask questions if anything is unclear. I always appreciate getting comments.

You can also email me : olevegard@headerphile.com

2 thoughts on “[ SDL2 – Part 8 ] Image rotation”

  1. Perhaps you want to include a note in your code for Visual Studio users, when dealing with time.

    Basically the compiler will complain about the “localtime(&timeEpoch);”, it’s deprecated, unsafe, the world will end today, bla, bla.

    It can be replaced with:

    tm* tmCurrent = new tm; // create instance to avoid more vs complaints
    localtime_s(tmCurrent, &timeEpoch); // convert time to tm

    with no further changes in the code.

    I’m following your tutorials, slowly, understanding SDL2 functions and the underlying structure in your code, just to grab a general idea. I’m using VS2013 and not a 1900×1200 screen resolution (smaller) so I need to modify the code sometimes to adjust it. So surely you can expect more comments from me, only when I think they are relevants.

    1. Hei 🙂

      I’ll try changing it to fix the issue next time I’m on Windows. I don’t think it’s too important if the compilation still succeeds, since I’m using the std chrono library in later posts.

      Feel free to post as many as you like, I’m always looking to improve my posts.

Leave a Reply

Your email address will not be published. Required fields are marked *