Rotation of rectangular image causes distortion...

Started by overjag, October 16, 2014, 19:29:16

Previous topic - Next topic

overjag

Hi everybody,

I'm new here, so I hope this is the right place for asking this question. Of course I tried to solve the problem on my own, but I've spend now more than 8h and still don't know what Im doing wrong...

I'm trying to rotate a rectangular Slick2d image with pixel size 666 x 333 using LWJGL. I was able to rotate a square image with pixel size 666 x 666 around its center, but the rectangular image does distort during the rotation and this is my problem.

Here is the image I use for testing purposes:


The left window shows the image before the rotation, the right window shows the image how it looks when I rotate it 90 degrees, it's distorted:


Here is my source code snippet for the rotation:

float x = 0.335f;
float y = 0.335f;
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glTranslatef(x, y, 0f);
glRotatef(angle, 0f, 0f, 1f);
glTranslatef(-x, -y, 0f);
glMatrixMode(GL_MODELVIEW);


You may wonder why I don't use the function “setRotation” or “rotate” of a Slick2d Image. The reason I don't use this does not matter here, but I simply can't use it in my real project and furthermore I want to do it with gl.

It's the first time ever I touch LWJGL and Slick2d and I need it only for a small part of my project. If you know how to rotate the image like above without the distortion, please help me.
Thank you  :)

Cornix

Dont rotate the texture matrix.
If you want to rotate the shown picture then rotate your modelview matrix or change your vertices.

overjag

Thanks for your fast reply. You're right, the distortion is no longer there. Anyway I don't think I can use this. Let me explain (I tried to keep it as simple as possible but I need a little bit something else... sorry, I reduced the information level to much):

I have a image that is 666 x 333 pixels (in the original project the image is a bit bigger but that does not matter here). However, I use "getSubImage" because I only want to show an piece of that image. The sub-image is 200 x 200 pixels. Now I want that the user can "navigate", this means the user can change his "view" by using the keyboard and navigate up, down, left, right in the source image...

Now the user should also be able to rotate it. The result should be that the users still sees a 200x200 pixel image, but rotated without "losing" edges. Do you know what I mean? It's a bit hard the explain, I'm sorry.

When I use GL_MODELVIEW, the rotation workes without distortion but not like described above.

Do you have an idea how to realize this?

Here is my code:
img = fullImg.getSubImage(a, b, 200, 200); 
img.draw(50, 50); // img is the sub-image
float x = 0.335f;
float y = 0.335f;
glMatrixMode(GL_MODELVIEW); // glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glTranslatef(x, y, 0f);
glRotatef(angle, 0f, 0f, 1f);
glTranslatef(-x, -y, 0f);
glMatrixMode(GL_MODELVIEW);


Edit:
A possible solution could be to rotate the texture but in a way that prevents the distortion... is this possible?

Cornix

No, I am sorry, I do not understand what you mean.
Perhaps you could show pictures of what is currently happening (and you dont like) and what should be happening if everything was correct.

abcdef

Your 2 pictures in the first post don't quite show what you describe in your last post, this makes it quite hard to understand what your error is.

From your first post this is what I gleen..

You have a texture sub image of ration 1x1 (333x333)
It looks right not rotated and it looks right when its rotated, this is because the ratio 1x1 is a square

You also have a texture sub image of ratio 2x1 (666x333)
It looks ok not rotated but when rotated by 90 degrees it doesn't. The reason for this is your 2x1 ratio picture is now a 1x2 ratio picture but you are forcing this in to the same screen shape. This means the height has twice as many squares squashed in to the same space as before and the width has half as many squares stretched in to the same space.

What cornix told you to do was to rotate the model matrix rather than the texture matrix, this then rotates everything (including the screen shape) so it looks good. But you didn't want this as you want the screen shape to still be the same.

What I think you need to do is as follows :

Not grab a sub image, grab everything to be your texture
Use the UV coordinates to determine which bit of the image to draw
Keep with your texture matrix rotation.

Example, image is 1000x1000, you want a 666x333 chunk initially. UV coordinates - (0,0) (top left), (0,0.666) (top right), (0.333,0) (bottom left), (0.333,0.666) (bottom right) can be applied to a set of vertex. Then let opengl do its magic.

overjag

Ok, please let me describe (and show) what I need. Yes, this is different from the original post.

I have a image that looks like this (666 x 333 px):


I want that the user sees only a piece of that image. The user should see a 200 x 00 px section of the image at position 50, 50. Please look at this picture, so far everything is well:


To realize that, I'm using:
img = fullImg.getSubImage(a, b, 200, 200);

a and b is the position in the full image, with the keyboard the user can change this values to “navigate” in the full image. But this does not matter here and it works well. The user should also be able to use the keyboard to rotate the image view, the result of a 45 degree rotation and a 90 degree rotation should be like the following:


That's all I want.


But with my original code it does not work like wished, the red dot is still in the center (or nearly in the center), but the image distorts:


I've changed my code and used “GL_MODELVIEW”, now the rotation does not distort but it does not what I want (and it makes sense):


What is the best way to realize what I want?

Cornix

I do not know what your subimage method does, but I would suggest you do the following:
Enable clipping and set up a clipping area (glViewport) at the position you want your image to be displayed at.
Then render the image, a little bit bigger then what you originally wanted. Because of the clipping you will get the desired size and form.


abcdef

My suggestion is to take the who image and use texture coordinates to decide what to show. You can then rotate the texture coordinates around a chosen point to do the rotation effect

overjag

Ok, now I understand your idea (@Cornix) but it does not work for me. Instead, I want to go another direction, but this has not any longer much to do with the original question / problem at post no 1.

For my issue now I'll create a new thread.

Thanks