2
\$\begingroup\$

How can you rotate a quad around its center?

This is what I am trying to do but it is not working:

    GL11.glTranslatef(x-getWidth()/2, y-getHeight()/2, 0);      
    GL11.glRotatef(30, 0.0f, 0.0f, 1.0f);
    GL11.glTranslatef(x+getWidth()/2, y+getHeight()/2, 0);  
        DRAW

my main problem is that it renders it off the screen..

draw code:

    GL11.glBegin(GL11.GL_QUADS);
    {
        GL11.glTexCoord2f(0, 0);
        GL11.glVertex2f(0, 0);
        GL11.glTexCoord2f(0, getTexture().getHeight());
        GL11.glVertex2f(0, height);
        GL11.glTexCoord2f(getTexture().getWidth(), getTexture().getHeight());
        GL11.glVertex2f(width,height);
        GL11.glTexCoord2f(getTexture().getWidth(), 0);
        GL11.glVertex2f(width,0);
    }
    GL11.glEnd();
\$\endgroup\$
  • \$\begingroup\$ That looks mostly correct except that the first translation needs to be negated ie GL11.glTranslatef(-(x-getWidth()/2), -(y-getHeight()/2), 0); \$\endgroup\$ – Michael Slade Nov 16 '12 at 13:44
  • \$\begingroup\$ doesn't work it renders it somewhere off the screen \$\endgroup\$ – Trixmix Nov 16 '12 at 13:52
  • \$\begingroup\$ Michael Slade comments seems right, but just remove the parenthesis. Like: GL11.glTranslatef(-x-getWidth()/2, -y-getHeight()/2, 0); \$\endgroup\$ – Allan Hasegawa Nov 16 '12 at 15:10
2
\$\begingroup\$

The quad's center is the position (0, 0, 0) in local space. Local space is the space in which you define your vertex positions.

For instance, if you draw your quad using the opengl glvertex* commands, you should specify each vertex relative to (0, 0, 0):

glBegin(GL_QUADS);                  // Draw A Quad
glVertex3f(-1.0f, 1.0f, 0.0f);      // Top Left
glVertex3f( 1.0f, 1.0f, 0.0f);      // Top Right
glVertex3f( 1.0f,-1.0f, 0.0f);      // Bottom Right
glVertex3f(-1.0f,-1.0f, 0.0f);      // Bottom Left
glEnd();                            // Done Drawing The Quad

The code was taken from the NeHe website: Your First Polygon

If you draw your quad like this, each rotate command will rotate the quad around it's center. That's because the rotation matrix will be multiplied with each vertex position, which will result in the vertex being rotated around (0, 0, 0).

You should have a look at the NeHe article, it's a good starting point. Also have a look at the other articles there: http://nehe.gamedev.net/tutorial/lessons_01__05/22004/ ( there's one dealing with rotations in particular ).

EDIT:

You're drawing the quad relative to the lower left corner, so in order to match the center of the quad with the object space origin, you should first translate it by ( -width()/2, -height()/2, 0 ). Keeping in mind that matrices are multiplied in the reverse order, I would try something like:

GL11.glTranslatef(x+getWidth()/2, y+getHeight()/2, 0); // M1 - 2nd translation
GL11.glRotatef(30, 0.0f, 0.0f, 1.0f);                  // M2
GL11.glTranslatef( -getWidth()/2, -getHeight()/2, 0);  // M3 - 1st translation

Matrices are multiplied in order, and then multiplied on the left side with the vertex. So the resulting formula would be M1 * M2 * M3 * V. Notice that V is first multiplied by M3, so that's the matrix we use to translate the quad into the origin.

\$\endgroup\$
1
\$\begingroup\$

I'm not sure what x & y do in your code, you just need;

GL11.glTranslatef(-getWidth()/2, -getHeight()/2, 0);      
GL11.glRotatef(30, 0.0f, 0.0f, 1.0f);
GL11.glTranslatef(+getWidth()/2, +getHeight()/2, 0);  
    DRAW

Looking at your drawing code, the centre of the quad seems to be [getWidth()/2, getHeight()/2], so you need to translate the centre to the origin, rotate, and translate back again

\$\endgroup\$
0
\$\begingroup\$

If you don't want to use glRotatef(), you can use this method with x,y the coordinates of quad(top-left) and sx : the weight and sy : the height.

rotation+=45;
double rot = Math.toRadians(rotation);
double rot2 = Math.toRadians(rotation+90);
double rot3 = Math.toRadians(rotation+180);
double rot4 = Math.toRadians(rotation+270);

float cx = x+sx/2;
float cy = y+sy/2;

float x1 = cx-(float)Math.cos(rot)*sx;
float y1 = cy-(float)Math.sin(rot)*sy;

float x2 = cx-(float)Math.cos(rot2)*sx;
float y2 = cy-(float)Math.sin(rot2)*sy;

float x3 = cx-(float)Math.cos(rot3)*sx;
float y3 = cy-(float)Math.sin(rot3)*sy;

float x4 = cx-(float)Math.cos(rot4)*sx;
float y4 = cy-(float)Math.sin(rot4)*sy;

GL11.glBegin(GL11.GL_QUADS);
    GL11.glTexCoord2f(0f, 0f);  GL11.glVertex2f(x1, y1);
    GL11.glTexCoord2f(1f, 0f);  GL11.glVertex2f(x2, y2);
    GL11.glTexCoord2f(1f, 1f);  GL11.glVertex2f(x3, y3);
    GL11.glTexCoord2f(0f, 1f);  GL11.glVertex2f(x4, y4);    
GL11.glEnd();   
\$\endgroup\$
  • 2
    \$\begingroup\$ This is a little wasteful, since you compute the same two values 8 times combined. cos(rot2) = -sin(rot) and sin(rot2) = cos(rot) and this pattern repeats for the rest. So you can cut your trig operations down to a quarter of what you have here. \$\endgroup\$ – DMGregory May 31 '17 at 19:40
  • \$\begingroup\$ You only need to calculate the position of the top right vertex. The other three vertices can be derived by negating and swapping coordinates (much faster than computing cos and sin). You also need to multiply the top right vertex by sqrt(2) or your quad will be slightly smaller than it should be. Imagine a right angled triangle where the two side lengths are 1. The hypotenuse would be sqrt(2). \$\endgroup\$ – Indiana Kernick May 4 '18 at 23:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.