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);
}
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 ofvelocity = 4
, so vectorvelocity = (1.6X, 2.4Z)
. Which meanposX += 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
andcos
of function as it is location on unit circle.To move backward and left you can use negative velocity.