How to update the "forward" movement in OpenGL

1.4k views Asked by At

I have a problem with my OpenGL application that you can clearly see in this gif. Basically I would like to move in the direction pointed by the cursor, but this doesn't happen and instead the "forward" direction remains the same.

For example if I turn 180° and press "w" to walk forward, I walk backwards instead. I'm talking about walking because I'm trying to replicate a first-person camera, like in a FPS game.

Down here you can see the code I've written so far:

#include <GL\glew.h>
#include <GL\freeglut.h>
#include <iostream>
#include <cstdlib>
#include "imageLoader.h"

using namespace std;

float _angleY = 0.0f;
float _angleX = 0.0f;
bool about_y = true;

float oldMouseX;
float oldMouseY;

int valid = 0;

float posX = 0.0;
float posZ = 0.0;

// actual vector representing the camera's direction
float lx = 0.0f, lz = -1.0f;

// XZ position of the camera
float x = 0.0f, z = 5.0f;

// the key states. These variables will be zero
// when no key is being presses
float deltaAngle = 0.0f;
float deltaMove = 0;

int xOrigin = -1;

// angle of rotation for the camera direction
float angle = 0.0f;

void mouseMove(int x, int y) {
    // this will only be true when the left button is down
    if (xOrigin >= 0) {

        // update deltaAngle
        deltaAngle = (x - xOrigin) * 0.001f;

        // update camera's direction
        lx = sin(angle + deltaAngle)*2;
        lz = -cos(angle + deltaAngle)*2;
    }
}

void mouseButton(int button, int state, int x, int y) {
    // only start motion if the left button is pressed
    if (button == GLUT_LEFT_BUTTON) {
        // when the button is released
        if (state == GLUT_UP) {
            angle += deltaAngle;
            xOrigin = -1;
        }
        else  {// state = GLUT_DOWN
            xOrigin = x;
        }
    }
}

void handleKeys(unsigned char key, int x, int y){
    switch (key)
    {
        case 'w':
            posZ+=4;
            cout << "FORWARD\n";
            break;
        case 's':
            posZ-=4;
            cout << "BACK\n";
            break;
        case 'd':
            posX-=4;
            cout << "RIGHT\n";
            break;
        case 'a':
            posX+=4;
            cout << "LEFT\n";
            break;
        case 27:
            exit(0);
            break;
    }
}

//initializes 3d rendering 
void initRendering(){
    glEnable(GL_DEPTH_TEST); //permits one object to show up behind another one
    glEnable(GL_COLOR_MATERIAL); 
    glEnable(GL_LIGHTING); //enables the lighting function
    glEnable(GL_LIGHT0);   //enables light num. 1
    glEnable(GL_LIGHT1);   //enables light num. 2
    glEnable(GL_NORMALIZE); 
    Image* image = loadBMP("bricks.bmp");
    _textureId = loadTexture(image);
    delete image;
}

//handles the resize of the window
void handleResize(int w, int h){
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0, double(w) / double(h), 1.0, 800.0);
}

void computePos(float deltaMove) {
    x += deltaMove * lx * 0.1f;
    z += deltaMove * lz * 0.1f;
}

//draws the 3D sccene
void drawScene(){
    cout << "ANGLE: "<<angle<<"\n";
    if (deltaMove){
        computePos(deltaMove);
    }

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    // Set the camera
    gluLookAt(x, 1.0f, z,
        x + lx, 1.0f, z + lz,
        0.0f, 1.0f, 0.0f);

    glTranslatef(posX, 0.0f, posZ);

    //HERE WE ADD THE AMBIENT LIGHT
    GLfloat ambientColor[] = { 0.3f, 0.3f, 0.3f, 1.0f }; //the first 3 floats represent the                                                      //RGB intensity of the light 
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientColor);

    //HERE WE ADD THE POSITIONED LIGHT (WHITE INTENSE)
    GLfloat lightColor0[] = { 0.5f, 0.5f, 0.5f, 1.0f }; //LIGHT0 color
    GLfloat lightPos0[] = { 4.0f, 0.0f, 8.0f, 1.0f };   //LIGHT0 position is (4,0,8)
    glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor0); //sets color/intensity of the light
    glLightfv(GL_LIGHT0, GL_DIFFUSE, lightPos0);   //sets position of the light

    //HERE WE ADD THE DIRECTIONAL LIGHT (RED)
    GLfloat lightColor1[] = { 0.5f, 0.2f, 0.2f, 1.0f }; //LIGHT1 color
    GLfloat lightPos1[] = { -1.0f, 0.5f, 0.5f, 0.0f };  //LIGHT1 is coming from (-1,0.5,0.5)
                                                        //NOTE: we just have to put the 4th 
                                                        //parameter to 0.0f to make it directional

    glLightfv(GL_LIGHT1, GL_DIFFUSE, lightColor1); //sets color/intensity of the light
    glLightfv(GL_LIGHT1, GL_DIFFUSE, lightPos1);   //sets position of the light

    glColor3f(1.0f, 1.0f, 0.0f); //we set the cube color

    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, _textureId);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    //HERE WE DEFINE COORDINATES FOR THE CUBE
    glBegin(GL_QUADS);

    //Front
    glNormal3f(0.0f, 0.0f, 1.0f);
    glTexCoord2f(0.0f, 0.0f);
    glVertex3f(-40.5f, -40.0f, 40.5f);
    glTexCoord2f(1.0f, 0.0f);
    glVertex3f(40.5f, -40.0f, 40.5f);
    glTexCoord2f(1.0f, 1.0f);
    glVertex3f(40.5f, 40.0f, 40.5f);
    glTexCoord2f(0.0f, 1.0f);
    glVertex3f(-40.5f, 40.0f, 40.5f);

    //Right
    glNormal3f(1.0f, 0.0f, 0.0f);
    glTexCoord2f(0.0f, 0.0f);
    glVertex3f(40.5f, -40.0f, -80.5f);
    glTexCoord2f(0.0f, 1.0f);
    glVertex3f(40.5f, 40.0f, -80.5f);
    glTexCoord2f(1.0f, 1.0f);
    glVertex3f(40.5f, 40.0f, 40.5f);
    glTexCoord2f(1.0f, 0.0f);
    glVertex3f(40.5f, -40.0f, 40.5f);

    //Back
    glNormal3f(0.0f, 0.0f, -1.0f);
    glTexCoord2f(0.0f, 1.0f);
    glVertex3f(-40.5f, -40.0f, -80.5f);
    glTexCoord2f(0.0f, 0.0f);
    glVertex3f(-40.5f, 40.0f, -80.5f);
    glTexCoord2f(1.0f, 0.0f);
    glVertex3f(40.5f, 40.0f, -80.5f);
    glTexCoord2f(1.0f, 1.0f);
    glVertex3f(40.5f, -40.0f, -80.5f);

    //Left
    glNormal3f(-1.0f, 0.0f, 0.0f);
    glTexCoord2f(0.0f, 0.0f);
    glVertex3f(-40.5f, -40.0f, -80.5f);
    glTexCoord2f(1.0f, 0.0f);
    glVertex3f(-40.5f, -40.0f, 40.5f);
    glTexCoord2f(1.0f, 1.0f);
    glVertex3f(-40.5f, 40.0f, 40.5f);
    glTexCoord2f(0.0f, 1.0f);
    glVertex3f(-40.5f, 40.0f, -80.5f);

    glEnd();

    glutSwapBuffers();
}

//main loop of the program
void update(int value){
    glutPostRedisplay();
    glutTimerFunc(25, update, 0);
}
1

There are 1 answers

0
outoftime On BEST ANSWER

You should create vector of direction. Every time you move your mouse, you should reevaluate it according to angle. Directional vector should be vector on unit circle.

Suppose you have directional vector direction = (0.4X, 0.6Z) (numbers can be unreal but let it be for example), then for moving forward you should multiply it by scalar of velocity = 4, so vector velocity = (1.6X, 2.4Z). Which mean posX += 1.6, posZ += 2.4;

If you need to go right, rotate it on 90 degrees and multiply on velocity scalar.

To rotate directional vector you can use sin and cos of function as it is location on unit circle.

To move backward and left you can use negative velocity.