2
votes

Long story short, I'm making an LWJGL engine, and am drawing a basic QUAD. When I draw this QUAD and use the Keyboard listener, it moves perfectly, up/down/left/right.

When I translate and rotate however, it also pivots around its center point just fine, use both of them together, and then you have a problem. Rotation starts to go off axis, and everytime you move, you pivot around a strange point somewhere else.

How can I make it so I can move the QUAD (not relative to rotation), aswell as rotate it?

Edit 1

I have found out that a major problem with this QUAD, is that when I goto rotate it, my entire screen, (text included) rotates...

My current results:

Before Movement Before movement.

After Movement (Hopefully you notice that it moved in a circle, instead of just LEFT when I move LEFT.) After Movement.

Code:

(Display Setup)

try {
    Display.setDisplayMode(new DisplayMode(width, height));
    Display.setVSyncEnabled(vsync);
    Display.create();
    open = true;

    GL11.glMatrixMode(GL11.GL_PROJECTION);
    GL11.glLoadIdentity();
    // Sets (0, 0) to the top left corner.
    GL11.glOrtho(0, this.width, this.height, 0, 1, -1);
    GL11.glMatrixMode(GL11.GL_MODELVIEW);
} catch (LWJGLException e) {
    e.printStackTrace();
}

(Keyboard listener)

public void userLogic() {
    if (keyboard.isKeyDown(Keyboard.KEY_A)) {
        rect.setLocation(rect.x - 1, rect.y, rect.width, rect.height);
        rect.setRotation(-1);
    } else if (keyboard.isKeyDown(Keyboard.KEY_D)) {
        rect.setLocation(rect.x + 1, rect.y, rect.width, rect.height);
        rect.setRotation(1);
    } if (keyboard.isKeyDown(Keyboard.KEY_W)) {
        rect.setLocation(rect.x, rect.y - 1, rect.width, rect.height);
    } else if (keyboard.isKeyDown(Keyboard.KEY_S)) {
        rect.setLocation(rect.x, rect.y + 1, rect.width, rect.height);
    }
}

(Movement/Rotation Logic)

public void setRotation(float degrees) {
    // TODO: Fix whatever the hell the problem is here.
    GL11.glTranslatef(x + (width / 2), y/* + (height / 2)*/, 0);
    GL11.glRotatef(degrees, 0f, 0f, 1f);
    GL11.glTranslatef(-(x + (width / 2)), -(y/* + (height / 2)*/), 0);
}

public void setLocation(int x, int y, int width, int height) {
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
}

(Drawing the QUAD, (detached from rest of the rendering process))

public void render() {
    switch(type) {
    case IMAGE:
        // Not ready yet.
        break;
    case TRIANGLE:
        // Not ready yet.
        break;
    case RECTANGLE:
        GL11.glColor3f(colour.red, colour.green, colour.blue);

        // X, Y, WIDTH, HEIGHT are the QUADS coords, not the displays or anything else's.

        GL11.glBegin(GL11.GL_QUADS);
            GL11.glVertex2f(x, y);
            GL11.glVertex2f(x + width, y);
            GL11.glVertex2f(x + width, y + height);
            GL11.glVertex2f(x, y + height);
        GL11.glEnd();
        break;
    }
}

Any help will be gratefully appreciated, if you are going to downvote, please give a reason so I can improve this question, or even better, comment instead.

1

1 Answers

1
votes

The problem here is the order in which you call the translate and rotate functions of OpenGL in your setRotationfunction . The order of calling must be Translation(if any)-> Rotation(if any)->Scaling. You cannot change this order of calling or mix them up in anyway. Or else you'll not get the desired results. This is because the way in which these commands are processed internally by OpenGL.

Change your SetRotation function to

public void setRotation(float degrees) {
    // TODO: Fix whatever the hell the problem is here.
    GL11.glMatrixMode(GL11.GL_MODELVIEW);
    GL11.glLoadIdentity();
    GL11.glTranslatef(x , y , 0);       
    GL11.glRotatef(degrees, 0f, 0f, 1f);

}

You'll notice that if you add the lines

GL11.glTranslatef(x , y, 0);

underneath

GL11.glRotatef(degrees, 0f, 0f, 1f);

, the result will be completely different. Meaning the order is important.

There are some problems in the userLogic()function as well. In this case, you need to create a global variable to store rotation and then pass it to setRotation()

float rotValue = 0;
public void userLogic() {
    if (keyboard.isKeyDown(Keyboard.KEY_A)) {
        rect.setLocation(rect.x - 1, rect.y, rect.width, rect.height);
        rotValue-=.1f;
        rotValue=rotValue<0?rotValue+360:rotValue;
        rect.setRotation(rotValue);
    } else if (keyboard.isKeyDown(Keyboard.KEY_D)) {
        rect.setLocation(rect.x + 1, rect.y, rect.width, rect.height);
        rotValue+=.1f;
        rotValue=rotValue>=360?rotValue-360:rotValue;
        rect.setRotation(rotValue);
    } if (keyboard.isKeyDown(Keyboard.KEY_W)) {
        rect.setLocation(rect.x, rect.y - 1, rect.width, rect.height);
    } else if (keyboard.isKeyDown(Keyboard.KEY_S)) {
        rect.setLocation(rect.x, rect.y + 1, rect.width, rect.height);
    }
}

Finally inside the render() function, pass in vertices centered around (0,0). glTranslatef will take care of translation.

case RECTANGLE:
        GL11.glColor3f(colour.red, colour.green, colour.blue);
        GL11.glBegin(GL11.GL_QUADS);
        GL11.glVertex2f(-width/2, -height/2);
        GL11.glVertex2f(width/2, -height/2);
        GL11.glVertex2f(width/2, height/2);
        GL11.glVertex2f(-width/2, height/2);
        GL11.glEnd();
        GL11.glMatrixMode(GL11.GL_MODELVIEW); //resetting the rotation
        GL11.glLoadIdentity();  //and translation so that other
                                //objects are unaffected
            break;

Here is a simple lwjgl project I made showcasing translation and rotation of a quad and triangle https://gist.github.com/Coditivity/0eedc86447a509f6b5ef