PDA

View Full Version : "Moving camera forward" relative to world rotation using gluLookAt()



Mr_Rockers
09-27-2015, 01:24 PM
I am a little bit stuck on a problem which I am guessing is a very n00bie problem.(?)
I am trying to move the camera forward (the world back) relative to the direction of the world. My problem is that I can only move the world forward, back, left and right (not relative to the camera...) so it is practically impossible to control.

Here is my code (It's crazy long for a code example and I'm sorry, but I have found that with openGL, everything is affected by everything else.)
Also, a few quick notes:


I rotated the world 180 degrees on the Y-Axis so that the camera would be facing the right way. Doing that reversed all of the controls however, so I reversed them again.
I am using SFML but I it bugged and didn't work the way it was supposed to (I'm using Code::Blocks... Of course nothing is going to work the first time) so I am using some GL Libraries mixed with some SFML OpenGL Libraries. This doesn't really affect the code though.
I was using a tutorial on a website called opengl-tutorial. I can't hyperlink it but it should be relatively easy to find. I was on beginners tutorials: 6 and it gave good information on how to rotate the "camera" like an FPS but not how to move forward based off of world rotation.




#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <SFML/System.hpp>
#include <SFML/OpenGL.hpp>
#include <GL/glu.h>
#include <iostream>
#include <math.h>

sf::RenderWindow window;

sf::Vector2i lastMousePosition, currentMousePosition;

sf::Vector3f crossProduct(sf::Vector3f a, sf::Vector3f b)
{
sf::Vector3f vecC;

vecC.x = (a.y * b.z) - (a.z * b.y);
vecC.y = (a.z * b.x) - (a.x * b.z);
vecC.z = (a.x * b.y) - (a.y * b.x);

return vecC;
}

void Initialize()
{
window.create(sf::VideoMode(800, 600), "SFML Game");
window.setVerticalSyncEnabled(true);
window.setMouseCursorVisible(false);

sf::Mouse::setPosition(sf::Vector2i(window.getSize ().x / 2, window.getSize().y / 2), window);
lastMousePosition = sf::Mouse::getPosition(window);

glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, window.getSize().x / window.getSize().y, 0.01, 500.0);
glMatrixMode(GL_MODELVIEW);
glRotatef(180.0f, 0.0f, 1.0f, 0.0f);
}

void Draw()
{
glBegin(GL_TRIANGLES);
{
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 2.0f, -5.0f);
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3f(-2.0f, -2.0f, -5.0f);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3f(2.0f, -2.0f, -5.0f);
}
glEnd();

glBegin(GL_QUADS);
{
glColor3f(0.5f, 0.5f, 0.5f);
glVertex3f(-2.0f, -2.0f, -5.0f);
glVertex3f(-2.0f, -2.0f, 5.0f);
glVertex3f(2.0f, -2.0f, 5.0f);
glVertex3f(2.0f, -2.0f, -5.0f);
}
glEnd();
}

bool running = true;
float axisVertical, axisHorizontal, camXPos, camZPos, mouseDifferenceX, mouseDifferenceY;
sf::Clock deltaClock;
sf::Time deltaTime;
int main()
{
Initialize();
while(running)
{
if(sf::Keyboard::isKeyPressed(sf::Keyboard::W))
{
axisVertical = -1;
}
else if(sf::Keyboard::isKeyPressed(sf::Keyboard::S))
{
axisVertical = 1;
}
else
{
axisVertical = 0;
}

if(sf::Keyboard::isKeyPressed(sf::Keyboard::D))
{
axisHorizontal = -1;
}
else if(sf::Keyboard::isKeyPressed(sf::Keyboard::A))
{
axisHorizontal = 1;
}
else
{
axisHorizontal = 0;
}

sf::Event event;
while(window.pollEvent(event))
{
switch(event.type)
{
case sf::Event::Closed:
running = false;
}
}

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClear(GL_COLOR_BUFFER_BIT);

deltaTime = deltaClock.restart();

currentMousePosition = sf::Mouse::getPosition(window);
mouseDifferenceX += (lastMousePosition.x - currentMousePosition.x) / 1000.0f;
mouseDifferenceY -= (lastMousePosition.y - currentMousePosition.y) / 1000.0f;

/*if(mouseDifferenceX > 360.0f)
{
mouseDifferenceX = 0.0f;
}
else if(mouseDifferenceX < 0.0f)
{
mouseDifferenceX = 360.0f;
}

if(mouseDifferenceY > 360.0f)
{
mouseDifferenceY = 0.0f;
}
else if(mouseDifferenceY < 0.0f)
{
mouseDifferenceY = 360.0f;
}*/

sf::Mouse::setPosition(sf::Vector2i(window.getSize ().x / 2, window.getSize().y / 2), window);
lastMousePosition = sf::Mouse::getPosition(window);

//Calculate Orientation
sf::Vector3f direction(cos(mouseDifferenceY) * sin(mouseDifferenceX),
sin(mouseDifferenceY),
cos(mouseDifferenceY) * cos(mouseDifferenceX));

sf::Vector3f right(sin(mouseDifferenceX - 3.14f / 2.0f),
0,
cos(mouseDifferenceX - 3.14f / 2.0f));

sf::Vector3f up(crossProduct(right, direction));

camXPos -= (axisHorizontal * deltaTime.asSeconds());
camZPos += (axisVertical * deltaTime.asSeconds());

sf::Vector3f position(camXPos, 0.0f, camZPos);

glPushMatrix();
gluLookAt(position.x, position.y, position.z, position.x + direction.x, position.y + direction.y, position.z + direction.z, up.x, up.y, up.z);

Draw();
glPopMatrix();

window.pushGLStates();

//GUI//
//Draw SFML
//window.draw(SFML Item To Draw);

window.popGLStates();

window.display();
}
return 0;
}


Any help is appreciated!

GClements
09-27-2015, 04:18 PM
I am a little bit stuck on a problem which I am guessing is a very n00bie problem.(?)

I am trying to move the camera forward (the world back) relative to the direction of the world. My problem is that I can only move the world forward, back, left and right (not relative to the camera...) so it is practically impossible to control.

gluLookAt() is the wrong tool for the job. Actually, the legacy OpenGL matrix functions in general are the wrong tool for the job. You should be constructing the matrix client-side and just using glLoadMatrix().

Essentially, what you want is


matrix = matrix * delta;
glLoadMatrix(inverse(matrix));

where delta is the matrix representing the motion relative to the camera's direction.

However, the need for an inverse can be avoided by using the fact that (A*B)-1 = B-1*A-1, so the above becomes


invmatrix = inverse(delta) * invmatrix;
glLoadMatrix(invmatrix);


But rather than generating delta and inverting it, you can just generate the inverse directly. So if delta is composed of a translation of (x,y,z) and a rotation of angle a, the inverse is a rotation of angle -a and a translation of (-x,-y,-z).

E.g.


static glm::mat4 invmatrix = glm::mat4(1.0);

void update(double move, double turn)
{
glm::mat4 r = glm::rotate(glm::mat4(1.0), -turn, glm::vec3(0.0,1.0,0.0));
glm::mat4 t = glm::translate(glm::mat4(1.0), glm::vec3(0.0,0.0,move));
invmatrix = r * t * invmatrix;
glLoadMatrixd(glm::value_ptr(invmatrix));
}