views:

49

answers:

1

My problem is related to getting the correct mouse co-ordinates from SFML while using OpenGL.

Basically I am making a polygon rotate on the Z axis to look at the current cursor position.

You can also move the polygon around the screen with the WASD keys.

If the polygon stays in the center of the screen everything works great, but my problems appear when I move the polygon to, for example, the top left of the screen.

Basically it is like it is getting the incorrect mouse co-ordinates and is overshooting the position of the actual mouse cursor.

I used GL_LINES to create a kind of crosshair to see where my variables thought the mouse cursor was, and it is overshooting the actual position.

To get the current mouse co-ordinates I am using this:

mouseX = Input.GetMouseX()-App.GetWidth()/2.f;
mouseY = Input.GetMouseY()-App.GetHeight()/2.f;

Does anybody know what my problem could be?

For the sake of providing all the information I can, below is my entire source code. Also, if I provide my source then for those who are interested in helping, you can compile it and see what I mean, since it is a bit hard for me to explain.

Sorry for it being so messy - I am new to this after all :)

#include <SFML/Window.hpp>
#include <iostream>
#include <cmath>

const float PI = 3.14159265f;

int main() {
    // Angle of rotation for the polygon
    float angle = 0.f;

    sf::Window App(sf::VideoMode(800, 600, 32), "SFML OpenGL");

    glClearDepth(1.f);
    glClearColor(0.f, 0.f, 0.f, 0.f);

    glEnable(GL_DEPTH_TEST);
    glDepthMask(GL_TRUE);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(90.f, 1.2f, 1.f, 500.f);

    // Current position of the polygon (used in glTranslatef)
    GLfloat currentPosX = 0.f;
    GLfloat currentPosY = 0.f;

    // Current position of the mouse cursor
    float mouseX = 0.f;
    float mouseY = 0.f;

    const sf::Input &Input = App.GetInput();

    App.SetFramerateLimit(30);

    while (App.IsOpened()) {
        sf::Event Event;
        while (App.GetEvent(Event)) {
            if (Event.Type == sf::Event::Closed) {
                App.Close();
            }
            if ((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::Escape)) {
                App.Close();
            }

            if (Event.Type == sf::Event::Resized) {
                glViewport(0, 0, Event.Size.Width, Event.Size.Height);
            }
        }

        App.SetActive();

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        if(Input.IsKeyDown(sf::Key::W)) {
            currentPosY += 3.f;
        }
        if(Input.IsKeyDown(sf::Key::S)) {
            currentPosY -= 3.f;
        }
        if(Input.IsKeyDown(sf::Key::D)) {
            currentPosX += 3.f;
        }
        if(Input.IsKeyDown(sf::Key::A)) {
            currentPosX -= 3.f;
        }

        // Minus half of the screen width and height
        // because the OpenGL origin is in the middle of the screen
        mouseX = Input.GetMouseX()-App.GetWidth()/2.f;
        mouseY = Input.GetMouseY()-App.GetHeight()/2.f;

        // I don't know any better way to flip the Y axis so this is what I did
        if(mouseY >= 0) {
            mouseY = -(mouseY);
        }
        else {
            mouseY = abs(mouseY);
        }

        // Calculate the angle which the polygon needs to rotate at
        angle = atan2(mouseY - currentPosY, mouseX - currentPosX)*180/PI;

        // Print variables to console to try and figure out what I'm doing wrong
        std::cout << mouseX << "(" << currentPosX << ")" << ", " << mouseY << "(" << currentPosY << ")" << " - " << angle <<  std::endl;

        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glTranslatef(currentPosX, currentPosY, -200.f);
        glRotatef(angle, 0.f, 0.f, 1.f);

        // Polygon
        glBegin(GL_QUADS);

            glVertex3f(-25.f, -25.f, -50.f);
            glVertex3f(25.f, -25.f, -50.f);
            glVertex3f(25.f, 25.f, -50.f);
            glVertex3f(-25.f, 25.f, -50.f);

        glEnd();

        glLoadIdentity();
        glTranslatef(currentPosX, currentPosY, -200.f);

        // Axis on polygon
        glBegin(GL_LINES);

            glVertex3f(-70.f, 0.f, -50.f);
            glVertex3f(70.f, 0.f, -50.f);

            glVertex3f(0.f, -70.f, -50.f);
            glVertex3f(0.f, 70.f, -50.f);

        glEnd();

        glLoadIdentity();
        glTranslatef(currentPosX, currentPosY, -200.f);
        glRotatef(angle, 0.f, 0.f, 1.f);

        // Line to indicate the direction of the polygon
        glBegin(GL_LINES);

            glVertex3f(0.f, 0.f, -50.f);
            glVertex3f(50.f, 0.f, -50.f);

        glEnd();

        glLoadIdentity();
        glTranslatef(0.f, 0.f, -200.f);

        // Screen axis
        glBegin(GL_LINES);

            glVertex3f(-400.f, 0.f, -60.f);
            glVertex3f(400.f, 0.f, -60.f);

            glVertex3f(0.f, 300.f, -60.f);
            glVertex3f(0.f, -300.f, -60.f);

        glEnd();

        glLoadIdentity();
        glTranslatef(mouseX, mouseY, -200.f);

        // Cursor position
        glBegin(GL_LINES);

            glVertex3f(-10.f, 0.f, -60.f);
            glVertex3f(10.f, 0.f, -60.f);

            glVertex3f(0.f, 10.f, -60.f);
            glVertex3f(0.f, -10.f, -60.f);

        glEnd();

        App.Display();
    }

    return 0;
}
+2  A: 

Input.GetMouse? gives you coords in, say, window-space and you need it to transform them to model-space. I could be wrong, but my lazy fix would be draw my 2D scene in the first quadrant and get mouse position by

(x, y) = (mouse_x, mouse_y) / (window_width, window_height)
         * (viewport_width, viewport_height)

You could always make your coding easier by setting up your projection accordingly to the window's dimensions:

glMatrixMode(GL_PROJECTION);
gluOrtho2D(0, App.GetWidth(), 0, App.GetHeight()); 
erjot