代码之家  ›  专栏  ›  技术社区  ›  chtimy

GLFW鼠标、Linux和OpenGL

  •  1
  • chtimy  · 技术社区  · 9 年前

    我对GLFW和拖动鼠标有问题。该程序无法获得Linux上鼠标的位移。我需要你的帮助,因为在windows上它是有效的。这是软件问题吗?

    代码如下:

    //SEED INCLUDES
    #include <Seed/Graphics/engine/engine.hpp>
    
    Engine::Engine()
    {
        initLog();
    }
    
    Engine::~Engine()
    {
        // Close OpenGL window and terminate GLFW
        glfwTerminate();
        TwTerminate();
    }
    
    void Engine::mainRender(std::shared_ptr<Scene> scene)
    {
        double currentTime = 0, lastTime = 0;
        float deltaTime = 0;
    
        glfwSetCursorPos(window, WIDTH / 2, HEIGHT / 2);
    
        //get all the nodes with a model
        std::stack<ObjectNode*> n;
        std::vector<ObjectNode*> nodes;
        n.push(scene->getRootObjectNode());
        while (!n.empty())
        {
            ObjectNode *n2 = n.top();
            n.pop();
            for (int i = 0; i < n2->getChildren()->size(); i++)
            {
                n.push(n2->getChildren()->at(i));
            }
            if (n2->getModel())
            {
                nodes.push_back(n2);
            }
        }
    
        //glfwWaitEvents();
        //glfwSwapInterval(0.1);
        //glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
    
        //main loop to render
        do
        {
            // Clear the depthbuffer and the colourbuffer
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
            // Black background
            glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
            //get events glfw
            glfwPollEvents();
            //get current time
            currentTime = glfwGetTime();
    
            //update mouse control and keyboard control
            this->controller->updateControl(this->window, scene->getCamera(), deltaTime);
    
            //node->getMaterial()->setLight(a, d, s);
            scene->render(nodes);
            //scene->ShadowMappingRender();
            //scene->SSAOrender();
    
            //Draw anttweakbar
            TwDraw();
            //get current time
            lastTime = glfwGetTime();
    
            //time between 2 frames
            deltaTime = float(lastTime - currentTime);
    
            //on nettoie les buffers
            glfwSwapBuffers(this->window);
    
        } while (glfwGetKey(this->window, GLFW_KEY_ESCAPE) != GLFW_PRESS && glfwWindowShouldClose(this->window) == 0);
    }
    bool Engine::initSystem()
    {
        // Initialise GLFW
        if (!glfwInit())
        {
            std::cout << "Failed to initialize GLFW" << std::endl;
            return false;
        }
        //glfwWindowHint(GLFW_SAMPLES, 4); // 4x antialiasing
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
        glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); //We don't want the old OpenGL
    
        window = glfwCreateWindow(WIDTH, HEIGHT, "Moteur3d", NULL, NULL);
    
        if (window == NULL){
            std::cout << "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n" << std::endl;
            glfwTerminate();
            return false;
        }
        glfwMakeContextCurrent(window); // Initialize GLEW 
        glewExperimental = GL_TRUE; // Needed in core profile 
    
        if (glewInit() != GLEW_OK) {
            std::cout << "Failed to initialize GLEW, version of opengl must be greater or equal than opengl 3.2\n" << std::endl;
            return false;
        }
        return true;
    }
    
    bool Engine::initController()
    {
        this->controller = new Controller(this->window);
        return true;
    }
    
    void TW_CALL CallbackButtonReset(void *clientData)
    {
        SPH::reset = true;
    }
    
    void TW_CALL CallbackButtonNextFrame(void *clientData)
    {
        SPH::nextFrame = true;
    }
    
    void TW_CALL CallbackButtonPlay(void *clientData)
    {
        SPH::play = true;
    }
    
    void TW_CALL CallbackButtonPause(void *clientData)
    {
        SPH::play = false;
    }
    

    控制器:

    //SEED INCLUDES
    #include <Seed/Graphics/engine/control.hpp>
    #include <Seed/Graphics/engine/scene.hpp>
    #include <Seed/Graphics/engine/camera.hpp>
    
    int Controller::context = 0;
    
    Controller::Controller(GLFWwindow *window)
    {
        //captur keys
        glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
        glfwSetMouseButtonCallback(window, mouse_buttonID_callback);
        this->context = 0;
        glfwSetCursorPos(window, WIDTH / 2, HEIGHT / 2);
    }
    
    Controller::~Controller()
    {
    }
    
    
    void Controller::updateControl(GLFWwindow* window, Camera *cam, float deltaTime)
    {
        //position of the camera
        glm::vec3 position = cam->getPosition();
        //horizontal and vertical angle
        float WAngle = cam->getWAngle();
        float HAngle = cam->getHAngle();
        //field of view
        const float initFoV = cam->getInitFoV();
        float near = cam->getNear();
        float far = cam->getFar();
        //speed move direction (keyboard)
        float speed = cam->getSpeed();
        //speed view direction (mouse)
        float mouseSpeed = cam->getMouseSpeed();
    
        float FoV = cam->getInitFoV();
        glm::vec3 direction;
        glm::vec3 up;
    
    
        /*if (glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS)
        {
            Controller::context += 1;
            Controller::context %= 2;
        }*/
    
        double xpos, ypos;
        //get mouse position on the screen
        glfwGetCursorPos(window, &xpos, &ypos);
    
        if (Controller::context == 0)
        {
            //reset position of mouse
            glfwSetCursorPos(window, WIDTH / 2, HEIGHT / 2);
    
            //compute angles
            WAngle += mouseSpeed * float(WIDTH / 2 - xpos);
            HAngle += mouseSpeed * float(HEIGHT / 2 - ypos);
    
            //get direction of the camera
            direction = glm::vec3(cos(HAngle) * sin(WAngle), sin(HAngle), cos(HAngle) * cos(WAngle));
            //get right direction of the camera
            glm::vec3 right(sin(WAngle - 3.14f / 2.0f), 0, cos(WAngle - 3.14f / 2.0f));
            //get the up direction of the camera
            up = glm::normalize(glm::cross(right, direction));
    
            if (glfwGetKey(window, GLFW_KEY_KP_3) == GLFW_PRESS)
            {
                position += direction * speed;
            }
            else if (glfwGetKey(window, GLFW_KEY_KP_1) == GLFW_PRESS)
            {
                position -= direction * speed;
            }
            else if (glfwGetKey(window, GLFW_KEY_KP_6) == GLFW_PRESS)
            {
                position += right * speed;
            }
            else if (glfwGetKey(window, GLFW_KEY_KP_4) == GLFW_PRESS)
            {
                position -= right * speed;
            }
            else if (glfwGetKey(window, GLFW_KEY_KP_8) == GLFW_PRESS)
            {
                position += up * speed;
            }
            else if (glfwGetKey(window, GLFW_KEY_KP_2) == GLFW_PRESS)
            {
                position -= up * speed;
            }
            //set the angle of the direction vector of the camera
            cam->setHAngle(HAngle);
            cam->setWAngle(WAngle);
            //update ViewMatrix
            cam->setViewMatrix(position, direction, up);
            //update Projection Matrix
            cam->setProjectionMatrix(FoV, WIDTH, HEIGHT, near, far);
        }
        else
        {
            //send position of the mouse to anttweakbar
            TwMouseMotion(xpos, ypos);
            if (glfwGetKey(window, GLFW_KEY_KP_0) == GLFW_PRESS)
            {
                TwEventKeyGLFW(GLFW_KEY_KP_0, GLFW_PRESS);
            }
            else if (glfwGetKey(window, GLFW_KEY_KP_1) == GLFW_PRESS)
            {
                TwEventKeyGLFW(GLFW_KEY_KP_1, GLFW_PRESS);
            }
            else if (glfwGetKey(window, GLFW_KEY_KP_2) == GLFW_PRESS)
            {
                TwEventKeyGLFW(GLFW_KEY_KP_2, GLFW_PRESS);
            }
            else if (glfwGetKey(window, GLFW_KEY_KP_3) == GLFW_PRESS)
            {
                TwEventKeyGLFW(GLFW_KEY_KP_3, GLFW_PRESS);
            }
            else if (glfwGetKey(window, GLFW_KEY_KP_4) == GLFW_PRESS)
            {
                TwEventKeyGLFW(GLFW_KEY_KP_4, GLFW_PRESS);
            }
            else if (glfwGetKey(window, GLFW_KEY_KP_5) == GLFW_PRESS)
            {
                TwEventKeyGLFW(GLFW_KEY_KP_5, GLFW_PRESS);
            }
            else if (glfwGetKey(window, GLFW_KEY_KP_6) == GLFW_PRESS)
            {
                TwEventKeyGLFW(GLFW_KEY_KP_6, GLFW_PRESS);
            }
            else if (glfwGetKey(window, GLFW_KEY_KP_7) == GLFW_PRESS)
            {
                TwEventKeyGLFW(GLFW_KEY_KP_7, GLFW_PRESS);
            }
            else if (glfwGetKey(window, GLFW_KEY_KP_8) == GLFW_PRESS)
            {
                TwEventKeyGLFW(GLFW_KEY_KP_8, GLFW_PRESS);
            }
            else if (glfwGetKey(window, GLFW_KEY_KP_9) == GLFW_PRESS)
            {
                TwEventKeyGLFW(GLFW_KEY_KP_9, GLFW_PRESS);
            }
            else if (glfwGetKey(window, GLFW_KEY_KP_ENTER) == GLFW_PRESS)
            {
                TwEventKeyGLFW(GLFW_KEY_KP_ENTER, GLFW_PRESS);
            }
            else if (glfwGetKey(window, GLFW_KEY_DELETE) == GLFW_PRESS)
            {
                TwEventKeyGLFW(GLFW_KEY_DELETE, GLFW_PRESS);
            }
        }
    }
    
    void mouse_buttonID_callback(GLFWwindow* window, int button, int action, int mods)
    {
        //if action is press button
        if (action == GLFW_PRESS)
        {
            //we get the right and left button of the souris to send these to anttweakbar
            switch (button)
            {
                case GLFW_MOUSE_BUTTON_LEFT:
                    TwMouseButton(TW_MOUSE_PRESSED, TW_MOUSE_LEFT);
                    break;
                case GLFW_MOUSE_BUTTON_RIGHT:
                    Controller::context += 1;
                    Controller::context %= 2;
                    //Controller::context = 0;
                    TwMouseButton(TW_MOUSE_PRESSED, TW_MOUSE_RIGHT);
                    break;
            }
        }
        //if user release button we do the same thing that above
        else if (action == GLFW_RELEASE)
        {
            switch (button)
            {
                case GLFW_MOUSE_BUTTON_LEFT:
                    TwMouseButton(TW_MOUSE_RELEASED, TW_MOUSE_LEFT);
                    break;
                case GLFW_MOUSE_BUTTON_RIGHT:
                    //Controller::context = 1;
                    TwMouseButton(TW_MOUSE_RELEASED, TW_MOUSE_RIGHT);
                    break;
            }
        }
    
    }
    
    void Controller::initAntWeakBar(std::string name)
    {
        //initialisation AntWeakBar
        TwInit(TW_OPENGL_CORE, NULL);
    
        //windows size for anttweakbar
        TwWindowSize(WIDTH, HEIGHT);
    
        //initialize bar
        this->bar = TwNewBar(name.c_str());
    }
    
    TwBar* Controller::getBar()
    {
        return this->bar;
    }
    

    你有解决方案吗?

    1 回复  |  直到 9 年前
        1
  •  0
  •   chtimy    9 年前

    好的,与windows的区别在于以下原因: 在Linux上,如果光标已经移动,则必须使用一个条件。

    glfwGetCursorPos(window, &xpos, &ypos);
    if(mouse_moving)
    {update}
    

    在Windows上,只需移动光标的新位置即可,而在Linux上则不行。

    glfwGetCursorPos(window, &xpos, &ypos);
    {update}