Search code examples
opengllwjglglrotate

Rotating with glRotatef causes warping


I'm trying to rotate the image of a player to where they are pointing. Technically, this works fine. It rotates the image along the Z axis after transforming to the center, and then transforms back, no problem.

However, when this is rendered, as the angle points towards the wide sections of the window, the image gets squished, as if it was trying to normalize the image proportionally. If I set the resolution to a square (1080x1080, 1440x1440, etc) then it works fine, but any rectangle resolution that isn't a square will have it's player image warped.

I originally had this same problem when trying to get the environment to rotate about the x/y coordinates of the player, but this was solved with setting glViewport to a square.

glViewport(0,0,width,width);

Warped when rotated 90 degrees

Normal when not rotated.

these effects mirror for 270 degrees and 180 degrees respectively, and gradually go between each other for all other angles.

Code for Player.render()

glPushMatrix();
    glTranslatef(
        x/Main.width*2,
        y/Main.height*2,
        0);
    glRotatef((float)angle,0f,0f,1f);
    glTranslatef(
        -x/Main.width*2,
        -y/Main.height*2,
        0);
    drawTexture(t,x-w/2,y-w/2,w,w); //t = texture, w = width in pixels for texture to be mapped to
glPopMatrix();

And the drawTexture method:

public static void drawTexture(Texture in,float x, float y,float w, float h) {
    //Main.width and Main.height are the window window width and height.
    float nx = x*2/Main.width;
    float ny = y*2/Main.height;
    float nw = w*2/Main.width;
    float nh = h*2/Main.height;

    in.bind(0); 

    glTexEnvf(GL_TEXTURE_2D,GL_TEXTURE_ENV_MODE,GL_MODULATE);
    glDepthMask(false);
    glEnable(GL_BLEND);

    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
    glColor4f(1.0f,1.0f,1.0f,1.0f);

    glBegin(GL_QUADS);
        glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
        glTexCoord2f(0, 1);
        glVertex2f(nx,ny);
        glTexCoord2f(1, 1);
        glVertex2f(nx+nw,ny);
        glTexCoord2f(1, 0);
        glVertex2f(nx+nw,ny+nh);
        glTexCoord2f(0, 0);
        glVertex2f(nx,ny+nh);
    glEnd();


    glDisable(GL_BLEND);
    glDepthMask(true);   

}

Not exactly sure where to go to try and resolve this issue, my own research into others that apparently have not had this problem has just resulted in hair loss. If more code is needed or more images, trust me I'll be at my knees for assistance.


Solution

  • And at a lovely 5:30 in the morning, I figured it out.

    Fixed code for the player rendering turned out to be

        glPushMatrix();
            glTranslatef(
                    x/Main.width*2,
                    y/Main.height*2,
                    0);
            glScalef(1f,(float)Main.width/Main.height,1f);
            glRotatef((float)angle,0f,0f,1f);
            glScalef(1f,(float)Main.height/Main.width,1f);
            glTranslatef(
                    -x/Main.width*2,
                    -y/Main.height*2,
                    0);
            drawTexture(t,x-w/2,y-w/2,w,w);
        glPopMatrix();
    

    (note the addition of the scaling functions around the rotations). Those had to be added because I added another scale function at the beginning of each frame that scaled everything to look normal at all resolutions:

            glScalef(1f,(float)Main.height/Main.width,1f);
    

    because otherwise it would treat 300 pixels of width as 169 pixels in height, due to the way that LWJGL takes proportional float arguments (-1f to +1f in both directions, this scaling function changes that to -1f to +1f in height, and -1.78f to +1.78f in width at a 16:9 aspect ratio. This made the texture map weirdly when it was rotated, so if I scale it by the opposite factor to get it to 1:1, rotate, then scale back to get to scaled ratios then all is well.

    Hopefully my explanation is understandable enough. First time playing around with this, so live and learn.